day3 (german!) libs
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import mathematik.*;
|
||||
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
/**
|
||||
* this sketch show how to create a particle system with a single particle in it.
|
||||
*/
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Particle mParticle;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system. */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/*
|
||||
* a physic-based particle system consists of a few components.
|
||||
*
|
||||
* 1 particles.
|
||||
* there are different kinds of particles. for now we use a simple particle.
|
||||
*
|
||||
* 2 forces.
|
||||
* there are all kinds of forces. one of the most obvious force is the gravitational force,
|
||||
* but there all kinds of different forces like attractors and springs. forces usually
|
||||
* affect all particles in the system.
|
||||
*
|
||||
* 3 behaviors
|
||||
* a behavior is special kind of force. it is something like an internal force or a motor
|
||||
* that only affects a single particle. a typical force is for example the 'seek force'
|
||||
* which constantly pulls a particle into a certain direction.
|
||||
*
|
||||
* 4 integrators.
|
||||
* integrators are used to integrate acceleration and velocity to calculate the new position.
|
||||
* the most well-known is the 'euler' integrator, but there are also optimized versions like 'runge-kutta'
|
||||
* or 'Midpoint' or even slightly different concepts like 'verlet'.
|
||||
*
|
||||
*/
|
||||
|
||||
/* create a particle. note that the particle is automatically added to particle system */
|
||||
mParticle = mPhysics.makeParticle();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
/* update the particle system to the next step. usually the time step is the duration of the las frame */
|
||||
final float mDeltaTime = 1.0 / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw particle */
|
||||
background(255);
|
||||
stroke(0, 127);
|
||||
fill(0, 32);
|
||||
ellipse(mParticle.position().x, mParticle.position().y, 12, 12);
|
||||
|
||||
/* reset particle s position and velocity */
|
||||
if (mousePressed) {
|
||||
mParticle.position().set(mouseX, mouseY);
|
||||
mParticle.velocity().set(mouseX - pmouseX, mouseY - pmouseY);
|
||||
mParticle.velocity().scale(10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Gravity;
|
||||
|
||||
/**
|
||||
* this sketch show how to create a particle system with a single particle in it.
|
||||
*/
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Particle mParticle;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a gravitational force */
|
||||
Gravity mGravity = new Gravity();
|
||||
/* the direction of the gravity is defined by the 'force' vector */
|
||||
mGravity.force().set(0, 30, 0);
|
||||
/* forces, like gravity or any other force, can be added to the system. they will be automatically applied to all particles */
|
||||
mPhysics.add(mGravity);
|
||||
|
||||
/* create a particle and add it to the system */
|
||||
mParticle = mPhysics.makeParticle();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
/* update the particle system. this applies the gravity to the particle */
|
||||
final float mDeltaTime = 1.0 / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw particle */
|
||||
background(255);
|
||||
stroke(0, 127);
|
||||
fill(0, 32);
|
||||
ellipse(mParticle.position().x, mParticle.position().y, 12, 12);
|
||||
|
||||
/* reset particle s position and velocity */
|
||||
if (mousePressed) {
|
||||
mParticle.position().set(mouseX, mouseY);
|
||||
mParticle.velocity().set(mouseX - pmouseX, mouseY - pmouseY);
|
||||
mParticle.velocity().scale(10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Gravity;
|
||||
|
||||
/**
|
||||
* this sketch shows how to create and handle multiple particles and remove individual particles.
|
||||
*/
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a gravitational force and add it to the particle system */
|
||||
Gravity myGravity = new Gravity(0, 30, 0);
|
||||
mPhysics.add(myGravity);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
if (mousePressed) {
|
||||
/* create and add a particle to the system */
|
||||
Particle mParticle = mPhysics.makeParticle();
|
||||
/* set particle to mouse position with random velocity */
|
||||
mParticle.position().set(mouseX, mouseY);
|
||||
mParticle.velocity().set(random(-20, 20), random(-50));
|
||||
}
|
||||
|
||||
/* update the particle system */
|
||||
final float mDeltaTime = 1.0 / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* remove particles right before they hit the edge of the screen */
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
Particle mParticle = mPhysics.particles(i);
|
||||
if (mParticle.position().y > height * 0.9f) {
|
||||
mPhysics.particles().remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw all the particles in the system */
|
||||
background(255);
|
||||
stroke(0, 127);
|
||||
fill(0, 32);
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
Particle mParticle = mPhysics.particles(i);
|
||||
ellipse(mParticle.position().x, mParticle.position().y, 10, 10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.Teleporter;
|
||||
import teilchen.force.Attractor;
|
||||
import teilchen.force.ViscousDrag;
|
||||
|
||||
/**
|
||||
* this sketch shows how to create and use attractors.
|
||||
*/
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Attractor mAttractor;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a viscous force that slows down all motion */
|
||||
ViscousDrag myDrag = new ViscousDrag();
|
||||
myDrag.coefficient = 0.75f;
|
||||
mPhysics.add(myDrag);
|
||||
|
||||
/* teleport particles from one edge of the screen to the other */
|
||||
Teleporter mTeleporter = new Teleporter();
|
||||
mTeleporter.min().set(0, 0);
|
||||
mTeleporter.max().set(width, height);
|
||||
mPhysics.add(mTeleporter);
|
||||
|
||||
/* create some particles */
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Particle myParticle = mPhysics.makeParticle();
|
||||
myParticle.position().set(random(width), random(height));
|
||||
}
|
||||
|
||||
/* create an attractor */
|
||||
mAttractor = new Attractor();
|
||||
mAttractor.radius(100);
|
||||
mAttractor.strength(150);
|
||||
mPhysics.add(mAttractor);
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
/* flip the direction of the attractors strength. */
|
||||
float myInvertedStrength = -1 * mAttractor.strength();
|
||||
/* a negative strength turns the attractor into a repulsor */
|
||||
mAttractor.strength(myInvertedStrength);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
/* set attractor to mouse position */
|
||||
mAttractor.position().set(mouseX, mouseY);
|
||||
|
||||
/* update the particle system */
|
||||
final float mDeltaTime = 1.0 / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw */
|
||||
background(255);
|
||||
|
||||
/* draw all the particles in particle system */
|
||||
fill(245);
|
||||
stroke(164);
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
Particle myParticle = mPhysics.particles(i);
|
||||
ellipse(myParticle.position().x, myParticle.position().y, 12, 12);
|
||||
}
|
||||
|
||||
/* draw attractor. green if it is attracting and red if it is repelling */
|
||||
noStroke();
|
||||
if (mAttractor.strength() < 0) {
|
||||
fill(255, 0, 0, 50);
|
||||
}
|
||||
else {
|
||||
fill(0, 255, 0, 50);
|
||||
}
|
||||
ellipse(mAttractor.position().x, mAttractor.position().y,
|
||||
mAttractor.radius(), mAttractor.radius());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.ShortLivedParticle;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.PlaneDeflector;
|
||||
import teilchen.force.ViscousDrag;
|
||||
|
||||
/**
|
||||
* this sketch shows
|
||||
* 1 how to create and use plane deflectors
|
||||
* 2 how to use 'ShortLivedParticle'
|
||||
*/
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
PlaneDeflector mDeflector;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a deflector and add it to the particle system.
|
||||
* the that defines the deflection area is defined by an
|
||||
* origin and a normal. this also means that the plane s size
|
||||
* is infinite.
|
||||
* note that there is also a triangle delfector that is constraint
|
||||
* by three points.
|
||||
*/
|
||||
mDeflector = new PlaneDeflector();
|
||||
/* set plane origin into the center of the screen */
|
||||
mDeflector.plane().origin.set(width / 2, height / 2, 0);
|
||||
mDeflector.plane().normal.set(0, -1, 0);
|
||||
/* the coefficient of restitution defines how hard particles bounce of the deflector */
|
||||
mDeflector.coefficientofrestitution(0.7f);
|
||||
mPhysics.add(mDeflector);
|
||||
|
||||
/* create gravitiy */
|
||||
Gravity myGravity = new Gravity();
|
||||
myGravity.force().y = 50;
|
||||
mPhysics.add(myGravity);
|
||||
|
||||
/* create drag */
|
||||
ViscousDrag myViscousDrag = new ViscousDrag();
|
||||
myViscousDrag.coefficient = 0.1f;
|
||||
mPhysics.add(myViscousDrag);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
/* rotate deflector plane */
|
||||
if (mousePressed) {
|
||||
final float myAngle = 2 * PI * (float)mouseX / width - PI;
|
||||
mDeflector.plane().normal.set(sin(myAngle), -cos(myAngle), 0);
|
||||
}
|
||||
|
||||
/* create a special particle */
|
||||
ShortLivedParticle myNewParticle = new ShortLivedParticle();
|
||||
myNewParticle.position().set(mouseX, mouseY);
|
||||
myNewParticle.velocity().set(0, random(100) + 50);
|
||||
/* this particle is removed after a specific interval */
|
||||
myNewParticle.setMaxAge(4);
|
||||
/* add particle manually to the particle system */
|
||||
mPhysics.add(myNewParticle);
|
||||
|
||||
/* update physics */
|
||||
final float mDeltaTime = 1.0 / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw all the particles in the particle system */
|
||||
background(255);
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
Particle myParticle = mPhysics.particles(i);
|
||||
/* this special particle can tell you how much time it has to live.
|
||||
* we map this information to its transparency.
|
||||
*/
|
||||
float myRatio = 1 - ((ShortLivedParticle)myParticle).ageRatio();
|
||||
stroke(0, 64 * myRatio);
|
||||
fill(0, 32 * myRatio);
|
||||
ellipse(myParticle.position().x, myParticle.position().y, 12, 12);
|
||||
}
|
||||
|
||||
/* draw deflector */
|
||||
stroke(0, 127);
|
||||
line(mDeflector.plane().origin.x - mDeflector.plane().normal.y * -width,
|
||||
mDeflector.plane().origin.y + mDeflector.plane().normal.x * -width,
|
||||
mDeflector.plane().origin.x - mDeflector.plane().normal.y * width,
|
||||
mDeflector.plane().origin.y + mDeflector.plane().normal.x * width);
|
||||
|
||||
stroke(255, 0, 0, 127);
|
||||
line(mDeflector.plane().origin.x,
|
||||
mDeflector.plane().origin.y,
|
||||
mDeflector.plane().origin.x + mDeflector.plane().normal.x * 20,
|
||||
mDeflector.plane().origin.y + mDeflector.plane().normal.y * 20);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
|
||||
/**
|
||||
* this sketch shows
|
||||
* 1 how to create a viscous drag to slow motion eventually down.
|
||||
* 2 how to create a spring that connects two particles.
|
||||
*/
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Spring mSpring;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a viscous force that slows down all motion; 0 means no slowing down. */
|
||||
ViscousDrag myDrag = new ViscousDrag(0.25f);
|
||||
mPhysics.add(myDrag);
|
||||
|
||||
/* create two particles that we can connect with a spring */
|
||||
Particle myA = mPhysics.makeParticle();
|
||||
myA.position().set(width / 2 - 50, height / 2);
|
||||
|
||||
Particle myB = mPhysics.makeParticle();
|
||||
myB.position().set(width / 2 + 50, height / 2);
|
||||
|
||||
/* create a spring force that connects two particles.
|
||||
* note that there is more than one way to create a spring.
|
||||
* in our case the restlength of the spring is defined by the
|
||||
* particles current position.
|
||||
*/
|
||||
mSpring = mPhysics.makeSpring(myA, myB);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
/* set first particle to mouse position */
|
||||
if (mousePressed) {
|
||||
mSpring.a().position().set(mouseX, mouseY);
|
||||
}
|
||||
|
||||
/* update the particle system */
|
||||
final float mDeltaTime = 1.0 / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw particles and connecting line */
|
||||
background(255);
|
||||
noFill();
|
||||
stroke(255, 0, 127, 64);
|
||||
line(mSpring.a().position().x, mSpring.a().position().y,
|
||||
mSpring.b().position().x, mSpring.b().position().y);
|
||||
fill(245);
|
||||
stroke(164);
|
||||
ellipse(mSpring.a().position().x, mSpring.a().position().y, 12, 12);
|
||||
ellipse(mSpring.b().position().x, mSpring.b().position().y, 12, 12);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Spring;
|
||||
|
||||
/**
|
||||
* this sketch shows
|
||||
* 1 how to create a viscous drag to slow motion eventually down.
|
||||
* 2 how to create a spring that connects two particles.
|
||||
*/
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Particle mRoot;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a particle to which we will connect springs */
|
||||
mRoot = mPhysics.makeParticle(width / 2, height / 2, 0.0);
|
||||
/* we give the root particle a higher mass so it doesn t move as easily */
|
||||
mRoot.mass(30);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
/* create a particle at mouse position and connect it to the root particle through a spring */
|
||||
if (mousePressed) {
|
||||
Particle mParticle = mPhysics.makeParticle(mouseX, mouseY, 0);
|
||||
Spring mSpring = mPhysics.makeSpring(mRoot, mParticle);
|
||||
/* restlength defines the desired length of the spring. in this case it is the distance between the two particles. */
|
||||
float mRestlength = mSpring.restlength();
|
||||
/* we modify the restlength to add a bit of energy into the system */
|
||||
mSpring.restlength(mRestlength * 1.5f);
|
||||
}
|
||||
|
||||
/* update the particle system */
|
||||
final float mDeltaTime = 1.0 / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw particles and connecting line */
|
||||
background(255);
|
||||
|
||||
/* draw springs */
|
||||
noFill();
|
||||
stroke(255, 0, 127, 64);
|
||||
for (int i = 0; i < mPhysics.forces().size(); i++) {
|
||||
if (mPhysics.forces().get(i) instanceof Spring) {
|
||||
Spring mSSpring = (Spring)mPhysics.forces().get(i);
|
||||
line(mSSpring.a().position().x, mSSpring.a().position().y,
|
||||
mSSpring.b().position().x, mSSpring.b().position().y);
|
||||
}
|
||||
}
|
||||
/* draw particles */
|
||||
fill(245);
|
||||
stroke(164);
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
ellipse(mPhysics.particles().get(i).position().x,
|
||||
mPhysics.particles().get(i).position().y,
|
||||
12, 12);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.util.DrawLib;
|
||||
import teilchen.Particle;
|
||||
import teilchen.constraint.Box;
|
||||
import teilchen.integration.RungeKutta;
|
||||
import teilchen.util.StableSpringQuad;
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Particle mRoot;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(60);
|
||||
|
||||
mPhysics = new Physics();
|
||||
/* we use 'runge kutta' as it is more stable for this application */
|
||||
mPhysics.setInegratorRef(new RungeKutta());
|
||||
|
||||
Gravity myGravity = new Gravity();
|
||||
myGravity.force().y = 98.1f;
|
||||
mPhysics.add(myGravity);
|
||||
|
||||
/* add drag to smooth the spring interaction */
|
||||
mPhysics.add(new ViscousDrag(0.2f));
|
||||
|
||||
/* add a container */
|
||||
Box myBox = new Box();
|
||||
myBox.min().set(0, 0, 0);
|
||||
myBox.max().set(width, height, 0);
|
||||
mPhysics.add(myBox);
|
||||
|
||||
/* create root */
|
||||
Particle a = mPhysics.makeParticle(0, 0);
|
||||
Particle b = mPhysics.makeParticle(100, 0);
|
||||
Particle c = mPhysics.makeParticle(100, 100);
|
||||
Particle d = mPhysics.makeParticle(0, 100);
|
||||
|
||||
new StableSpringQuad(mPhysics, d, c, mPhysics.makeParticle(100, 200), mPhysics.makeParticle(0, 200));
|
||||
|
||||
/* create stable quad from springs */
|
||||
/* first the edge-springs ... */
|
||||
final float mySpringConstant = 100;
|
||||
final float mySpringDamping = 5;
|
||||
mPhysics.makeSpring(a, b, mySpringConstant, mySpringDamping);
|
||||
mPhysics.makeSpring(b, c, mySpringConstant, mySpringDamping);
|
||||
mPhysics.makeSpring(c, d, mySpringConstant, mySpringDamping);
|
||||
mPhysics.makeSpring(d, a, mySpringConstant, mySpringDamping).restlength();
|
||||
/* ... then the diagonal-springs */
|
||||
mPhysics.makeSpring(a, c, mySpringConstant, mySpringDamping);
|
||||
mPhysics.makeSpring(b, d, mySpringConstant, mySpringDamping).restlength();
|
||||
|
||||
/* define 'a' as root particle for mouse interaction */
|
||||
mRoot = a;
|
||||
mRoot.fixed(true);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
/* handle particles */
|
||||
if (mousePressed) {
|
||||
mRoot.fixed(true);
|
||||
mRoot.position().set(mouseX, mouseY);
|
||||
}
|
||||
else {
|
||||
mRoot.fixed(false);
|
||||
}
|
||||
|
||||
mPhysics.step(1f / frameRate);
|
||||
|
||||
/* draw */
|
||||
background(255);
|
||||
DrawLib.drawSprings(g, mPhysics, color(255, 0, 127, 64));
|
||||
DrawLib.drawParticles(g, mPhysics, 12, color(164), color(245));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.Stick;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.integration.Verlet;
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Particle[] mParticles;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
frameRate(60);
|
||||
smooth();
|
||||
|
||||
mPhysics = new Physics();
|
||||
/* increase the number of iterations for contraints in each step. this can greatly relaxes tensions in the system. */
|
||||
mPhysics.contraint_iterations_per_steps = 5;
|
||||
|
||||
/* add gravity for extra fun */
|
||||
mPhysics.add(new Gravity());
|
||||
|
||||
/* we chose verlet integration as it integrates much more nicely with sticks ( and constraints in general ) */
|
||||
Verlet myVerlet = new Verlet();
|
||||
myVerlet.damping(0.99f);
|
||||
mPhysics.setInegratorRef(myVerlet);
|
||||
|
||||
/* setup sticks to form a whip */
|
||||
mParticles = new Particle[16];
|
||||
float mSegmentLength = 20.0;
|
||||
/* create root */
|
||||
for (int x = 0; x < mParticles.length; x++) {
|
||||
mParticles[x] = mPhysics.makeParticle(x * mSegmentLength, 0, 0, 0.1f);
|
||||
if (x > 0) {
|
||||
Stick myStick = new Stick(mParticles[x - 1],
|
||||
mParticles[x],
|
||||
mSegmentLength);
|
||||
/* damp the stick to release tensions from the system */
|
||||
myStick.damping(0.99f);
|
||||
mPhysics.add(myStick);
|
||||
}
|
||||
}
|
||||
|
||||
/* fix root particle so it can stick to the mouse later */
|
||||
mParticles[0].fixed(true);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
/* stick root particle to mouse */
|
||||
mParticles[0].position().set(mouseX, mouseY);
|
||||
|
||||
/* update */
|
||||
mPhysics.step(1.0 / frameRate);
|
||||
|
||||
/* draw sticks with descending stroke weight */
|
||||
background(255);
|
||||
stroke(0, 192);
|
||||
for (int x = 1; x < mParticles.length; x++) {
|
||||
Particle p1 = mParticles[x - 1];
|
||||
Particle p2 = mParticles[x];
|
||||
final float mStrokeWeight = 4.0 * (1.0 - (float)x / mParticles.length);
|
||||
strokeWeight(mStrokeWeight);
|
||||
line(p1.position().x, p1.position().y, p1.position().z,
|
||||
p2.position().x, p2.position().y, p2.position().z);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.IConstraint;
|
||||
import teilchen.constraint.Stick;
|
||||
import teilchen.force.Attractor;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.integration.Verlet;
|
||||
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Particle[][] mParticles;
|
||||
|
||||
final int GRID_WIDTH = 32;
|
||||
|
||||
final int GRID_HEIGHT = 16;
|
||||
|
||||
Attractor mAttractor;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
frameRate(60);
|
||||
|
||||
mPhysics = new Physics();
|
||||
mPhysics.contraint_iterations_per_steps = 5;
|
||||
|
||||
Verlet myVerlet = new Verlet();
|
||||
myVerlet.damping(0.9f);
|
||||
mPhysics.setInegratorRef(myVerlet);
|
||||
mPhysics.add(new Gravity(new Vector3f(0, 1000f, 0)));
|
||||
|
||||
mAttractor = new Attractor();
|
||||
mAttractor.strength(-15000);
|
||||
mAttractor.radius(300);
|
||||
mPhysics.add(mAttractor);
|
||||
|
||||
mParticles = new Particle[GRID_WIDTH][GRID_HEIGHT];
|
||||
|
||||
/* setup cloth */
|
||||
float mGridStepX = ((float)width / GRID_WIDTH);
|
||||
float mGridStepY = (((float)height * 0.5f) / GRID_HEIGHT);
|
||||
for (int y = 0; y < GRID_HEIGHT; y++) {
|
||||
for (int x = 0; x < GRID_WIDTH; x++) {
|
||||
mParticles[x][y] = mPhysics.makeParticle();
|
||||
mParticles[x][y].position().set((x + 0.5f) * mGridStepX,
|
||||
y * mGridStepY,
|
||||
random(0, 1));
|
||||
mParticles[x][y].old_position().set(mParticles[x][y].position());
|
||||
mParticles[x][y].mass(0.1f);
|
||||
|
||||
final float DAMPING = 0.9f;
|
||||
if (y > 0) {
|
||||
Stick myStick = new Stick(mParticles[x][y - 1],
|
||||
mParticles[x][y],
|
||||
mGridStepY);
|
||||
myStick.damping(DAMPING);
|
||||
mPhysics.add(myStick);
|
||||
}
|
||||
if (x > 0) {
|
||||
Stick myStick = new Stick(mParticles[x - 1][y],
|
||||
mParticles[x][y],
|
||||
mGridStepX);
|
||||
myStick.damping(DAMPING);
|
||||
mPhysics.add(myStick);
|
||||
}
|
||||
if (x > 0 && y > 0) {
|
||||
Stick myStick1 = new Stick(mParticles[x - 1][y - 1],
|
||||
mParticles[x][y],
|
||||
new Vector3f(mGridStepX, mGridStepY).length());
|
||||
mPhysics.add(myStick1);
|
||||
Stick myStick2 = new Stick(mParticles[x][y - 1],
|
||||
mParticles[x - 1][y],
|
||||
new Vector3f(mGridStepX, mGridStepY).length());
|
||||
mPhysics.add(myStick2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fix first row */
|
||||
for (int x = 0; x < mParticles.length; x++) {
|
||||
mParticles[x][0].fixed(true);
|
||||
}
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
/* update */
|
||||
mAttractor.position().set(mouseX, mouseY, 50);
|
||||
mPhysics.step(1.0 / frameRate);
|
||||
|
||||
background(255);
|
||||
|
||||
/* draw sticks */
|
||||
stroke(0, 127);
|
||||
|
||||
for (int i = 0; i < mPhysics.constraints().size(); i++) {
|
||||
IConstraint mConstraint = mPhysics.constraints().get(i);
|
||||
if (mConstraint instanceof Stick) {
|
||||
final Stick myStick = (Stick)mConstraint;
|
||||
line(myStick.a().position().x,
|
||||
myStick.a().position().y,
|
||||
myStick.a().position().z,
|
||||
myStick.b().position().x,
|
||||
myStick.b().position().y,
|
||||
myStick.b().position().z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.BehaviorParticle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.behavior.Arrival;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch shows how to assign an 'arrival' behavior to a particle.
|
||||
*/
|
||||
Physics mPhysics;
|
||||
|
||||
BehaviorParticle mParticle;
|
||||
|
||||
Arrival mArrival;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(120);
|
||||
colorMode(RGB, 1.0f);
|
||||
noFill();
|
||||
|
||||
/* physics */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create particles */
|
||||
mParticle = mPhysics.makeParticle(BehaviorParticle.class);
|
||||
mParticle.maximumInnerForce(100);
|
||||
|
||||
/* create arrival behavior */
|
||||
mArrival = new Arrival();
|
||||
mArrival.breakforce(mParticle.maximumInnerForce() * 0.25f);
|
||||
mArrival.breakradius(mParticle.maximumInnerForce() * 0.25f);
|
||||
mParticle.behaviors().add(mArrival);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
/* set the arrival position to the mouse position */
|
||||
mArrival.position().set(mouseX, mouseY);
|
||||
|
||||
/* update particle system */
|
||||
mPhysics.step(1.0f / frameRate);
|
||||
|
||||
/* draw behavior particle */
|
||||
background(1);
|
||||
stroke(0, 0.5f);
|
||||
if (mArrival.arriving()) {
|
||||
/* color particle red while it is arriving */
|
||||
stroke(1, 0, 0, 0.5f);
|
||||
}
|
||||
if (mArrival.arrived()) {
|
||||
/* color particle green when it has arrived */
|
||||
stroke(0, 1, 0, 0.5f);
|
||||
}
|
||||
|
||||
line(mParticle.position().x,
|
||||
mParticle.position().y,
|
||||
mParticle.position().x + mParticle.velocity().x,
|
||||
mParticle.position().y + mParticle.velocity().y);
|
||||
fill(1);
|
||||
ellipse(mParticle.position().x, mParticle.position().y, 12, 12);
|
||||
|
||||
/* draw arrival */
|
||||
stroke(0, 0.25f);
|
||||
noFill();
|
||||
ellipse(mArrival.position().x,
|
||||
mArrival.position().y,
|
||||
mArrival.breakradius() * 2,
|
||||
mArrival.breakradius() * 2);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import processing.opengl.*;
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.util.Overlap;
|
||||
|
||||
/**
|
||||
* this sketch is exactly like Lesson06_Springs, except that it also shows how to remove overlaps.
|
||||
*/
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Particle mRoot;
|
||||
|
||||
static final float PARTICLE_RADIUS = 6;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
mPhysics = new Physics();
|
||||
mRoot = mPhysics.makeParticle(width / 2, height / 2, 0.0);
|
||||
mRoot.mass(30);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
if (mousePressed) {
|
||||
Particle mParticle = mPhysics.makeParticle(mouseX, mouseY, 0);
|
||||
Spring mSpring = mPhysics.makeSpring(mRoot, mParticle);
|
||||
float mRestlength = mSpring.restlength();
|
||||
mSpring.restlength(mRestlength * 1.5f);
|
||||
|
||||
/* we define a radius for the particle so the particle has dimensions */
|
||||
mParticle.radius(PARTICLE_RADIUS);
|
||||
}
|
||||
|
||||
/* move overlapping particles away from each other */
|
||||
Overlap.resolveOverlap(mPhysics.particles());
|
||||
|
||||
/* update the particle system */
|
||||
final float mDeltaTime = 1.0 / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw particles and connecting line */
|
||||
background(255);
|
||||
|
||||
/* draw springs */
|
||||
noFill();
|
||||
stroke(255, 0, 127, 64);
|
||||
for (int i = 0; i < mPhysics.forces().size(); i++) {
|
||||
if (mPhysics.forces().get(i) instanceof Spring) {
|
||||
Spring mSSpring = (Spring)mPhysics.forces().get(i);
|
||||
line(mSSpring.a().position().x, mSSpring.a().position().y,
|
||||
mSSpring.b().position().x, mSSpring.b().position().y);
|
||||
}
|
||||
}
|
||||
/* draw particles */
|
||||
fill(245);
|
||||
stroke(164);
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
ellipse(mPhysics.particles().get(i).position().x,
|
||||
mPhysics.particles().get(i).position().y,
|
||||
PARTICLE_RADIUS * 2, PARTICLE_RADIUS * 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
import processing.opengl.*;
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.Box;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.util.CollisionManager;
|
||||
|
||||
static final float PARTICLE_SIZE = 12;
|
||||
|
||||
CollisionManager mCollision;
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
noFill();
|
||||
ellipseMode(CENTER);
|
||||
|
||||
mCollision = new CollisionManager();
|
||||
mCollision.distancemode(CollisionManager.DISTANCE_MODE_FIXED);
|
||||
mCollision.minimumDistance(50);
|
||||
|
||||
mPhysics = new Physics();
|
||||
mPhysics.add(new ViscousDrag(0.85f));
|
||||
mPhysics.add(new Gravity());
|
||||
|
||||
Box myBox = new Box();
|
||||
myBox.min().set(50, 50, 0);
|
||||
myBox.max().set(width - 50, height - 50, 0);
|
||||
myBox.coefficientofrestitution(0.7f);
|
||||
myBox.reflect(true);
|
||||
mPhysics.add(myBox);
|
||||
|
||||
/* create a first particle */
|
||||
final Particle myParticle = mPhysics.makeParticle(new Vector3f(mouseX, mouseY, 0), 10);
|
||||
mCollision.collision().add(myParticle);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
/* create particles */
|
||||
if (mousePressed) {
|
||||
final Particle myParticle = mPhysics.makeParticle(new Vector3f(mouseX, mouseY, 0), 10);
|
||||
mCollision.collision().add(myParticle);
|
||||
}
|
||||
|
||||
/* collision handler */
|
||||
final float mDeltaTime = 1.0 / frameRate;
|
||||
mCollision.createCollisionResolvers();
|
||||
mCollision.loop(mDeltaTime);
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw */
|
||||
background(255);
|
||||
drawThings();
|
||||
|
||||
mCollision.removeCollisionResolver();
|
||||
}
|
||||
|
||||
void drawThings() {
|
||||
/* collision springs */
|
||||
noFill();
|
||||
stroke(255, 0, 127, 64);
|
||||
for (int i = 0; i < mCollision.collision().forces().size(); ++i) {
|
||||
if (mCollision.collision().forces().get(i) instanceof Spring) {
|
||||
Spring mySpring = (Spring)mCollision.collision_forces().get(i);
|
||||
line(mySpring.a().position().x, mySpring.a().position().y, mySpring.a().position().z,
|
||||
mySpring.b().position().x, mySpring.b().position().y, mySpring.b().position().z);
|
||||
}
|
||||
}
|
||||
|
||||
/* particles */
|
||||
fill(245);
|
||||
stroke(164);
|
||||
for (int i = 0; i < mPhysics.particles().size(); ++i) {
|
||||
Particle myParticle = mPhysics.particles().get(i);
|
||||
pushMatrix();
|
||||
translate(myParticle.position().x, myParticle.position().y, myParticle.position().z);
|
||||
ellipse(0, 0,
|
||||
PARTICLE_SIZE,
|
||||
PARTICLE_SIZE);
|
||||
popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+131
@@ -0,0 +1,131 @@
|
||||
import mathematik.Vector3f;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.ShortLivedParticle;
|
||||
import teilchen.constraint.Box;
|
||||
import teilchen.force.Attractor;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.util.ParticleTrail;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Vector<ParticleTrail> mTrails;
|
||||
|
||||
Attractor mAttractor;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(60);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a gravitational force */
|
||||
Gravity myGravity = new Gravity();
|
||||
mPhysics.add(myGravity);
|
||||
myGravity.force().y = 20;
|
||||
|
||||
/* create drag */
|
||||
ViscousDrag myViscousDrag = new ViscousDrag();
|
||||
myViscousDrag.coefficient = 0.1f;
|
||||
mPhysics.add(myViscousDrag);
|
||||
|
||||
final float mBorder = 40;
|
||||
Box mBox = new Box(new Vector3f(mBorder, mBorder, mBorder), new Vector3f(width - mBorder, height - mBorder, 100 - mBorder));
|
||||
mBox.reflect(true);
|
||||
mPhysics.add(mBox);
|
||||
|
||||
/* create an attractor */
|
||||
mAttractor = new Attractor();
|
||||
mAttractor.radius(200);
|
||||
mAttractor.strength(-300);
|
||||
mPhysics.add(mAttractor);
|
||||
|
||||
|
||||
/* create trails and particles */
|
||||
mTrails = new Vector<ParticleTrail>();
|
||||
for (int i = 0; i < 500; i++) {
|
||||
Particle mParticle = mPhysics.makeParticle();
|
||||
mParticle.mass(2.0f);
|
||||
ParticleTrail myParticleTrail = new ParticleTrail(mPhysics, mParticle, 0.2f, random(0.5f, 1));
|
||||
myParticleTrail.mass(0.5f);
|
||||
mTrails.add(myParticleTrail);
|
||||
}
|
||||
resetParticles(width / 2, height / 2);
|
||||
}
|
||||
|
||||
void resetParticles(float x, float y) {
|
||||
for (ParticleTrail myTrails : mTrails) {
|
||||
myTrails.particle().position().set(x + random(-10, 10), y + random(-10, 10), 0);
|
||||
myTrails.particle().velocity().set(random(-10, 10), random(-10, 10), random(-10, 10));
|
||||
myTrails.fragments().clear();
|
||||
}
|
||||
}
|
||||
|
||||
void draw() {
|
||||
/* set attractor to mouse position */
|
||||
mAttractor.position().set(mouseX, mouseY);
|
||||
|
||||
for (ParticleTrail myTrails : mTrails) {
|
||||
myTrails.loop(1f / frameRate);
|
||||
}
|
||||
|
||||
mPhysics.step(1f / frameRate);
|
||||
|
||||
background(255);
|
||||
for (ParticleTrail myTrail : mTrails) {
|
||||
drawTrail(myTrail);
|
||||
}
|
||||
}
|
||||
|
||||
void drawTrail(ParticleTrail theTrail) {
|
||||
|
||||
final Vector<Particle> mFragments = theTrail.fragments();
|
||||
final Particle mParticle = theTrail.particle();
|
||||
|
||||
/* draw head */
|
||||
if (mFragments.size() > 1) {
|
||||
fill(255, 0, 127);
|
||||
noStroke();
|
||||
pushMatrix();
|
||||
translate(mParticle.position().x,
|
||||
mParticle.position().y,
|
||||
mParticle.position().z);
|
||||
sphereDetail(4);
|
||||
sphere(3);
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
/* draw trail */
|
||||
for (int i = 0; i < mFragments.size() - 1; i++) {
|
||||
if (mFragments.get(i) instanceof ShortLivedParticle) {
|
||||
final float mRatio = 1.0f - ((ShortLivedParticle)mFragments.get(i)).ageRatio();
|
||||
stroke(127, mRatio * 255);
|
||||
strokeWeight(mRatio * 3);
|
||||
}
|
||||
int j = (i + 1) % mFragments.size();
|
||||
line(mFragments.get(i).position().x,
|
||||
mFragments.get(i).position().y,
|
||||
mFragments.get(i).position().z,
|
||||
mFragments.get(j).position().x,
|
||||
mFragments.get(j).position().y,
|
||||
mFragments.get(j).position().z);
|
||||
}
|
||||
if (!mFragments.isEmpty()) {
|
||||
line(mFragments.lastElement().position().x,
|
||||
mFragments.lastElement().position().y,
|
||||
mFragments.lastElement().position().z,
|
||||
mParticle.position().x,
|
||||
mParticle.position().y,
|
||||
mParticle.position().z);
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
resetParticles(mouseX, mouseY);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.test.cubicle.*;
|
||||
import teilchen.integration.*;
|
||||
import verhalten.*;
|
||||
import teilchen.*;
|
||||
import verhalten.view.*;
|
||||
import teilchen.test.particle.behavior.*;
|
||||
import teilchen.behavior.*;
|
||||
import teilchen.demo.*;
|
||||
import teilchen.test.particle.springs.*;
|
||||
import teilchen.gestalt.test.*;
|
||||
import teilchen.cubicle.*;
|
||||
import verhalten.test.*;
|
||||
import teilchen.force.flowfield.*;
|
||||
import teilchen.test.particle.*;
|
||||
import teilchen.gestalt.util.*;
|
||||
import teilchen.constraint.*;
|
||||
import teilchen.force.vectorfield.*;
|
||||
import teilchen.force.*;
|
||||
import teilchen.util.*;
|
||||
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Attractor;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.integration.RungeKutta;
|
||||
import teilchen.util.Overlap;
|
||||
import teilchen.util.StickMan;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* this demo shows some advanced use of particles, springs and attractors to create stickmen.
|
||||
*/
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Attractor mAttractor;
|
||||
|
||||
Gravity mGravity;
|
||||
|
||||
ViscousDrag mViscousDrag;
|
||||
|
||||
StickMan[] mMyStickMan;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(60);
|
||||
noFill();
|
||||
|
||||
mPhysics = new Physics();
|
||||
mPhysics.setInegratorRef(new RungeKutta());
|
||||
|
||||
mGravity = new Gravity();
|
||||
mGravity.force().y = 20;
|
||||
mPhysics.add(mGravity);
|
||||
|
||||
mViscousDrag = new ViscousDrag();
|
||||
mViscousDrag.coefficient = 0.85f;
|
||||
mPhysics.add(mViscousDrag);
|
||||
|
||||
mAttractor = new Attractor();
|
||||
mAttractor.radius(500);
|
||||
mAttractor.strength(0);
|
||||
mAttractor.position().set(width / 2, height / 2);
|
||||
mPhysics.add(mAttractor);
|
||||
|
||||
mMyStickMan = new StickMan[20];
|
||||
for (int i = 0; i < mMyStickMan.length; i++) {
|
||||
mMyStickMan[i] = new StickMan(mPhysics, random(0, width), random(0.3f, 0.6f));
|
||||
}
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
mPhysics.step(1f / 60f);
|
||||
Overlap.resolveOverlap(mPhysics.particles());
|
||||
|
||||
/* constraint particles */
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
if (mPhysics.particles(i).position().y > height - 10) {
|
||||
mPhysics.particles(i).position().y = height - 10;
|
||||
}
|
||||
if (mPhysics.particles(i).position().x > width) {
|
||||
mPhysics.particles(i).position().x = width;
|
||||
}
|
||||
if (mPhysics.particles(i).position().x < 0) {
|
||||
mPhysics.particles(i).position().x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle particles */
|
||||
if (mousePressed) {
|
||||
mAttractor.position().set(mouseX, mouseY);
|
||||
if (mouseButton == RIGHT) {
|
||||
mAttractor.strength(-500);
|
||||
mAttractor.radius(500);
|
||||
}
|
||||
else {
|
||||
mAttractor.strength(500);
|
||||
mAttractor.radius(100);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mAttractor.strength(0);
|
||||
}
|
||||
|
||||
if (keyPressed) {
|
||||
mGravity.force().y = -10;
|
||||
}
|
||||
else {
|
||||
mGravity.force().y = 20;
|
||||
}
|
||||
|
||||
/* draw */
|
||||
background(255);
|
||||
|
||||
/* draw springs */
|
||||
stroke(0, 20);
|
||||
for (int i = 0; i < mPhysics.forces().size(); i++) {
|
||||
if (mPhysics.forces(i) instanceof Spring) {
|
||||
Spring mySpring = (Spring)mPhysics.forces(i);
|
||||
line(mySpring.a().position().x,
|
||||
mySpring.a().position().y,
|
||||
mySpring.b().position().x,
|
||||
mySpring.b().position().y);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw particles */
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
ellipse(mPhysics.particles(i).position().x,
|
||||
mPhysics.particles(i).position().y, 5, 5);
|
||||
}
|
||||
|
||||
/* draw man */
|
||||
for (int i = 0; i < mMyStickMan.length; i++) {
|
||||
mMyStickMan[i].draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
import mathematik.*;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.AngleConstraintStick;
|
||||
import teilchen.constraint.Stick;
|
||||
import teilchen.force.AngleConstraintSpring;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.integration.RungeKutta;
|
||||
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
Particle mParticleA;
|
||||
|
||||
Particle mParticleB;
|
||||
|
||||
Particle mParticleC;
|
||||
|
||||
Particle mParticleD;
|
||||
|
||||
AngleConstraintSpring mAngleConstraintABC;
|
||||
|
||||
AngleConstraintStick mAngleConstraintBCD;
|
||||
|
||||
void setup() {
|
||||
size(640, 480);
|
||||
frameRate(30);
|
||||
smooth();
|
||||
|
||||
mPhysics = new Physics();
|
||||
mPhysics.setInegratorRef(new RungeKutta());
|
||||
|
||||
ViscousDrag myViscousDrag = new ViscousDrag();
|
||||
myViscousDrag.coefficient = 1f;
|
||||
mPhysics.add(myViscousDrag);
|
||||
|
||||
Gravity myGravity = new Gravity();
|
||||
myGravity.force().y = 50;
|
||||
mPhysics.add(myGravity);
|
||||
|
||||
/* particles */
|
||||
mParticleA = mPhysics.makeParticle();
|
||||
mParticleB = mPhysics.makeParticle();
|
||||
mParticleC = mPhysics.makeParticle();
|
||||
mParticleD = mPhysics.makeParticle();
|
||||
|
||||
mParticleA.position().set(width / 2 + 50, height / 3);
|
||||
mParticleB.position().set(width / 2, height - height / 1.75f);
|
||||
mParticleC.position().set(width / 2, height - height / 4);
|
||||
mParticleD.position().set(width / 2, height - height / 8);
|
||||
|
||||
mParticleA.radius(7);
|
||||
mParticleB.radius(3);
|
||||
mParticleC.radius(10);
|
||||
mParticleD.radius(2);
|
||||
|
||||
mParticleB.fixed(true);
|
||||
|
||||
/* springs */
|
||||
Spring mSpringAB = new Spring(mParticleA, mParticleB);
|
||||
mSpringAB.strength(250);
|
||||
mSpringAB.damping(10);
|
||||
mPhysics.add(mSpringAB);
|
||||
|
||||
Spring mSpringBC = new Spring(mParticleB, mParticleC);
|
||||
mSpringBC.strength(250);
|
||||
mSpringBC.damping(10);
|
||||
mPhysics.add(mSpringBC);
|
||||
|
||||
Stick mSpringCD = new Stick(mParticleC, mParticleD);
|
||||
mSpringCD.damping(1);
|
||||
mPhysics.add(mSpringCD);
|
||||
|
||||
/* angle constraint */
|
||||
mAngleConstraintABC = new AngleConstraintSpring(mParticleA, mParticleB, mParticleC);
|
||||
mAngleConstraintABC.min_angle(PI * 0.5f);
|
||||
mAngleConstraintABC.damping(1);
|
||||
mAngleConstraintABC.strength(200);
|
||||
mPhysics.add(mAngleConstraintABC);
|
||||
|
||||
mAngleConstraintBCD = new AngleConstraintStick(mParticleB, mParticleC, mParticleD);
|
||||
mAngleConstraintBCD.min_angle(PI * 0.8f);
|
||||
mAngleConstraintBCD.damping(0.5f);
|
||||
mPhysics.add(mAngleConstraintBCD);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
/* attach particle to mouse */
|
||||
if (mousePressed) {
|
||||
mParticleA.position().set(mouseX, mouseY);
|
||||
}
|
||||
|
||||
/* apply constraints */
|
||||
mAngleConstraintABC.pre_step();
|
||||
mAngleConstraintBCD.pre_step();
|
||||
draw_physics();
|
||||
|
||||
mPhysics.step(1f / frameRate);
|
||||
|
||||
/* remove contraints */
|
||||
mAngleConstraintABC.post_step();
|
||||
mAngleConstraintBCD.post_step();
|
||||
}
|
||||
|
||||
void draw_physics() {
|
||||
background(255);
|
||||
|
||||
drawSprings();
|
||||
drawSticks();
|
||||
drawParticles();
|
||||
}
|
||||
|
||||
void drawSprings() {
|
||||
for (int i = 0; i < mPhysics.forces().size(); i++) {
|
||||
if (mPhysics.forces(i) instanceof Spring) {
|
||||
final Spring mSpring = (Spring)mPhysics.forces(i);
|
||||
if (mSpring instanceof AngleConstraintSpring) {
|
||||
strokeWeight(1);
|
||||
if (mSpring.active()) {
|
||||
stroke(255, 0, 0, 64);
|
||||
}
|
||||
else {
|
||||
stroke(255, 0, 0, 16);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strokeWeight(3);
|
||||
stroke(0, 128);
|
||||
}
|
||||
line(mSpring.a(), mSpring.b());
|
||||
}
|
||||
}
|
||||
strokeWeight(1);
|
||||
}
|
||||
|
||||
void drawSticks() {
|
||||
for (int i = 0; i < mPhysics.constraints().size(); i++) {
|
||||
if (mPhysics.constraints(i) instanceof Stick) {
|
||||
final Stick mStick = (Stick)mPhysics.constraints(i);
|
||||
if (mStick instanceof AngleConstraintStick) {
|
||||
strokeWeight(1);
|
||||
if (mStick.active()) {
|
||||
stroke(0, 127, 255, 64);
|
||||
}
|
||||
else {
|
||||
stroke(0, 127, 255, 16);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strokeWeight(3);
|
||||
stroke(0, 128);
|
||||
}
|
||||
line(mStick.a(), mStick.b());
|
||||
}
|
||||
}
|
||||
strokeWeight(1);
|
||||
}
|
||||
|
||||
void drawParticles() {
|
||||
stroke(0);
|
||||
fill(92);
|
||||
drawParticle(mParticleA);
|
||||
fill(127);
|
||||
drawParticle(mParticleB);
|
||||
fill(192);
|
||||
drawParticle(mParticleC);
|
||||
fill(64);
|
||||
drawParticle(mParticleD);
|
||||
}
|
||||
|
||||
void drawParticle(Particle p) {
|
||||
ellipse(p.position().x,
|
||||
p.position().y,
|
||||
p.radius() * 2, p.radius() * 2);
|
||||
}
|
||||
|
||||
void line(Particle p1, Particle p2) {
|
||||
line(p1.position().x, p1.position().y,
|
||||
p2.position().x, p2.position().y);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
import mathematik.*;
|
||||
|
||||
import processing.opengl.*;
|
||||
|
||||
import teilchen.BehaviorParticle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.behavior.Arrival;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.util.CollisionManager;
|
||||
|
||||
/**
|
||||
* this demo shows how to add behaviors to particles. in this example the
|
||||
* arrival behavior.
|
||||
*/
|
||||
|
||||
Physics mPhysics;
|
||||
|
||||
ArrayList<Duckling> mDucklings;
|
||||
|
||||
CollisionManager mCollision;
|
||||
|
||||
void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
frameRate(60);
|
||||
smooth();
|
||||
colorMode(RGB, 1.0f);
|
||||
|
||||
/* physics */
|
||||
mPhysics = new Physics();
|
||||
|
||||
ViscousDrag myViscousDrag = new ViscousDrag();
|
||||
myViscousDrag.coefficient = 0.25f;
|
||||
mPhysics.add(myViscousDrag);
|
||||
|
||||
mCollision = new CollisionManager();
|
||||
mCollision.minimumDistance(25);
|
||||
|
||||
/* ducklings */
|
||||
mDucklings = new ArrayList<Duckling>();
|
||||
for (int i = 0; i < 13; i++) {
|
||||
final Duckling mDuckling = new Duckling();
|
||||
if (!mDucklings.isEmpty()) {
|
||||
mDuckling.arrival.setPositionRef(mDucklings.get(mDucklings.size()-1).particle.position());
|
||||
}
|
||||
mCollision.collision().add(mDuckling.particle);
|
||||
mDucklings.add(mDuckling);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void draw() {
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
background(1);
|
||||
|
||||
/* update particles */
|
||||
mCollision.createCollisionResolvers();
|
||||
mCollision.loop(mDeltaTime);
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
drawCollisionSprings();
|
||||
mCollision.removeCollisionResolver();
|
||||
|
||||
mDucklings.get(0).arrival.oversteer(!mousePressed);
|
||||
mDucklings.get(0).arrival.position().set(mouseX, mouseY);
|
||||
|
||||
/* draw */
|
||||
for (int i=0; i < mDucklings.size(); i++) {
|
||||
Duckling mDuckling = mDucklings.get(i);
|
||||
drawParticle(mDuckling);
|
||||
}
|
||||
|
||||
/* draw arrival */
|
||||
stroke(0, 0.25f);
|
||||
noFill();
|
||||
ellipse(mDucklings.get(0).arrival.position().x,
|
||||
mDucklings.get(0).arrival.position().y,
|
||||
20, 20);
|
||||
}
|
||||
|
||||
void drawParticle(Duckling pDuckling) {
|
||||
final BehaviorParticle mParticle = pDuckling.particle;
|
||||
final Arrival mArrival = pDuckling.arrival;
|
||||
|
||||
/* draw particle */
|
||||
stroke(0, 0.5f);
|
||||
noFill();
|
||||
if (mArrival.arriving()) {
|
||||
stroke(1, 0, 0, 0.5f);
|
||||
}
|
||||
if (mArrival.arrived()) {
|
||||
stroke(0, 1, 0, 0.5f);
|
||||
}
|
||||
ellipse(mParticle.position().x, mParticle.position().y,
|
||||
mParticle.radius() * 2, mParticle.radius() * 2);
|
||||
|
||||
/* - */
|
||||
pushMatrix();
|
||||
translate(mParticle.position().x,
|
||||
mParticle.position().y);
|
||||
|
||||
/* draw velocity */
|
||||
stroke(1, 0, 0, 0.5f);
|
||||
line(0, 0, mParticle.velocity().x, mParticle.velocity().y);
|
||||
|
||||
/* draw break force */
|
||||
stroke(0, 0.5f, 1, 0.5f);
|
||||
line(0, 0, mArrival.force().x, mArrival.force().y);
|
||||
|
||||
/* - */
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
void drawCollisionSprings() {
|
||||
stroke(0, 1, 0, 0.25f);
|
||||
for (int i = 0; i < mCollision.collision().forces().size(); ++i) {
|
||||
if (mCollision.collision().forces().get(i) instanceof Spring) {
|
||||
Spring mySpring = (Spring) mCollision.collision_forces().get(i);
|
||||
line(mySpring.a().position().x, mySpring.a().position().y, mySpring.a().position().z,
|
||||
mySpring.b().position().x, mySpring.b().position().y, mySpring.b().position().z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Duckling {
|
||||
|
||||
BehaviorParticle particle;
|
||||
|
||||
Arrival arrival;
|
||||
|
||||
Duckling() {
|
||||
/* create particles */
|
||||
particle = mPhysics.makeParticle(BehaviorParticle.class);
|
||||
particle.position().set(random(width), random(height));
|
||||
particle.maximumInnerForce(random(50, 150));
|
||||
particle.radius(random(6, 10));
|
||||
|
||||
arrival = new Arrival();
|
||||
arrival.breakforce(random(12, 28));
|
||||
arrival.breakradius(random(45, 55));
|
||||
|
||||
particle.behaviors().add(arrival);
|
||||
}
|
||||
}
|
||||
|
||||
Executable
BIN
Binary file not shown.
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
|
||||
public class BasicParticle
|
||||
implements Particle, Serializable {
|
||||
|
||||
private boolean mFixed;
|
||||
|
||||
private float mAge;
|
||||
|
||||
private float mMass;
|
||||
|
||||
private Vector3f mPosition;
|
||||
|
||||
private final Vector3f mOldPosition;
|
||||
|
||||
private final Vector3f mVelocity;
|
||||
|
||||
private final Vector3f mForce;
|
||||
|
||||
private boolean mTagged;
|
||||
|
||||
private boolean mStill;
|
||||
|
||||
private float mRadius;
|
||||
|
||||
private static final long serialVersionUID = 3737917975116369338L;
|
||||
|
||||
public BasicParticle() {
|
||||
mPosition = new Vector3f();
|
||||
mOldPosition = new Vector3f();
|
||||
mVelocity = new Vector3f();
|
||||
mForce = new Vector3f();
|
||||
mMass = 1;
|
||||
mFixed = false;
|
||||
mAge = 0;
|
||||
mTagged = false;
|
||||
mStill = false;
|
||||
mRadius = 0;
|
||||
}
|
||||
|
||||
public boolean fixed() {
|
||||
return mFixed;
|
||||
}
|
||||
|
||||
public void fixed(boolean theFixed) {
|
||||
mFixed = theFixed;
|
||||
}
|
||||
|
||||
public float age() {
|
||||
return mAge;
|
||||
}
|
||||
|
||||
public void age(float theAge) {
|
||||
mAge = theAge;
|
||||
}
|
||||
|
||||
public float mass() {
|
||||
return mMass;
|
||||
}
|
||||
|
||||
public void mass(float theMass) {
|
||||
mMass = theMass;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
public Vector3f old_position() {
|
||||
return mOldPosition;
|
||||
}
|
||||
|
||||
public void setPositionRef(Vector3f thePosition) {
|
||||
mPosition = thePosition;
|
||||
}
|
||||
|
||||
public Vector3f velocity() {
|
||||
return mVelocity;
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return mForce;
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void accumulateInnerForce(final float theDeltaTime) {
|
||||
}
|
||||
|
||||
public boolean tagged() {
|
||||
return mTagged;
|
||||
}
|
||||
|
||||
public void tag(boolean theTag) {
|
||||
mTagged = theTag;
|
||||
}
|
||||
|
||||
public boolean still() {
|
||||
return mStill;
|
||||
}
|
||||
|
||||
public void still(boolean theStill) {
|
||||
mStill = theStill;
|
||||
}
|
||||
|
||||
public float radius() {
|
||||
return mRadius;
|
||||
}
|
||||
|
||||
public void radius(float theRadius) {
|
||||
mRadius = theRadius;
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen;
|
||||
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import teilchen.behavior.IBehavior;
|
||||
|
||||
|
||||
public class BehaviorParticle
|
||||
extends BasicParticle
|
||||
implements IBehaviorParticle {
|
||||
|
||||
private final Vector<IBehavior> mBehaviors;
|
||||
|
||||
private float mMaximumInnerForce;
|
||||
|
||||
private static final long serialVersionUID = 2735849326244271321L;
|
||||
|
||||
public BehaviorParticle() {
|
||||
mBehaviors = new Vector<IBehavior>();
|
||||
mMaximumInnerForce = 50;
|
||||
}
|
||||
|
||||
public void accumulateInnerForce(final float theDeltaTime) {
|
||||
for (final IBehavior mBehavior : mBehaviors) {
|
||||
if (mBehavior != null) {
|
||||
mBehavior.update(theDeltaTime, this);
|
||||
force().add(mBehavior.force());
|
||||
}
|
||||
}
|
||||
/* clamp to maximum force */
|
||||
if (maximumInnerForce() > 0) {
|
||||
final float mForceLength = force().length();
|
||||
if (mForceLength > maximumInnerForce()) {
|
||||
force().scale(maximumInnerForce() / mForceLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float maximumInnerForce() {
|
||||
return mMaximumInnerForce;
|
||||
}
|
||||
|
||||
public void maximumInnerForce(float theForce) {
|
||||
mMaximumInnerForce = theForce;
|
||||
}
|
||||
|
||||
public Vector<IBehavior> behaviors() {
|
||||
return mBehaviors;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen;
|
||||
|
||||
|
||||
public abstract class ConditionalParticle
|
||||
extends BasicParticle {
|
||||
|
||||
public boolean dead() {
|
||||
return !condition();
|
||||
}
|
||||
|
||||
public abstract boolean condition();
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen;
|
||||
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
public interface IBehaviorParticle
|
||||
extends Particle {
|
||||
|
||||
float maximumInnerForce();
|
||||
|
||||
void maximumInnerForce(float theForce);
|
||||
|
||||
Vector<teilchen.behavior.IBehavior> behaviors();
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen;
|
||||
|
||||
|
||||
public interface IConnection {
|
||||
|
||||
Particle a();
|
||||
|
||||
Particle b();
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.util.SpatialEntity;
|
||||
|
||||
|
||||
public interface Particle
|
||||
extends SpatialEntity {
|
||||
|
||||
boolean fixed();
|
||||
|
||||
void fixed(boolean theFixed);
|
||||
|
||||
float age();
|
||||
|
||||
void age(float theAge);
|
||||
|
||||
float mass();
|
||||
|
||||
void mass(float theMass);
|
||||
|
||||
Vector3f position();
|
||||
|
||||
Vector3f old_position();
|
||||
|
||||
void setPositionRef(Vector3f thePosition);
|
||||
|
||||
Vector3f velocity();
|
||||
|
||||
Vector3f force();
|
||||
|
||||
boolean dead();
|
||||
|
||||
boolean tagged();
|
||||
|
||||
void tag(boolean theTag);
|
||||
|
||||
void accumulateInnerForce(final float theDeltaTime);
|
||||
|
||||
float radius();
|
||||
|
||||
void radius(float theRadius);
|
||||
|
||||
boolean still();
|
||||
|
||||
void still(boolean theStill);
|
||||
}
|
||||
Executable
+374
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen;
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.constraint.IConstraint;
|
||||
import teilchen.force.IForce;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.integration.IIntegrator;
|
||||
import teilchen.integration.Midpoint;
|
||||
import teilchen.integration.Verlet;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Vector;
|
||||
import teilchen.integration.RungeKutta;
|
||||
|
||||
public class Physics {
|
||||
|
||||
private final Vector<Particle> mParticles;
|
||||
|
||||
private final Vector<IForce> mForces;
|
||||
|
||||
private final Vector<IConstraint> mConstraints;
|
||||
|
||||
private IIntegrator mIntegrator;
|
||||
|
||||
private static final float EPSILON = 0.001f;
|
||||
|
||||
public boolean HINT_OPTIMIZE_STILL = true;
|
||||
|
||||
public boolean HINT_REMOVE_DEAD = true;
|
||||
|
||||
public boolean HINT_RECOVER_NAN = true;
|
||||
|
||||
public int contraint_iterations_per_steps = 1;
|
||||
|
||||
public static boolean HINT_UPDATE_OLD_POSITION = true;
|
||||
|
||||
public Physics() {
|
||||
mParticles = new Vector<Particle>();
|
||||
mForces = new Vector<IForce>();
|
||||
mConstraints = new Vector<IConstraint>();
|
||||
mIntegrator = new Midpoint();
|
||||
}
|
||||
|
||||
|
||||
/* particles */
|
||||
public void add(Particle theParticle) {
|
||||
mParticles.add(theParticle);
|
||||
}
|
||||
|
||||
public void add(Collection<? extends Particle> theParticles) {
|
||||
mParticles.addAll(theParticles);
|
||||
}
|
||||
|
||||
public void remove(Particle theParticle) {
|
||||
mParticles.remove(theParticle);
|
||||
}
|
||||
|
||||
public void remove(Collection<? extends Particle> theParticles) {
|
||||
|
||||
mParticles.removeAll(theParticles);
|
||||
}
|
||||
|
||||
public Vector<Particle> particles() {
|
||||
return mParticles;
|
||||
}
|
||||
|
||||
public Particle particles(final int theIndex) {
|
||||
return mParticles.get(theIndex);
|
||||
}
|
||||
|
||||
public BasicParticle makeParticle() {
|
||||
BasicParticle myParticle = new BasicParticle();
|
||||
mParticles.add(myParticle);
|
||||
return myParticle;
|
||||
}
|
||||
|
||||
public BasicParticle makeParticle(final Vector3f thePosition) {
|
||||
BasicParticle myParticle = makeParticle();
|
||||
myParticle.setPositionRef(thePosition);
|
||||
myParticle.old_position().set(myParticle.position());
|
||||
return myParticle;
|
||||
}
|
||||
|
||||
public BasicParticle makeParticle(final float x, final float y) {
|
||||
BasicParticle myParticle = makeParticle();
|
||||
myParticle.position().set(x, y);
|
||||
myParticle.old_position().set(myParticle.position());
|
||||
return myParticle;
|
||||
}
|
||||
|
||||
public BasicParticle makeParticle(final float x, final float y, final float z) {
|
||||
BasicParticle myParticle = makeParticle();
|
||||
myParticle.position().set(x, y, z);
|
||||
myParticle.old_position().set(myParticle.position());
|
||||
return myParticle;
|
||||
}
|
||||
|
||||
public BasicParticle makeParticle(final float x, final float y, final float z, final float pMass) {
|
||||
BasicParticle myParticle = makeParticle();
|
||||
myParticle.position().set(x, y, z);
|
||||
myParticle.mass(pMass);
|
||||
myParticle.old_position().set(myParticle.position());
|
||||
return myParticle;
|
||||
}
|
||||
|
||||
public BasicParticle makeParticle(final Vector3f thePosition, final float pMass) {
|
||||
BasicParticle myParticle = makeParticle();
|
||||
myParticle.setPositionRef(thePosition);
|
||||
myParticle.old_position().set(myParticle.position());
|
||||
myParticle.mass(pMass);
|
||||
return myParticle;
|
||||
}
|
||||
|
||||
public <T extends Particle> T makeParticle(Class<T> theParticleClass) {
|
||||
T myParticle;
|
||||
try {
|
||||
myParticle = theParticleClass.newInstance();
|
||||
mParticles.add(myParticle);
|
||||
} catch (Exception ex) {
|
||||
System.err.println(ex);
|
||||
myParticle = null;
|
||||
}
|
||||
return myParticle;
|
||||
}
|
||||
|
||||
public void removeTags() {
|
||||
for (final Particle myParticle : mParticles) {
|
||||
myParticle.tag(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* forces */
|
||||
public void add(IForce theForce) {
|
||||
if (theForce instanceof ViscousDrag && mIntegrator instanceof Verlet) {
|
||||
System.err.println(
|
||||
"### WARNING / 'viscous drag' might have no effect with 'verlet' integration. use 'Verlet.damping(float theDamping)' instead.");
|
||||
}
|
||||
mForces.add(theForce);
|
||||
}
|
||||
|
||||
public void addForces(final Vector<? extends IForce> theForces) {
|
||||
mForces.addAll(theForces);
|
||||
}
|
||||
|
||||
public void remove(IForce theForce) {
|
||||
mForces.remove(theForce);
|
||||
}
|
||||
|
||||
public Vector<IForce> forces() {
|
||||
return mForces;
|
||||
}
|
||||
|
||||
public IForce forces(final int theIndex) {
|
||||
return mForces.get(theIndex);
|
||||
}
|
||||
|
||||
public void applyForces(final float theDeltaTime) {
|
||||
/* accumulate inner forces */
|
||||
synchronized (mParticles) {
|
||||
final Iterator<Particle> iter = mParticles.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final Particle myParticle = iter.next();
|
||||
if (!myParticle.fixed()) {
|
||||
/* accumulate inner forces */
|
||||
myParticle.accumulateInnerForce(theDeltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add new forces to each particle */
|
||||
synchronized (mForces) {
|
||||
Iterator<IForce> iter = mForces.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final IForce mForce = iter.next();
|
||||
if (mForce.active()) {
|
||||
mForce.apply(theDeltaTime, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends IForce> T makeForce(Class<T> theForceClass) {
|
||||
T myForce;
|
||||
try {
|
||||
myForce = theForceClass.newInstance();
|
||||
mForces.add(myForce);
|
||||
} catch (Exception ex) {
|
||||
System.err.println(ex);
|
||||
myForce = null;
|
||||
}
|
||||
return myForce;
|
||||
}
|
||||
|
||||
public Spring makeSpring(final Particle theA, final Particle theB) {
|
||||
Spring mySpring = new Spring(theA, theB);
|
||||
mForces.add(mySpring);
|
||||
return mySpring;
|
||||
}
|
||||
|
||||
public Spring makeSpring(final Particle theA,
|
||||
final Particle theB,
|
||||
final float theRestLength) {
|
||||
Spring mySpring = new Spring(theA, theB, theRestLength);
|
||||
mForces.add(mySpring);
|
||||
return mySpring;
|
||||
}
|
||||
|
||||
public Spring makeSpring(final Particle theA,
|
||||
final Particle theB,
|
||||
final float theSpringConstant,
|
||||
final float theSpringDamping) {
|
||||
Spring mySpring = new Spring(theA, theB, theSpringConstant, theSpringDamping);
|
||||
mForces.add(mySpring);
|
||||
return mySpring;
|
||||
}
|
||||
|
||||
public Spring makeSpring(final Particle theA,
|
||||
final Particle theB,
|
||||
final float theSpringConstant,
|
||||
final float theSpringDamping,
|
||||
final float theRestLength) {
|
||||
Spring mySpring = new Spring(theA, theB, theSpringConstant, theSpringDamping, theRestLength);
|
||||
mForces.add(mySpring);
|
||||
return mySpring;
|
||||
}
|
||||
|
||||
|
||||
/* constraints */
|
||||
public void add(final IConstraint theConstraint) {
|
||||
mConstraints.add(theConstraint);
|
||||
}
|
||||
|
||||
public void addConstraints(final Vector<? extends IConstraint> theConstraints) {
|
||||
mConstraints.addAll(theConstraints);
|
||||
}
|
||||
|
||||
public void remove(final IConstraint theConstraint) {
|
||||
mConstraints.remove(theConstraint);
|
||||
}
|
||||
|
||||
public Vector<IConstraint> constraints() {
|
||||
return mConstraints;
|
||||
}
|
||||
|
||||
public IConstraint constraints(final int theIndex) {
|
||||
return mConstraints.get(theIndex);
|
||||
}
|
||||
|
||||
|
||||
/* integration */
|
||||
public void setInegratorRef(IIntegrator theIntegrator) {
|
||||
mIntegrator = theIntegrator;
|
||||
}
|
||||
|
||||
public IIntegrator getIntegrator() {
|
||||
return mIntegrator;
|
||||
}
|
||||
|
||||
public void loop(final float theDeltaTime, final int theIterations) {
|
||||
for (int i = 0; i < theIterations; i++) {
|
||||
step(theDeltaTime / (float) theIterations);
|
||||
}
|
||||
}
|
||||
|
||||
public void step(final float theDeltaTime) {
|
||||
prepareParticles(theDeltaTime);
|
||||
handleForces();
|
||||
integrate(theDeltaTime);
|
||||
handleParticles(theDeltaTime);
|
||||
handleContraints();
|
||||
}
|
||||
|
||||
protected synchronized void integrate(float theDeltaTime) {
|
||||
mIntegrator.step(theDeltaTime, this);
|
||||
}
|
||||
|
||||
protected synchronized void handleForces() {
|
||||
synchronized (mForces) {
|
||||
final Iterator<IForce> iter = mForces.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final IForce myForce = iter.next();
|
||||
if (myForce.dead()) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void handleContraints() {
|
||||
synchronized (mConstraints) {
|
||||
for (int i = 0; i < contraint_iterations_per_steps; i++) {
|
||||
final Iterator<IConstraint> iter = mConstraints.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final IConstraint myContraint = iter.next();
|
||||
myContraint.apply(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void handleParticles(float theDeltaTime) {
|
||||
synchronized (mParticles) {
|
||||
final Iterator<Particle> iter = mParticles.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final Particle myParticle = iter.next();
|
||||
/* clear force */
|
||||
myParticle.force().set(0, 0, 0);
|
||||
/* age particle */
|
||||
myParticle.age(myParticle.age() + theDeltaTime);
|
||||
/* remove dead */
|
||||
if (HINT_REMOVE_DEAD) {
|
||||
if (myParticle.dead()) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
/* recover NAN */
|
||||
if (HINT_RECOVER_NAN) {
|
||||
if (myParticle.position().isNaN()) {
|
||||
if (myParticle.old_position().isNaN()) {
|
||||
myParticle.position().set(0, 0, 0);
|
||||
} else {
|
||||
myParticle.position().set(myParticle.old_position());
|
||||
}
|
||||
}
|
||||
if (myParticle.velocity().isNaN()) {
|
||||
myParticle.velocity().set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
/* still */
|
||||
if (HINT_OPTIMIZE_STILL) {
|
||||
final float mySpeed = myParticle.velocity().lengthSquared();
|
||||
myParticle.still(mySpeed > -EPSILON && mySpeed < EPSILON);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void prepareParticles(float theDeltaTime) {
|
||||
synchronized (mParticles) {
|
||||
final Iterator<Particle> iter = mParticles.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final Particle myParticle = iter.next();
|
||||
if (HINT_UPDATE_OLD_POSITION) {
|
||||
myParticle.old_position().set(myParticle.position());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen;
|
||||
|
||||
|
||||
public class ShortLivedParticle
|
||||
extends BasicParticle {
|
||||
|
||||
private float _myMaxAge;
|
||||
|
||||
public ShortLivedParticle(float theMaxAge) {
|
||||
_myMaxAge = theMaxAge;
|
||||
}
|
||||
|
||||
public ShortLivedParticle() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public void setMaxAge(float theMaxAge) {
|
||||
_myMaxAge = theMaxAge;
|
||||
}
|
||||
|
||||
public float ageRatio() {
|
||||
return Math.min(age() / _myMaxAge, 1);
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return age() >= _myMaxAge;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen;
|
||||
|
||||
|
||||
import mathematik.Vector3i;
|
||||
|
||||
|
||||
public class VectorfieldParticle
|
||||
extends BasicParticle {
|
||||
|
||||
private Vector3i _myLastUnit;
|
||||
|
||||
public VectorfieldParticle() {
|
||||
super();
|
||||
_myLastUnit = new Vector3i();
|
||||
}
|
||||
|
||||
public void setLastUnit(Vector3i theUnit) {
|
||||
_myLastUnit = theUnit;
|
||||
}
|
||||
|
||||
public Vector3i getLastUnit() {
|
||||
return _myLastUnit;
|
||||
}
|
||||
|
||||
public void accumulateInnerForce(final float theDeltaTime) {
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.IBehaviorParticle;
|
||||
import teilchen.behavior.Util.ProximityStructure;
|
||||
import java.io.Serializable;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
public class Alignment
|
||||
implements IBehavior,
|
||||
Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4953599448151741585L;
|
||||
|
||||
private float mProximity;
|
||||
|
||||
private float mWeight;
|
||||
|
||||
private final Vector3f mForce;
|
||||
|
||||
private Vector<IBehaviorParticle> mNeighbors;
|
||||
|
||||
public Alignment() {
|
||||
mProximity = 100.0f;
|
||||
mWeight = 1.0f;
|
||||
mForce = new Vector3f();
|
||||
}
|
||||
|
||||
public void update(float theDeltaTime, IBehaviorParticle pParent) {
|
||||
mForce.set(0, 0, 0);
|
||||
if (mNeighbors != null) {
|
||||
Vector<ProximityStructure> mCloseNeighbors = ProximityStructure.findProximityEntities(pParent, mNeighbors, mProximity);
|
||||
findCommonVelocity(mCloseNeighbors, mForce);
|
||||
mForce.scale(weight());
|
||||
}
|
||||
}
|
||||
|
||||
private static void findCommonVelocity(Vector<ProximityStructure> mCloseNeighbors, final Vector3f pForce) {
|
||||
/* find away vector */
|
||||
pForce.set(0, 0, 0);
|
||||
if (!mCloseNeighbors.isEmpty()) {
|
||||
/**
|
||||
* @todo the vectors could be weighted according to distance: 1.0 -
|
||||
* distance ( for example )
|
||||
*/
|
||||
for (ProximityStructure p : mCloseNeighbors) {
|
||||
pForce.add(p.particle.velocity());
|
||||
}
|
||||
pForce.scale(1.0f / mCloseNeighbors.size());
|
||||
pForce.normalize();
|
||||
if (pForce.isNaN()) {
|
||||
pForce.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <E extends IBehaviorParticle> void neighbors(final Vector<E> pNeighbors) {
|
||||
/**
|
||||
* @todo well is this OK?
|
||||
*/
|
||||
mNeighbors = (Vector<IBehaviorParticle>) pNeighbors;
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return mForce;
|
||||
}
|
||||
|
||||
public float weight() {
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
public void weight(float pWeight) {
|
||||
mWeight = pWeight;
|
||||
}
|
||||
|
||||
public float proximity() {
|
||||
return mProximity;
|
||||
}
|
||||
|
||||
public void proximity(float thePrivacyRadius) {
|
||||
mProximity = thePrivacyRadius;
|
||||
}
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import teilchen.IBehaviorParticle;
|
||||
|
||||
|
||||
public class Arrival
|
||||
implements IBehavior, Verhalten {
|
||||
|
||||
static final long serialVersionUID = 6897889750581191781L;
|
||||
|
||||
private Vector3f mSeekPosition;
|
||||
|
||||
private final Vector3f mForce;
|
||||
|
||||
private float mWeight;
|
||||
|
||||
private float mBreakRadius;
|
||||
|
||||
private float mBreakForce;
|
||||
|
||||
private boolean mIsArriving;
|
||||
|
||||
private boolean mHasArrived;
|
||||
|
||||
private boolean mOverSteer;
|
||||
|
||||
public Arrival() {
|
||||
mBreakRadius = 50.0f;
|
||||
mBreakForce = 50.0f;
|
||||
mForce = new Vector3f();
|
||||
mSeekPosition = new Vector3f();
|
||||
mWeight = 1;
|
||||
mIsArriving = false;
|
||||
mHasArrived = false;
|
||||
mOverSteer = true;
|
||||
}
|
||||
|
||||
public boolean arriving() {
|
||||
return mIsArriving;
|
||||
}
|
||||
|
||||
public boolean arrived() {
|
||||
return mHasArrived;
|
||||
}
|
||||
|
||||
public boolean oversteer() {
|
||||
return mOverSteer;
|
||||
}
|
||||
|
||||
public void oversteer(boolean pOverSteer) {
|
||||
mOverSteer = pOverSteer;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return mSeekPosition;
|
||||
}
|
||||
|
||||
public void setPositionRef(final Vector3f pPoint) {
|
||||
mSeekPosition = pPoint;
|
||||
}
|
||||
|
||||
public void breakforce(float pBreakForce) {
|
||||
mBreakForce = pBreakForce;
|
||||
}
|
||||
|
||||
public float breakforce() {
|
||||
return mBreakForce;
|
||||
}
|
||||
|
||||
public void breakradius(float pOutterRadius) {
|
||||
mBreakRadius = pOutterRadius;
|
||||
}
|
||||
|
||||
public float breakradius() {
|
||||
return mBreakRadius;
|
||||
}
|
||||
|
||||
public void update(float theDeltaTime, IBehaviorParticle pParent) {
|
||||
mForce.sub(mSeekPosition, pParent.position());
|
||||
final float myDistanceToArrivalPoint = mForce.length();
|
||||
|
||||
/* get direction */
|
||||
if (myDistanceToArrivalPoint < mBreakRadius) {
|
||||
mIsArriving = true;
|
||||
final float mSpeed = pParent.velocity().length();
|
||||
final float MIN_ACCEPTABLE_SPEED = 10.0f;
|
||||
if (mSpeed < MIN_ACCEPTABLE_SPEED) {
|
||||
/* sleep */
|
||||
mForce.set(0, 0, 0);
|
||||
mHasArrived = true;
|
||||
} else {
|
||||
/* break */
|
||||
final boolean USE_WEIGHTED_BREAK_FORCE = true;
|
||||
if (USE_WEIGHTED_BREAK_FORCE) {
|
||||
final float mRatio = myDistanceToArrivalPoint / mBreakRadius;
|
||||
|
||||
final Vector3f mBreakForceVector = new Vector3f(pParent.velocity());
|
||||
mBreakForceVector.scale(-mBreakForce);
|
||||
mBreakForceVector.scale(1.0f - mRatio);
|
||||
|
||||
final Vector3f mSteerForce = new Vector3f(mForce);
|
||||
mSteerForce.scale(pParent.maximumInnerForce() / myDistanceToArrivalPoint);
|
||||
mSteerForce.scale(mRatio);
|
||||
|
||||
mForce.add(mBreakForceVector, mSteerForce);
|
||||
} else {
|
||||
mForce.set(pParent.velocity().x * -mBreakForce,
|
||||
pParent.velocity().y * -mBreakForce,
|
||||
pParent.velocity().z * -mBreakForce);
|
||||
}
|
||||
mHasArrived = false;
|
||||
}
|
||||
} else {
|
||||
/* outside of the outter radius continue 'seeking' */
|
||||
mForce.scale(pParent.maximumInnerForce() / myDistanceToArrivalPoint);
|
||||
if (mOverSteer) {
|
||||
mForce.sub(mForce, pParent.velocity());
|
||||
}
|
||||
mIsArriving = false;
|
||||
mHasArrived = false;
|
||||
}
|
||||
mForce.scale(weight());
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return mForce;
|
||||
}
|
||||
|
||||
public float weight() {
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
public void weight(float pWeight) {
|
||||
mWeight = pWeight;
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.IBehaviorParticle;
|
||||
import teilchen.behavior.Util.ProximityStructure;
|
||||
import java.io.Serializable;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
public class Cohesion
|
||||
implements IBehavior,
|
||||
Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4953599448151741585L;
|
||||
|
||||
private float mProximity;
|
||||
|
||||
private float mWeight;
|
||||
|
||||
private final Vector3f mForce;
|
||||
|
||||
private Vector<IBehaviorParticle> mNeighbors;
|
||||
|
||||
public Cohesion() {
|
||||
mProximity = 100.0f;
|
||||
mWeight = 1.0f;
|
||||
mForce = new Vector3f();
|
||||
}
|
||||
|
||||
public void update(float theDeltaTime, IBehaviorParticle pParent) {
|
||||
mForce.set(0, 0, 0);
|
||||
if (mNeighbors != null) {
|
||||
Vector<ProximityStructure> mCloseNeighbors = ProximityStructure.findProximityEntities(pParent, mNeighbors, mProximity);
|
||||
findTowardsVector(mCloseNeighbors, mForce);
|
||||
mForce.scale(weight());
|
||||
}
|
||||
}
|
||||
|
||||
private static void findTowardsVector(Vector<ProximityStructure> mCloseNeighbors, final Vector3f pForce) {
|
||||
/* find away vector */
|
||||
if (!mCloseNeighbors.isEmpty()) {
|
||||
pForce.set(0, 0, 0);
|
||||
/**
|
||||
* @todo the vectors could be weighted according to distance: 1.0 -
|
||||
* distance ( for example )
|
||||
*/
|
||||
for (ProximityStructure p : mCloseNeighbors) {
|
||||
final Vector3f mTowardsVector = mathematik.Util.scale(p.distanceVec, -1.0f);
|
||||
pForce.add(mTowardsVector);
|
||||
}
|
||||
pForce.scale(1.0f / mCloseNeighbors.size());
|
||||
pForce.normalize();
|
||||
if (pForce.isNaN()) {
|
||||
pForce.set(0, 0, 0);
|
||||
}
|
||||
} else {
|
||||
pForce.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public <E extends IBehaviorParticle> void neighbors(final Vector<E> pNeighbors) {
|
||||
/**
|
||||
* @todo well is this OK?
|
||||
*/
|
||||
mNeighbors = (Vector<IBehaviorParticle>) pNeighbors;
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return mForce;
|
||||
}
|
||||
|
||||
public float weight() {
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
public void weight(float pWeight) {
|
||||
mWeight = pWeight;
|
||||
}
|
||||
|
||||
public float proximity() {
|
||||
return mProximity;
|
||||
}
|
||||
|
||||
public void proximity(float thePrivacyRadius) {
|
||||
mProximity = thePrivacyRadius;
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.IBehaviorParticle;
|
||||
|
||||
|
||||
public class Flee
|
||||
implements IBehavior, Verhalten {
|
||||
|
||||
static final long serialVersionUID = -6530887943347815188L;
|
||||
|
||||
private Vector3f mFleePosition;
|
||||
|
||||
private Vector3f mForce;
|
||||
|
||||
private float mWeight = 1;
|
||||
|
||||
public Flee() {
|
||||
mFleePosition = new Vector3f();
|
||||
mForce = new Vector3f();
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return mFleePosition;
|
||||
}
|
||||
|
||||
public void setPositionRef(final Vector3f thePoint) {
|
||||
mFleePosition = thePoint;
|
||||
}
|
||||
|
||||
public void update(float theDeltaTime, IBehaviorParticle theParent) {
|
||||
mForce.sub(theParent.position(), mFleePosition);
|
||||
final float myDistanceToPoint = mForce.length();
|
||||
if (myDistanceToPoint > SMALLEST_ACCEPTABLE_DISTANCE) {
|
||||
mForce.scale(theParent.maximumInnerForce() / myDistanceToPoint);
|
||||
mForce.sub(mForce, theParent.velocity());
|
||||
mForce.scale(weight());
|
||||
} else {
|
||||
mForce.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return mForce;
|
||||
}
|
||||
|
||||
public float weight() {
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
public void weight(float theWeight) {
|
||||
mWeight = theWeight;
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.IBehaviorParticle;
|
||||
|
||||
|
||||
public interface IBehavior
|
||||
extends Serializable {
|
||||
|
||||
void update(float theDeltaTime, final IBehaviorParticle pParent);
|
||||
|
||||
Vector3f force();
|
||||
|
||||
float weight();
|
||||
|
||||
void weight(float theWeight);
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.IBehaviorParticle;
|
||||
|
||||
|
||||
public class Motor
|
||||
implements IBehavior,
|
||||
Verhalten {
|
||||
|
||||
static final long serialVersionUID = -3781170603537691466L;
|
||||
|
||||
private Vector3f mDirection;
|
||||
|
||||
private float mStrength;
|
||||
|
||||
private final Vector3f mForce;
|
||||
|
||||
private float mWeight;
|
||||
|
||||
private boolean mAutoNormalizeDirection;
|
||||
|
||||
private boolean mActive;
|
||||
|
||||
private boolean mAutoUpdateDirection;
|
||||
|
||||
public final Vector3f AUTO_RECOVER_DIRECTION;
|
||||
|
||||
public Motor() {
|
||||
mDirection = new Vector3f(1, 0, 0);
|
||||
mForce = new Vector3f();
|
||||
mActive = true;
|
||||
mStrength = 1;
|
||||
mWeight = 1;
|
||||
mAutoUpdateDirection = false;
|
||||
mAutoNormalizeDirection = true;
|
||||
AUTO_RECOVER_DIRECTION = new Vector3f();
|
||||
AUTO_RECOVER_DIRECTION.randomize();
|
||||
AUTO_RECOVER_DIRECTION.z = 0;
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return mActive;
|
||||
}
|
||||
|
||||
public void active(boolean pActive) {
|
||||
mActive = pActive;
|
||||
}
|
||||
|
||||
public float strength() {
|
||||
return mStrength;
|
||||
}
|
||||
|
||||
public void strength(final float theStrength) {
|
||||
mStrength = theStrength;
|
||||
}
|
||||
|
||||
public Vector3f direction() {
|
||||
return mDirection;
|
||||
}
|
||||
|
||||
public void setDirectionRef(final Vector3f theDirection) {
|
||||
mDirection = theDirection;
|
||||
}
|
||||
|
||||
public void auto_update_direction(boolean pAutoUpdateDirection) {
|
||||
mAutoUpdateDirection = pAutoUpdateDirection;
|
||||
}
|
||||
|
||||
public void auto_normalize_direction(boolean pAutoNormalizeDirection) {
|
||||
mAutoNormalizeDirection = pAutoNormalizeDirection;
|
||||
}
|
||||
|
||||
public void update(float theDeltaTime, IBehaviorParticle pParent) {
|
||||
if (mActive) {
|
||||
if (mAutoUpdateDirection) {
|
||||
if (pParent.velocity().length() > 0.0f) {
|
||||
mDirection.set(pParent.velocity());
|
||||
} else {
|
||||
mDirection.set(AUTO_RECOVER_DIRECTION);
|
||||
}
|
||||
}
|
||||
if (mAutoNormalizeDirection) {
|
||||
mDirection.normalize();
|
||||
}
|
||||
mForce.scale(mStrength, mDirection);
|
||||
mForce.scale(mWeight, mForce);
|
||||
} else {
|
||||
mForce.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return mForce;
|
||||
}
|
||||
|
||||
public float weight() {
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
public void weight(float theWeight) {
|
||||
mWeight = theWeight;
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.IBehaviorParticle;
|
||||
|
||||
|
||||
public class Seek
|
||||
implements IBehavior, Verhalten {
|
||||
|
||||
static final long serialVersionUID = -3781170603537691477L;
|
||||
|
||||
private Vector3f mSeekPosition;
|
||||
|
||||
private Vector3f mForce;
|
||||
|
||||
private float mWeight = 1;
|
||||
|
||||
private float mDistanceToPoint;
|
||||
|
||||
private boolean mOverSteer;
|
||||
|
||||
public Seek() {
|
||||
mSeekPosition = new Vector3f();
|
||||
mForce = new Vector3f();
|
||||
mOverSteer = false;
|
||||
}
|
||||
|
||||
public boolean oversteer() {
|
||||
return mOverSteer;
|
||||
}
|
||||
|
||||
public void oversteer(boolean pOverSteer) {
|
||||
mOverSteer = pOverSteer;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return mSeekPosition;
|
||||
}
|
||||
|
||||
public void setPositionRef(final Vector3f thePoint) {
|
||||
mSeekPosition = thePoint;
|
||||
}
|
||||
|
||||
public float distancetopoint() {
|
||||
return mDistanceToPoint;
|
||||
}
|
||||
|
||||
public void update(float theDeltaTime, IBehaviorParticle theParent) {
|
||||
mForce.sub(mSeekPosition, theParent.position());
|
||||
mDistanceToPoint = mForce.length();
|
||||
if (mDistanceToPoint > SMALLEST_ACCEPTABLE_DISTANCE) {
|
||||
mForce.scale(theParent.maximumInnerForce() / mDistanceToPoint);
|
||||
if (mOverSteer) {
|
||||
mForce.sub(mForce, theParent.velocity());
|
||||
}
|
||||
mForce.scale(weight());
|
||||
} else {
|
||||
mForce.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return mForce;
|
||||
}
|
||||
|
||||
public float weight() {
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
public void weight(float theWeight) {
|
||||
mWeight = theWeight;
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.IBehaviorParticle;
|
||||
import teilchen.behavior.Util.ProximityStructure;
|
||||
import java.io.Serializable;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
public class Separation
|
||||
implements IBehavior,
|
||||
Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4953599448151741585L;
|
||||
|
||||
private float mProximity;
|
||||
|
||||
private float mWeight;
|
||||
|
||||
private final Vector3f mForce;
|
||||
|
||||
private Vector<IBehaviorParticle> mNeighbors;
|
||||
|
||||
public Separation() {
|
||||
mProximity = 100.0f;
|
||||
mWeight = 1.0f;
|
||||
mForce = new Vector3f();
|
||||
}
|
||||
|
||||
public void update(float theDeltaTime, IBehaviorParticle pParent) {
|
||||
mForce.set(0, 0, 0);
|
||||
if (mNeighbors != null) {
|
||||
Vector<ProximityStructure> mCloseNeighbors = ProximityStructure.findProximityEntities(pParent, mNeighbors, mProximity);
|
||||
findAwayVector(mCloseNeighbors, mForce);
|
||||
mForce.scale(weight());
|
||||
}
|
||||
}
|
||||
|
||||
private static void findAwayVector(Vector<ProximityStructure> mCloseNeighbors, final Vector3f pForce) {
|
||||
/* find away vector */
|
||||
if (!mCloseNeighbors.isEmpty()) {
|
||||
pForce.set(0, 0, 0);
|
||||
/**
|
||||
* @todo the vectors could be weighted according to distance: 1.0 -
|
||||
* distance ( for example )
|
||||
*/
|
||||
for (ProximityStructure p : mCloseNeighbors) {
|
||||
pForce.add(p.distanceVec);
|
||||
}
|
||||
pForce.scale(1.0f / mCloseNeighbors.size());
|
||||
pForce.normalize();
|
||||
if (pForce.isNaN()) {
|
||||
pForce.set(0, 0, 0);
|
||||
}
|
||||
} else {
|
||||
pForce.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public <E extends IBehaviorParticle> void neighbors(final Vector<E> pNeighbors) {
|
||||
/**
|
||||
* @todo well is this OK?
|
||||
*/
|
||||
mNeighbors = (Vector<IBehaviorParticle>) pNeighbors;
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return mForce;
|
||||
}
|
||||
|
||||
public float weight() {
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
public void weight(float pWeight) {
|
||||
mWeight = pWeight;
|
||||
}
|
||||
|
||||
public float proximity() {
|
||||
return mProximity;
|
||||
}
|
||||
|
||||
public void proximity(float thePrivacyRadius) {
|
||||
mProximity = thePrivacyRadius;
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import teilchen.IBehaviorParticle;
|
||||
|
||||
public class Steering implements IBehavior,
|
||||
Verhalten {
|
||||
|
||||
private final Vector3f mForce;
|
||||
private final Vector3f mUPVector;
|
||||
|
||||
private float mWeight;
|
||||
|
||||
private float mSteering = 0.0f;
|
||||
|
||||
private boolean mActive = true;
|
||||
|
||||
public Steering() {
|
||||
mForce = new Vector3f();
|
||||
mUPVector = new Vector3f(0, 0, -1);
|
||||
mWeight = 1;
|
||||
}
|
||||
|
||||
public void update(float theDeltaTime, IBehaviorParticle pParent) {
|
||||
if (mActive) {
|
||||
/* 2D warning -- ignoring z-axis for now */
|
||||
Vector3f mDirection = new Vector3f(pParent.velocity());
|
||||
if (mDirection.lengthSquared() > 0) {
|
||||
mDirection.normalize();
|
||||
mDirection = mathematik.Util.cross(mDirection, mUPVector);
|
||||
mDirection.scale(mSteering);
|
||||
mForce.set(mDirection);
|
||||
} else {
|
||||
mForce.set(0, 0, 0);
|
||||
}
|
||||
} else {
|
||||
mForce.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public float steering_strength() {
|
||||
return mSteering;
|
||||
}
|
||||
|
||||
public void steering_strength(float pSteering) {
|
||||
mSteering = pSteering;
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return mForce;
|
||||
}
|
||||
|
||||
public Vector3f upvector() {
|
||||
return mUPVector;
|
||||
}
|
||||
|
||||
public float weight() {
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
public void weight(float pWeight) {
|
||||
mWeight = pWeight;
|
||||
}
|
||||
|
||||
public void active(boolean pActive) {
|
||||
mActive = pActive;
|
||||
}
|
||||
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.IBehaviorParticle;
|
||||
import teilchen.Particle;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
public class Util {
|
||||
|
||||
public static class ProximityStructure {
|
||||
|
||||
public final Particle particle;
|
||||
|
||||
public final Vector3f distanceVec;
|
||||
|
||||
public final float distance;
|
||||
|
||||
public ProximityStructure(Particle pP, Vector3f pDistanceVec, float pDistance) {
|
||||
particle = pP;
|
||||
distanceVec = pDistanceVec;
|
||||
distance = pDistance;
|
||||
}
|
||||
|
||||
public static Vector<ProximityStructure> findProximityEntities(IBehaviorParticle pParentEntity,
|
||||
Vector<IBehaviorParticle> pNeighborsEntity,
|
||||
float pProximity) {
|
||||
/* find neighbors in proximity */
|
||||
Vector<ProximityStructure> mCloseNeighbors = new Vector<ProximityStructure>();
|
||||
for (IBehaviorParticle p : pNeighborsEntity) {
|
||||
if (!p.equals(pParentEntity)) { /* exclude self */
|
||||
final Vector3f mDistanceVec = mathematik.Util.sub(pParentEntity.position(), p.position());
|
||||
final float mDistance = mDistanceVec.length();
|
||||
if (mDistance <= pProximity) {
|
||||
mCloseNeighbors.add(new ProximityStructure(p, mDistanceVec, mDistance));
|
||||
}
|
||||
}
|
||||
}
|
||||
return mCloseNeighbors;
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
public interface Verhalten
|
||||
extends Serializable {
|
||||
|
||||
float SMALLEST_ACCEPTABLE_DISTANCE = 0.01f;
|
||||
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.behavior;
|
||||
|
||||
|
||||
import mathematik.Random;
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.IBehaviorParticle;
|
||||
|
||||
|
||||
public class Wander
|
||||
implements IBehavior {
|
||||
|
||||
static final long serialVersionUID = 4957162698340669663L;
|
||||
|
||||
private Vector3f mForce;
|
||||
|
||||
private float mSteeringStrength;
|
||||
|
||||
private float mSteeringOffset;
|
||||
|
||||
private float mCurrentSteeringStrength;
|
||||
|
||||
private Vector3f mUpVector;
|
||||
|
||||
private float mWeight;
|
||||
|
||||
private final Random mRandom;
|
||||
|
||||
private boolean mActive;
|
||||
|
||||
public Wander() {
|
||||
mRandom = new Random();
|
||||
|
||||
mForce = new Vector3f();
|
||||
mSteeringStrength = 10f;
|
||||
mSteeringOffset = 5f;
|
||||
|
||||
mUpVector = new Vector3f(0, 0, 1);
|
||||
|
||||
mWeight = 1;
|
||||
mActive = true;
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return mActive;
|
||||
}
|
||||
|
||||
public void active(boolean pActive) {
|
||||
mActive = pActive;
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return mForce;
|
||||
}
|
||||
|
||||
public float weight() {
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
public void weight(float theWeight) {
|
||||
mWeight = theWeight;
|
||||
}
|
||||
|
||||
public void update(float pDeltaTime, IBehaviorParticle pParent) {
|
||||
if (mActive && pParent.velocity().length() > 0) {
|
||||
mCurrentSteeringStrength += mRandom.getFloat(-0.5f, 0.5f) * mSteeringOffset;
|
||||
mCurrentSteeringStrength = Math.max(Math.min(mCurrentSteeringStrength, mSteeringStrength), -mSteeringStrength);
|
||||
|
||||
final Vector3f mWanderTarget = mathematik.Util.cross(mUpVector, pParent.velocity());
|
||||
mWanderTarget.normalize();
|
||||
mWanderTarget.scale(mCurrentSteeringStrength);
|
||||
if (mWanderTarget.isNaN()) {
|
||||
mForce.set(0, 0, 0);
|
||||
} else {
|
||||
mForce.scale(mWeight, mWanderTarget);
|
||||
}
|
||||
} else {
|
||||
mForce.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3f upvector() {
|
||||
return mUpVector;
|
||||
}
|
||||
|
||||
public float steeringstrength() {
|
||||
return mSteeringStrength;
|
||||
}
|
||||
|
||||
public void steeringstrength(final float theSteeringStrength) {
|
||||
mSteeringStrength = theSteeringStrength;
|
||||
}
|
||||
|
||||
public float steeringoffset() {
|
||||
return mSteeringOffset;
|
||||
}
|
||||
|
||||
public void steeringoffset(final float theSteeringOffset) {
|
||||
mSteeringOffset = theSteeringOffset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.constraint;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
|
||||
|
||||
public class AngleConstraintStick
|
||||
extends Stick {
|
||||
|
||||
private final Particle mParticleA;
|
||||
|
||||
private final Particle mParticleB;
|
||||
|
||||
private final Particle mParticleC;
|
||||
|
||||
private float mMinAngle;
|
||||
|
||||
/**
|
||||
*
|
||||
* particles are connected like this: A -- B -- C
|
||||
*
|
||||
* @param pParticleA
|
||||
* @param pParticleB
|
||||
* @param pParticleC
|
||||
*/
|
||||
public AngleConstraintStick(Particle pParticleA, Particle pParticleB, Particle pParticleC) {
|
||||
super(pParticleA, pParticleC);
|
||||
mParticleA = pParticleA;
|
||||
mParticleB = pParticleB;
|
||||
mParticleC = pParticleC;
|
||||
mMinAngle = Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
public void min_angle(float pAngle) {
|
||||
mMinAngle = pAngle;
|
||||
}
|
||||
|
||||
public void pre_step() {
|
||||
Vector3f ab = mathematik.Util.sub(mParticleA.position(), mParticleB.position());
|
||||
Vector3f cb = mathematik.Util.sub(mParticleC.position(), mParticleB.position());
|
||||
final float mCurrentAngle = ab.angle(cb);
|
||||
|
||||
if (mCurrentAngle < mMinAngle) {
|
||||
final float b = ab.length();
|
||||
final float c = cb.length();
|
||||
// a = sqrt ( b*b + c*c - 2bc*cosA )
|
||||
final float mDistance = (float) Math.sqrt(b * b + c * c - 2 * b * c * (float) Math.cos(mMinAngle));
|
||||
restlength(mDistance);
|
||||
active(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void post_step() {
|
||||
active(false);
|
||||
}
|
||||
}
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.constraint;
|
||||
|
||||
|
||||
import mathematik.Util;
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
/**
|
||||
* @todo it probably pays of two check if we deal with a 2D or 3D constraint. it
|
||||
* s just checking components once and then saving a lot of time.
|
||||
*/
|
||||
public class Angular
|
||||
implements IConstraint {
|
||||
|
||||
protected boolean mActive = true;
|
||||
|
||||
private final Particle _myA;
|
||||
|
||||
private final Particle _myB;
|
||||
|
||||
private final Particle _myC;
|
||||
|
||||
private final Vector3f _myTempA = new Vector3f();
|
||||
|
||||
private final Vector3f _myTempB = new Vector3f();
|
||||
|
||||
private float _myMinimumAngle;
|
||||
|
||||
private float _myMaximumAngle;
|
||||
|
||||
private final Vector3f _myTempNormal;
|
||||
|
||||
public boolean OK;
|
||||
|
||||
private static final double EPSILON = 0.001;
|
||||
|
||||
private static final double _myStrength = 1;
|
||||
|
||||
public Angular(Particle theA, Particle theB, Particle theC,
|
||||
float theMinimumAngle, float theMaximumAngle) {
|
||||
_myA = theA;
|
||||
_myB = theB;
|
||||
_myC = theC;
|
||||
_myTempNormal = new Vector3f();
|
||||
range(theMinimumAngle, theMaximumAngle);
|
||||
}
|
||||
|
||||
public Angular(Particle theA, Particle theB, Particle theC) {
|
||||
this(theA,
|
||||
theB,
|
||||
theC,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
public void range(float theMinimumAngle, float theMaximumAngle) {
|
||||
_myMinimumAngle = theMinimumAngle;
|
||||
_myMaximumAngle = theMaximumAngle;
|
||||
sortAngles();
|
||||
}
|
||||
|
||||
public float minimumAngle() {
|
||||
return _myMinimumAngle;
|
||||
}
|
||||
|
||||
public float maximumAngle() {
|
||||
return _myMaximumAngle;
|
||||
}
|
||||
|
||||
private void sortAngles() {
|
||||
final float myMaximumAngle = _myMaximumAngle;
|
||||
final float myMinimumAngle = _myMinimumAngle;
|
||||
_myMaximumAngle = Math.max(myMaximumAngle, myMinimumAngle);
|
||||
_myMinimumAngle = Math.min(myMaximumAngle, myMinimumAngle);
|
||||
}
|
||||
|
||||
public void apply(Physics theParticleSystem) {
|
||||
|
||||
if (!mActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo test for special case: a and c are in the same place.
|
||||
*/
|
||||
_myTempA.sub(_myB.position(), _myA.position());
|
||||
_myTempB.sub(_myB.position(), _myC.position());
|
||||
|
||||
_myTempA.normalize();
|
||||
_myTempB.normalize();
|
||||
|
||||
/**
|
||||
* @todo check for special cases! like angle being 0 etc.
|
||||
*/
|
||||
/**
|
||||
* @todo check if the range exceeds PI.
|
||||
*/
|
||||
if (_myMinimumAngle < Math.PI && _myMaximumAngle > Math.PI) {
|
||||
System.out.println("### WARNING split range and check twice.");
|
||||
}
|
||||
|
||||
float myCosinusAngle = _myTempA.dot(_myTempB);
|
||||
if (myCosinusAngle > 1) {
|
||||
System.out.println("### WARNING myCosinusAngle > 1: " + myCosinusAngle);
|
||||
myCosinusAngle = 1;
|
||||
}
|
||||
|
||||
final float myTempCosMaximumAngle = (float) Math.cos(_myMaximumAngle);
|
||||
final float myTempCosMinimumAngle = (float) Math.cos(_myMinimumAngle);
|
||||
final float myCosMaximumAngle = Math.max(myTempCosMinimumAngle, myTempCosMaximumAngle);
|
||||
final float myCosMinimumAngle = Math.min(myTempCosMinimumAngle, myTempCosMaximumAngle);
|
||||
|
||||
calculateNormal(_myTempA, _myTempB);
|
||||
final boolean myLeftSide = checkForHemisphere(_myTempA, _myTempB);
|
||||
double myCurrentAngle = 0;
|
||||
|
||||
/**
|
||||
* @todo until i the split is implemented agular constraints only work
|
||||
* for one side.
|
||||
*/
|
||||
OK = myLeftSide;
|
||||
|
||||
if (myLeftSide) {
|
||||
if (myCosinusAngle < myCosMinimumAngle || myCosinusAngle > myCosMaximumAngle) {
|
||||
myCurrentAngle = Math.acos(myCosinusAngle);
|
||||
OK = false;
|
||||
} else {
|
||||
OK = true;
|
||||
}
|
||||
} else {
|
||||
myCurrentAngle = 2 * Math.PI - Math.acos(myCosinusAngle);
|
||||
}
|
||||
|
||||
if (!OK) {
|
||||
final double myTheta;
|
||||
if (myCurrentAngle > _myMaximumAngle) {
|
||||
myTheta = _myMaximumAngle - myCurrentAngle;
|
||||
} else if (myCosinusAngle < _myMinimumAngle) {
|
||||
myTheta = -1 * (myCurrentAngle - _myMinimumAngle);
|
||||
} else {
|
||||
System.out.println("### WARNING puzzled.");
|
||||
myTheta = 0;
|
||||
}
|
||||
|
||||
correctAngle(myTheta);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateNormal(Vector3f myVectorA, Vector3f myVectorB) {
|
||||
_myTempNormal.cross(myVectorA, myVectorB);
|
||||
_myTempNormal.normalize();
|
||||
if (_myTempNormal.isNaN()) {
|
||||
_myTempNormal.set(0, 0, 1);
|
||||
System.out.println("### WARNING can t find normal.");
|
||||
}
|
||||
}
|
||||
|
||||
private void correctAngle(double theTheta) {
|
||||
if (theTheta < -EPSILON || theTheta > EPSILON) {
|
||||
|
||||
Vector3f myOtherPointOnAxis = Util.add(_myB.position(), _myTempNormal);
|
||||
|
||||
Vector3f myRotatedPointA = Util.rotatePoint(_myA.position(), theTheta * -0.5 * _myStrength,
|
||||
_myB.position(),
|
||||
myOtherPointOnAxis);
|
||||
_myA.position().set(myRotatedPointA);
|
||||
|
||||
Vector3f myRotatedPointB = Util.rotatePoint(_myC.position(), theTheta * 0.5 * _myStrength,
|
||||
_myB.position(),
|
||||
myOtherPointOnAxis);
|
||||
_myC.position().set(myRotatedPointB);
|
||||
|
||||
System.out.println("correct " + Math.toDegrees(theTheta) + " / " + _myTempNormal);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkForHemisphere(Vector3f myVectorA, Vector3f myVectorB) {
|
||||
/* special case thus easy to find the direction */
|
||||
if (myVectorA.z == 0 && myVectorB.z == 0) {
|
||||
return _myTempNormal.z > 0;
|
||||
} else {
|
||||
/**
|
||||
* @todo do it the hard way and create a matrix from the two vectors
|
||||
* and transform the cross vector into local space
|
||||
*/
|
||||
System.out.println("### WARNING calculate for 3D plane / not implemented.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return mActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
mActive = theActiveState;
|
||||
}
|
||||
}
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.constraint;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.integration.Verlet;
|
||||
|
||||
|
||||
public class Box
|
||||
implements IConstraint {
|
||||
|
||||
protected boolean mActive = true;
|
||||
|
||||
private final Vector3f _myMin;
|
||||
|
||||
private final Vector3f _myMax;
|
||||
|
||||
private boolean _myReflectFlag;
|
||||
|
||||
private float _myCoefficientOfRestitution;
|
||||
|
||||
private boolean _myTeleport;
|
||||
|
||||
public Box(final Vector3f theMin, final Vector3f theMax) {
|
||||
_myMin = theMin;
|
||||
_myMax = theMax;
|
||||
_myReflectFlag = true;
|
||||
_myCoefficientOfRestitution = 1.0f;
|
||||
_myTeleport = false;
|
||||
}
|
||||
|
||||
public Box() {
|
||||
this(new Vector3f(), new Vector3f());
|
||||
}
|
||||
|
||||
public void telelport(boolean theTeleportState) {
|
||||
_myTeleport = theTeleportState;
|
||||
}
|
||||
|
||||
public void reflect(boolean theReflectState) {
|
||||
_myReflectFlag = theReflectState;
|
||||
}
|
||||
|
||||
public Vector3f min() {
|
||||
return _myMin;
|
||||
}
|
||||
|
||||
public Vector3f max() {
|
||||
return _myMax;
|
||||
}
|
||||
private static final Vector3f[] _myNormals;
|
||||
|
||||
static {
|
||||
_myNormals = new Vector3f[6];
|
||||
_myNormals[0] = new Vector3f(-1, 0, 0);
|
||||
_myNormals[1] = new Vector3f(0, -1, 0);
|
||||
_myNormals[2] = new Vector3f(0, 0, -1);
|
||||
_myNormals[3] = new Vector3f(1, 0, 0);
|
||||
_myNormals[4] = new Vector3f(0, 1, 0);
|
||||
_myNormals[5] = new Vector3f(0, 0, 1);
|
||||
}
|
||||
|
||||
public void coefficientofrestitution(float theCoefficientOfRestitution) {
|
||||
_myCoefficientOfRestitution = theCoefficientOfRestitution;
|
||||
}
|
||||
|
||||
public float coefficientofrestitution() {
|
||||
return _myCoefficientOfRestitution;
|
||||
}
|
||||
|
||||
public void apply(final Physics theParticleSystem) {
|
||||
|
||||
if (!mActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Particle myParticle : theParticleSystem.particles()) {
|
||||
if (_myTeleport) {
|
||||
if (myParticle.position().x > _myMax.x) {
|
||||
myParticle.position().x = _myMin.x;
|
||||
}
|
||||
if (myParticle.position().y > _myMax.y) {
|
||||
myParticle.position().y = _myMin.y;
|
||||
}
|
||||
if (myParticle.position().z > _myMax.z) {
|
||||
myParticle.position().z = _myMin.z;
|
||||
}
|
||||
if (myParticle.position().x < _myMin.x) {
|
||||
myParticle.position().x = _myMax.x;
|
||||
}
|
||||
if (myParticle.position().y < _myMin.y) {
|
||||
myParticle.position().y = _myMax.y;
|
||||
}
|
||||
if (myParticle.position().z < _myMin.z) {
|
||||
myParticle.position().z = _myMax.z;
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* @todo to do this properly we would need to add the normals
|
||||
* and normalize them. maybe later.
|
||||
*/
|
||||
int myTag = -1;
|
||||
final Vector3f myPosition = new Vector3f(myParticle.position());
|
||||
if (myParticle.position().x > _myMax.x) {
|
||||
myParticle.position().x = _myMax.x;
|
||||
myTag = 0;
|
||||
}
|
||||
if (myParticle.position().y > _myMax.y) {
|
||||
myParticle.position().y = _myMax.y;
|
||||
myTag = 1;
|
||||
}
|
||||
if (myParticle.position().z > _myMax.z) {
|
||||
myParticle.position().z = _myMax.z;
|
||||
myTag = 2;
|
||||
}
|
||||
if (myParticle.position().x < _myMin.x) {
|
||||
myParticle.position().x = _myMin.x;
|
||||
myTag = 3;
|
||||
}
|
||||
if (myParticle.position().y < _myMin.y) {
|
||||
myParticle.position().y = _myMin.y;
|
||||
myTag = 4;
|
||||
}
|
||||
if (myParticle.position().z < _myMin.z) {
|
||||
myParticle.position().z = _myMin.z;
|
||||
myTag = 5;
|
||||
}
|
||||
if (myTag >= 0) {
|
||||
if (_myReflectFlag) {
|
||||
if (theParticleSystem.getIntegrator() instanceof Verlet) {
|
||||
final Vector3f myDiff = mathematik.Util.sub(myPosition, myParticle.position());
|
||||
teilchen.util.Util.reflect(myDiff, _myNormals[myTag], _myCoefficientOfRestitution);
|
||||
// System.out.println("### reflect " + _myNormals[myTag]);
|
||||
// System.out.println("myDiff " + myDiff);
|
||||
myParticle.old_position().sub(myDiff);
|
||||
} else {
|
||||
teilchen.util.Util.reflectVelocity(myParticle,
|
||||
_myNormals[myTag],
|
||||
_myCoefficientOfRestitution);
|
||||
}
|
||||
} else {
|
||||
myParticle.velocity().set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return mActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
mActive = theActiveState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.constraint;
|
||||
|
||||
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public interface IConstraint {
|
||||
|
||||
void apply(final Physics theParticleSystem);
|
||||
|
||||
boolean active();
|
||||
|
||||
void active(boolean theActiveState);
|
||||
}
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.constraint;
|
||||
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.integration.Verlet;
|
||||
|
||||
|
||||
public class ReflectBox
|
||||
implements IConstraint {
|
||||
|
||||
protected boolean mActive = true;
|
||||
|
||||
private final Vector3f _myMin;
|
||||
|
||||
private final Vector3f _myMax;
|
||||
|
||||
private float _myCoefficientOfRestitution;
|
||||
|
||||
private float _myEpsilon;
|
||||
|
||||
public boolean NEGATIVE_X = true;
|
||||
|
||||
public boolean NEGATIVE_Y = true;
|
||||
|
||||
public boolean NEGATIVE_Z = true;
|
||||
|
||||
public boolean POSITIV_X = true;
|
||||
|
||||
public boolean POSITIV_Y = true;
|
||||
|
||||
public boolean POSITIV_Z = true;
|
||||
|
||||
public ReflectBox(final Vector3f theMin, final Vector3f theMax) {
|
||||
_myMin = theMin;
|
||||
_myMax = theMax;
|
||||
_myCoefficientOfRestitution = 1.0f;
|
||||
_myEpsilon = 0.001f;
|
||||
}
|
||||
|
||||
public ReflectBox() {
|
||||
this(new Vector3f(), new Vector3f());
|
||||
}
|
||||
|
||||
public void epsilon(final float theEpsilon) {
|
||||
_myEpsilon = theEpsilon;
|
||||
}
|
||||
|
||||
public Vector3f min() {
|
||||
return _myMin;
|
||||
}
|
||||
|
||||
public Vector3f max() {
|
||||
return _myMax;
|
||||
}
|
||||
private static final Vector3f[] _myNormals;
|
||||
|
||||
static {
|
||||
_myNormals = new Vector3f[6];
|
||||
_myNormals[0] = new Vector3f(-1, 0, 0);
|
||||
_myNormals[1] = new Vector3f(0, -1, 0);
|
||||
_myNormals[2] = new Vector3f(0, 0, -1);
|
||||
_myNormals[3] = new Vector3f(1, 0, 0);
|
||||
_myNormals[4] = new Vector3f(0, 1, 0);
|
||||
_myNormals[5] = new Vector3f(0, 0, 1);
|
||||
}
|
||||
|
||||
public void coefficientofrestitution(float theCoefficientOfRestitution) {
|
||||
_myCoefficientOfRestitution = theCoefficientOfRestitution;
|
||||
}
|
||||
|
||||
public float coefficientofrestitution() {
|
||||
return _myCoefficientOfRestitution;
|
||||
}
|
||||
|
||||
public void apply(final Physics theParticleSystem) {
|
||||
if (!(theParticleSystem.getIntegrator() instanceof Verlet)) {
|
||||
System.out.println("### WARNING @ " + getClass().getSimpleName() + " / only works with verlet integrator.");
|
||||
}
|
||||
apply(theParticleSystem.particles());
|
||||
}
|
||||
|
||||
public void apply(final Vector<Particle> theParticles) {
|
||||
apply(theParticles, null);
|
||||
}
|
||||
|
||||
public void apply(final Vector<Particle> theParticles, final Vector<Particle> theCollisionParticles) {
|
||||
if (!mActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Particle myParticle : theParticles) {
|
||||
final Vector3f myPositionBeforeCollision = new Vector3f(myParticle.position());
|
||||
final Vector3f p = myParticle.position();
|
||||
final Vector3f p_old = myParticle.old_position();
|
||||
final float r = myParticle.radius();
|
||||
/**
|
||||
* @todo we should weight the deflection normal
|
||||
*/
|
||||
if (p.x + r > _myMax.x
|
||||
|| p.y + r > _myMax.y
|
||||
|| p.z + r > _myMax.z
|
||||
|| p.x - r < _myMin.x
|
||||
|| p.y - r < _myMin.y
|
||||
|| p.z - r < _myMin.z) {
|
||||
int myNumberOfCollisions = 0;
|
||||
final Vector3f myDeflectionNormal = new Vector3f();
|
||||
if (POSITIV_X) {
|
||||
if (p.x + r > _myMax.x) {
|
||||
final float myBorderDiff = _myMax.x - p_old.x - r;
|
||||
p.x = p_old.x + myBorderDiff;
|
||||
myDeflectionNormal.add(_myNormals[0]);
|
||||
myNumberOfCollisions++;
|
||||
}
|
||||
}
|
||||
|
||||
if (POSITIV_Y) {
|
||||
if (p.y + r > _myMax.y) {
|
||||
final float myBorderDiff = _myMax.y - p_old.y - r;
|
||||
p.y = p_old.y + myBorderDiff;
|
||||
myDeflectionNormal.add(_myNormals[1]);
|
||||
myNumberOfCollisions++;
|
||||
}
|
||||
}
|
||||
|
||||
if (POSITIV_Z) {
|
||||
if (p.z + r > _myMax.z) {
|
||||
final float myBorderDiff = _myMax.z - p_old.z - r;
|
||||
p.z = p_old.z + myBorderDiff;
|
||||
myDeflectionNormal.add(_myNormals[2]);
|
||||
myNumberOfCollisions++;
|
||||
}
|
||||
}
|
||||
|
||||
if (NEGATIVE_X) {
|
||||
if (p.x - r < _myMin.x) {
|
||||
final float myBorderDiff = _myMin.x - p_old.x + r;
|
||||
p.x = p_old.x + myBorderDiff;
|
||||
myDeflectionNormal.add(_myNormals[3]);
|
||||
myNumberOfCollisions++;
|
||||
}
|
||||
}
|
||||
|
||||
if (NEGATIVE_Y) {
|
||||
if (p.y - r < _myMin.y) {
|
||||
final float myBorderDiff = _myMin.y - p_old.y + r;
|
||||
p.y = p_old.y + myBorderDiff;
|
||||
myDeflectionNormal.add(_myNormals[4]);
|
||||
myNumberOfCollisions++;
|
||||
}
|
||||
}
|
||||
|
||||
if (NEGATIVE_Z) {
|
||||
if (p.z - r < _myMin.z) {
|
||||
final float myBorderDiff = _myMin.z - p_old.z + r;
|
||||
p.z = p_old.z + myBorderDiff;
|
||||
myDeflectionNormal.add(_myNormals[5]);
|
||||
myNumberOfCollisions++;
|
||||
}
|
||||
}
|
||||
|
||||
if (myNumberOfCollisions > 0) {
|
||||
/* remember collided particles */
|
||||
if (theCollisionParticles != null) {
|
||||
theCollisionParticles.add(myParticle);
|
||||
}
|
||||
/* room for optimization / we don t need to reflect twice. */
|
||||
final float mySpeed = myPositionBeforeCollision.distanceSquared(myParticle.old_position());
|
||||
if (mySpeed > _myEpsilon) {
|
||||
final Vector3f myDiffAfterCollision = mathematik.Util.sub(myPositionBeforeCollision,
|
||||
myParticle.position());
|
||||
final Vector3f myDiffBeforeCollision = mathematik.Util.sub(myParticle.old_position(),
|
||||
myParticle.position());
|
||||
myDeflectionNormal.scale(1.0f / (float) myNumberOfCollisions);
|
||||
teilchen.util.Util.reflect(myDiffAfterCollision, myDeflectionNormal,
|
||||
_myCoefficientOfRestitution);
|
||||
teilchen.util.Util.reflect(myDiffBeforeCollision, myDeflectionNormal, 1);
|
||||
|
||||
if (!myParticle.old_position().isNaN() && !myParticle.position().isNaN()) {
|
||||
myParticle.old_position().add(myParticle.position(), myDiffBeforeCollision);
|
||||
myParticle.position().add(myDiffAfterCollision);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return mActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
mActive = theActiveState;
|
||||
}
|
||||
}
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.constraint;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.IConnection;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class Stick
|
||||
implements IConstraint,
|
||||
IConnection {
|
||||
|
||||
protected final Particle mA;
|
||||
|
||||
protected final Particle mB;
|
||||
|
||||
protected float mRestLength;
|
||||
|
||||
protected final Vector3f mTempDistanceVector;
|
||||
|
||||
protected final Vector3f mTempVector;
|
||||
|
||||
protected boolean mOneWay;
|
||||
|
||||
protected float mDamping;
|
||||
|
||||
protected boolean mActive = true;
|
||||
|
||||
protected static final float EPSILON = 0.0001f;
|
||||
|
||||
public Stick(Particle theA, Particle theB) {
|
||||
this(theA,
|
||||
theB,
|
||||
theA.position().distance(theB.position()));
|
||||
}
|
||||
|
||||
public Stick(final Particle theA,
|
||||
final Particle theB,
|
||||
final float theRestLength) {
|
||||
mRestLength = theRestLength;
|
||||
mA = theA;
|
||||
mB = theB;
|
||||
mTempDistanceVector = new Vector3f();
|
||||
mTempVector = new Vector3f();
|
||||
mOneWay = false;
|
||||
mDamping = 1f;
|
||||
}
|
||||
|
||||
public void setRestLengthByPosition() {
|
||||
mRestLength = mA.position().distance(mB.position());
|
||||
}
|
||||
|
||||
public float damping() {
|
||||
return mDamping;
|
||||
}
|
||||
|
||||
public void damping(float theDamping) {
|
||||
mDamping = theDamping;
|
||||
}
|
||||
|
||||
public float restlength() {
|
||||
return mRestLength;
|
||||
}
|
||||
|
||||
public void restlength(float theRestLength) {
|
||||
mRestLength = theRestLength;
|
||||
}
|
||||
|
||||
public final Particle a() {
|
||||
return mA;
|
||||
}
|
||||
|
||||
public final Particle b() {
|
||||
return mB;
|
||||
}
|
||||
|
||||
public void setOneWay(boolean theOneWayState) {
|
||||
mOneWay = theOneWayState;
|
||||
}
|
||||
|
||||
public void apply(Physics theParticleSystem) {
|
||||
if (!mActive) {
|
||||
return;
|
||||
}
|
||||
if (mA.fixed() && mB.fixed()) {
|
||||
return;
|
||||
}
|
||||
mTempDistanceVector.sub(mA.position(), mB.position());
|
||||
final float myDistanceSquared = mTempDistanceVector.lengthSquared();
|
||||
if (myDistanceSquared > 0) {
|
||||
final float myDistance = (float) Math.sqrt(myDistanceSquared);
|
||||
final float myDifference = mRestLength - myDistance;
|
||||
if (myDifference > EPSILON || myDifference < -EPSILON) {
|
||||
if (!mOneWay) {
|
||||
final float myDifferenceScale = mDamping * 0.5f * myDifference / myDistance;
|
||||
mTempVector.scale(myDifferenceScale, mTempDistanceVector);
|
||||
if (mA.fixed()) {
|
||||
mB.position().sub(mTempVector);
|
||||
mB.position().sub(mTempVector);
|
||||
} else if (mB.fixed()) {
|
||||
mA.position().add(mTempVector);
|
||||
mA.position().add(mTempVector);
|
||||
} else {
|
||||
mA.position().add(mTempVector);
|
||||
mB.position().sub(mTempVector);
|
||||
}
|
||||
} else {
|
||||
final float myDifferenceScale = myDifference / myDistance;
|
||||
mTempVector.scale(myDifferenceScale, mTempDistanceVector);
|
||||
mB.position().sub(mTempVector);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mA.fixed()) {
|
||||
mB.position().set(mA.position());
|
||||
mB.position().x += mRestLength;
|
||||
} else if (mB.fixed()) {
|
||||
mA.position().set(mB.position());
|
||||
mA.position().x += mRestLength;
|
||||
} else {
|
||||
mB.position().set(mA.position());
|
||||
mA.position().x -= mRestLength / 2;
|
||||
mB.position().x += mRestLength / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return mActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
mActive = theActiveState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.constraint;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class Teleporter
|
||||
implements IConstraint {
|
||||
|
||||
protected boolean mActive = true;
|
||||
|
||||
private final Vector3f mMin;
|
||||
|
||||
private final Vector3f mMax;
|
||||
|
||||
public Teleporter() {
|
||||
this(new Vector3f(), new Vector3f());
|
||||
}
|
||||
|
||||
public Teleporter(final Vector3f pMin, final Vector3f pMax) {
|
||||
mMin = new Vector3f(pMin);
|
||||
mMax = new Vector3f(pMax);
|
||||
}
|
||||
|
||||
public Vector3f max() {
|
||||
return mMax;
|
||||
}
|
||||
|
||||
public Vector3f min() {
|
||||
return mMin;
|
||||
}
|
||||
|
||||
public void apply(Physics theParticleSystem) {
|
||||
if (!mActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Particle mParticle : theParticleSystem.particles()) {
|
||||
if (mParticle.position().x > mMax.x) {
|
||||
mParticle.position().x -= Math.abs(mMax.x - mMin.x);
|
||||
}
|
||||
if (mParticle.position().y > mMax.y) {
|
||||
mParticle.position().y -= Math.abs(mMax.y - mMin.y);
|
||||
}
|
||||
if (mParticle.position().z > mMax.z) {
|
||||
mParticle.position().z -= Math.abs(mMax.z - mMin.z);
|
||||
}
|
||||
if (mParticle.position().x < mMin.x) {
|
||||
mParticle.position().x += Math.abs(mMax.x - mMin.x);
|
||||
}
|
||||
if (mParticle.position().y < mMin.y) {
|
||||
mParticle.position().y += Math.abs(mMax.y - mMin.y);
|
||||
}
|
||||
if (mParticle.position().z < mMin.z) {
|
||||
mParticle.position().z += Math.abs(mMax.z - mMin.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return mActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
mActive = theActiveState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.cubicle;
|
||||
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import mathematik.Vector3i;
|
||||
|
||||
|
||||
/*
|
||||
* container class for ICubicleEntity representing one cube in the world.
|
||||
*/
|
||||
public class CubicleAtom {
|
||||
|
||||
private Vector<ICubicleEntity> mContainer;
|
||||
|
||||
private final Vector3i mPosition;
|
||||
|
||||
public CubicleAtom(int x, int y, int z) {
|
||||
mContainer = new Vector<ICubicleEntity>();
|
||||
mPosition = new Vector3i(x, y, z);
|
||||
}
|
||||
|
||||
public Vector3i position() {
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
public void add(ICubicleEntity theEntity) {
|
||||
mContainer.add(theEntity);
|
||||
}
|
||||
|
||||
public boolean remove(ICubicleEntity theEntity) {
|
||||
return mContainer.remove(theEntity);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
mContainer.clear();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return mContainer.size();
|
||||
}
|
||||
|
||||
public Vector<ICubicleEntity> data() {
|
||||
return mContainer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.cubicle;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import mathematik.Vector3i;
|
||||
|
||||
|
||||
public class CubicleEntity
|
||||
implements ICubicleEntity {
|
||||
|
||||
private Vector3i _myCubiclePosition;
|
||||
|
||||
private final Vector3f _myPosition;
|
||||
|
||||
public CubicleEntity() {
|
||||
_myCubiclePosition = new Vector3i();
|
||||
_myPosition = new Vector3f();
|
||||
}
|
||||
|
||||
public Vector3i cubicle() {
|
||||
return _myCubiclePosition;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return _myPosition;
|
||||
}
|
||||
|
||||
public boolean leaving(int theX, int theY, int theZ) {
|
||||
if (theX == cubicle().x
|
||||
&& theY == cubicle().y
|
||||
&& theZ == cubicle().z) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.cubicle;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import mathematik.Vector3i;
|
||||
|
||||
import teilchen.BasicParticle;
|
||||
|
||||
|
||||
public class CubicleParticle
|
||||
extends BasicParticle implements ICubicleEntity {
|
||||
|
||||
private final Vector3i _myCubiclePosition;
|
||||
|
||||
private final Vector3f _myPosition;
|
||||
|
||||
public CubicleParticle() {
|
||||
_myCubiclePosition = new Vector3i();
|
||||
_myPosition = new Vector3f();
|
||||
}
|
||||
|
||||
public Vector3i cubicle() {
|
||||
return _myCubiclePosition;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return _myPosition;
|
||||
}
|
||||
|
||||
public boolean leaving(int theX, int theY, int theZ) {
|
||||
if (theX == cubicle().x
|
||||
&& theY == cubicle().y
|
||||
&& theZ == cubicle().z) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return !fixed();
|
||||
}
|
||||
}
|
||||
+302
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.cubicle;
|
||||
|
||||
|
||||
import mathematik.TransformMatrix4f;
|
||||
import mathematik.Vector3f;
|
||||
import mathematik.Vector3i;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/*
|
||||
* cubicle world handles entities and queries about a cubicles state.
|
||||
*/
|
||||
public class CubicleWorld {
|
||||
|
||||
public static final int OFF_WORLD = -1;
|
||||
|
||||
private CubicleAtom[][][] mWorld;
|
||||
|
||||
private CubicleAtom mOffWorld;
|
||||
|
||||
private TransformMatrix4f mTransform;
|
||||
|
||||
private Vector3f mScale;
|
||||
|
||||
private Vector<ICubicleEntity> mEntites;
|
||||
|
||||
public CubicleWorld(Vector3i theNumberOfAtoms) {
|
||||
this(theNumberOfAtoms.x, theNumberOfAtoms.y, theNumberOfAtoms.z);
|
||||
}
|
||||
|
||||
public CubicleWorld(int theNumberOfXAtoms,
|
||||
int theNumberOfYAtoms,
|
||||
int theNumberOfZAtoms) {
|
||||
initializeAtoms(theNumberOfXAtoms, theNumberOfYAtoms, theNumberOfZAtoms);
|
||||
mTransform = new TransformMatrix4f(TransformMatrix4f.IDENTITY);
|
||||
mScale = new Vector3f(1, 1, 1);
|
||||
mEntites = new Vector<ICubicleEntity>();
|
||||
}
|
||||
|
||||
private void initializeAtoms(int theNumberOfXAtoms,
|
||||
int theNumberOfYAtoms,
|
||||
int theNumberOfZAtoms) {
|
||||
mWorld = new CubicleAtom[theNumberOfXAtoms][theNumberOfYAtoms][theNumberOfZAtoms];
|
||||
for (int x = 0; x < mWorld.length; x++) {
|
||||
for (int y = 0; y < mWorld[x].length; y++) {
|
||||
for (int z = 0; z < mWorld[x][y].length; z++) {
|
||||
mWorld[x][y][z] = new CubicleAtom(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
mOffWorld = new CubicleAtom(OFF_WORLD, OFF_WORLD, OFF_WORLD);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
Iterator<ICubicleEntity> myIterator = mEntites.iterator();
|
||||
while (myIterator.hasNext()) {
|
||||
handleEntity(myIterator.next());
|
||||
}
|
||||
}
|
||||
|
||||
public void add(ICubicleEntity theEntity) {
|
||||
mEntites.add(theEntity);
|
||||
theEntity.cubicle().set(OFF_WORLD, OFF_WORLD, OFF_WORLD);
|
||||
mOffWorld.add(theEntity);
|
||||
}
|
||||
|
||||
public boolean remove(ICubicleEntity theEntity) {
|
||||
return removeFromCubicle(theEntity) && mEntites.remove(theEntity);
|
||||
}
|
||||
|
||||
public void handleEntity(ICubicleEntity theEntity) {
|
||||
if (theEntity.isActive()) {
|
||||
|
||||
/* transform entity position into cubicle world space */
|
||||
|
||||
final Vector3i myIndex = worldposition2index(theEntity.position());
|
||||
|
||||
/* handle entites position in cubicle grid */
|
||||
if (checkBounds(myIndex.x, myIndex.y, myIndex.z)) {
|
||||
if (theEntity.leaving(myIndex.x, myIndex.y, myIndex.z)) {
|
||||
/* remove from previous cubicles */
|
||||
if (!removeFromCubicle(theEntity)) {
|
||||
System.err.println("### ERROR @ CubicleWorld / removing entity / inworld");
|
||||
}
|
||||
/* add to current cubicle */
|
||||
mWorld[myIndex.x][myIndex.y][myIndex.z].add(theEntity);
|
||||
/* store cubicle */
|
||||
theEntity.cubicle().set(myIndex.x, myIndex.y, myIndex.z);
|
||||
}
|
||||
} else {
|
||||
if (theEntity.leaving(OFF_WORLD, OFF_WORLD, OFF_WORLD)) {
|
||||
/* remove from cubicles */
|
||||
if (!removeFromCubicle(theEntity)) {
|
||||
System.err.println("### ERROR @ CubicleWorld / removing entity / offworld");
|
||||
}
|
||||
/* add to off world */
|
||||
mOffWorld.add(theEntity);
|
||||
|
||||
/* store cubicle */
|
||||
theEntity.cubicle().set(OFF_WORLD, OFF_WORLD, OFF_WORLD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Vector<ICubicleEntity> getLocalEntities(Vector3f thePosition) {
|
||||
final Vector3i myIndex = worldposition2index(thePosition);
|
||||
if (checkBounds(myIndex.x, myIndex.y, myIndex.z)) {
|
||||
final CubicleAtom myCubicleAtom = getAtom(myIndex.x, myIndex.y, myIndex.z);
|
||||
return myCubicleAtom.data();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Vector<ICubicleEntity> getLocalEntities(ICubicleEntity theEntity) {
|
||||
final Vector3i myIndex = theEntity.cubicle();
|
||||
return getAtom(myIndex.x, myIndex.y, myIndex.z).data();
|
||||
}
|
||||
|
||||
public Vector<ICubicleEntity> getLocalEntities(Vector3f thePosition, int pExtraRadius) {
|
||||
return getLocalEntities(thePosition, pExtraRadius, pExtraRadius, pExtraRadius);
|
||||
}
|
||||
|
||||
public Vector<ICubicleEntity> getLocalEntities(Vector3f thePosition,
|
||||
int theXRadius,
|
||||
int theYRadius,
|
||||
int theZRadius) {
|
||||
final Vector3i myIndex = worldposition2index(thePosition);
|
||||
if (checkBounds(myIndex.x, myIndex.y, myIndex.z)) {
|
||||
final Vector<CubicleAtom> mAtoms = getAtoms(myIndex.x,
|
||||
myIndex.y,
|
||||
myIndex.z,
|
||||
theXRadius,
|
||||
theYRadius,
|
||||
theZRadius);
|
||||
final Vector<ICubicleEntity> mEntities = new Vector<ICubicleEntity>();
|
||||
for (CubicleAtom a : mAtoms) {
|
||||
mEntities.addAll(a.data());
|
||||
}
|
||||
return mEntities.isEmpty() ? null : mEntities;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector<ICubicleEntity> getLocalEntities(ICubicleEntity theEntity,
|
||||
int theXRadius,
|
||||
int theYRadius,
|
||||
int theZRadius) {
|
||||
final Vector3i myIndex = theEntity.cubicle();
|
||||
final Vector<CubicleAtom> mAtoms = getAtoms(myIndex.x,
|
||||
myIndex.y,
|
||||
myIndex.z,
|
||||
theXRadius,
|
||||
theYRadius,
|
||||
theZRadius);
|
||||
final Vector<ICubicleEntity> mEntities = new Vector<ICubicleEntity>();
|
||||
for (CubicleAtom a : mAtoms) {
|
||||
mEntities.addAll(a.data());
|
||||
}
|
||||
return mEntities.isEmpty() ? null : mEntities;
|
||||
}
|
||||
|
||||
public Vector<ICubicleEntity> entities() {
|
||||
return mEntites;
|
||||
}
|
||||
|
||||
public Vector3i worldposition2index(Vector3f thePosition) {
|
||||
/* get position */
|
||||
final Vector3f myPosition = new Vector3f(thePosition);
|
||||
|
||||
/* translation */
|
||||
myPosition.sub(mTransform.translation);
|
||||
|
||||
/* rotation */
|
||||
mTransform.rotation.transform(myPosition);
|
||||
|
||||
/* scale */
|
||||
myPosition.divide(mScale);
|
||||
|
||||
/* round off */
|
||||
final Vector3i myIndex = new Vector3i((int) Math.floor(myPosition.x),
|
||||
(int) Math.floor(myPosition.y),
|
||||
(int) Math.floor(myPosition.z));
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
private boolean removeFromCubicle(ICubicleEntity theEntity) {
|
||||
if (theEntity.cubicle().x == OFF_WORLD
|
||||
&& theEntity.cubicle().y == OFF_WORLD
|
||||
&& theEntity.cubicle().z == OFF_WORLD) {
|
||||
/* was stored in the offworld cubicle */
|
||||
return mOffWorld.remove(theEntity);
|
||||
} else {
|
||||
if (checkBounds(theEntity.cubicle().x, theEntity.cubicle().y, theEntity.cubicle().z)) {
|
||||
/* was stored in a cubicle */
|
||||
return mWorld[theEntity.cubicle().x][theEntity.cubicle().y][theEntity.cubicle().z].remove(theEntity);
|
||||
} else {
|
||||
/* values were invalid */
|
||||
System.out.println("### WARNING @ CubicleWorld / couldn t remove entity");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkBounds(int theX,
|
||||
int theY,
|
||||
int theZ) {
|
||||
if (theX < mWorld.length && theX >= 0) {
|
||||
if (theY < mWorld[theX].length && theY >= 0) {
|
||||
if (theZ < mWorld[theX][theY].length && theZ >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public CubicleAtom getAtom(int theX,
|
||||
int theY,
|
||||
int theZ) {
|
||||
if (checkBounds(theX, theY, theZ)) {
|
||||
return mWorld[theX][theY][theZ];
|
||||
} else {
|
||||
return mOffWorld;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector<CubicleAtom> getAtoms(int theX,
|
||||
int theY,
|
||||
int theZ,
|
||||
int theXRadius,
|
||||
int theYRadius,
|
||||
int theZRadius) {
|
||||
Vector<CubicleAtom> myAtoms = new Vector<CubicleAtom>();
|
||||
for (int z = -theZRadius; z < theZRadius + 1; ++z) {
|
||||
for (int y = -theYRadius; y < theYRadius + 1; ++y) {
|
||||
for (int x = -theXRadius; x < theXRadius + 1; ++x) {
|
||||
int myX = theX + x;
|
||||
int myY = theY + y;
|
||||
int myZ = theZ + z;
|
||||
if (checkBounds(myX, myY, myZ) && mWorld[myX][myY][myZ].size() > 0) {
|
||||
myAtoms.add(mWorld[myX][myY][myZ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return myAtoms;
|
||||
}
|
||||
|
||||
public Vector3f cellscale() {
|
||||
return mScale;
|
||||
}
|
||||
|
||||
public TransformMatrix4f transform() {
|
||||
return mTransform;
|
||||
}
|
||||
|
||||
public CubicleAtom[][][] getDataRef() {
|
||||
return mWorld;
|
||||
}
|
||||
|
||||
public Vector<ICubicleEntity> getEntities() {
|
||||
return mEntites;
|
||||
}
|
||||
|
||||
public CubicleAtom getOffWorldAtom() {
|
||||
return mOffWorld;
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
final Iterator<ICubicleEntity> iter = mEntites.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final ICubicleEntity c = iter.next();
|
||||
removeFromCubicle(c);
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.cubicle;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import mathematik.Vector3i;
|
||||
|
||||
|
||||
public interface ICubicleEntity {
|
||||
|
||||
/**
|
||||
* get reference to the cubicle id
|
||||
*
|
||||
* @return Vector3i
|
||||
*/
|
||||
Vector3i cubicle();
|
||||
|
||||
/**
|
||||
* get reference to position vector
|
||||
*
|
||||
* @return Vector3f
|
||||
*/
|
||||
Vector3f position();
|
||||
|
||||
/**
|
||||
* returns true if the new position don t match the previously stored
|
||||
* position
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean leaving(int theX, int theY, int theZ);
|
||||
|
||||
/**
|
||||
* entities can be temporarily removed from the process of being updated by
|
||||
* the world.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isActive();
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch show how to create a particle system with a single particle in
|
||||
* it.
|
||||
*/
|
||||
public class Lesson00_Particle
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Particle mParticle;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system. */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/*
|
||||
* a physic-based particle system consists of a few components.
|
||||
*
|
||||
* 1 particles.
|
||||
* there are different kinds of particles. for now we use a simple particle.
|
||||
*
|
||||
* 2 forces.
|
||||
* there are all kinds of forces. one of the most obvious force is the gravitational force,
|
||||
* but there all kinds of different forces like attractors and springs. forces usually
|
||||
* affect all particles in the system.
|
||||
*
|
||||
* 3 behaviors
|
||||
* a behavior is special kind of force. it is something like an internal force or a motor
|
||||
* that only affects a single particle. a typical force is for example the 'seek force'
|
||||
* which constantly pulls a particle into a certain direction.
|
||||
*
|
||||
* 4 integrators.
|
||||
* integrators are used to integrate acceleration and velocity to calculate the new position.
|
||||
* the most well-known is the 'euler' integrator, but there are also optimized versions like 'runge-kutta'
|
||||
* or 'Midpoint' or even slightly different concepts like 'verlet'.
|
||||
*
|
||||
*/
|
||||
|
||||
/* create a particle. note that the particle is automatically added to particle system */
|
||||
mParticle = mPhysics.makeParticle();
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* update the particle system to the next step. usually the time step is the duration of the las frame */
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw particle */
|
||||
background(255);
|
||||
stroke(0, 127);
|
||||
fill(0, 32);
|
||||
ellipse(mParticle.position().x, mParticle.position().y, 12, 12);
|
||||
|
||||
/* reset particle s position and velocity */
|
||||
if (mousePressed) {
|
||||
mParticle.position().set(mouseX, mouseY);
|
||||
mParticle.velocity().set(mouseX - pmouseX, mouseY - pmouseY);
|
||||
mParticle.velocity().scale(10);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson00_Particle.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Gravity;
|
||||
import processing.core.PApplet;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch show how to create a particle system with a single particle in
|
||||
* it.
|
||||
*/
|
||||
public class Lesson01_Gravity
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Particle mParticle;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a gravitational force */
|
||||
Gravity mGravity = new Gravity();
|
||||
/* the direction of the gravity is defined by the 'force' vector */
|
||||
mGravity.force().set(0, 30, 0);
|
||||
/* forces, like gravity or any other force, can be added to the system. they will be automatically applied to all particles */
|
||||
mPhysics.add(mGravity);
|
||||
|
||||
/* create a particle and add it to the system */
|
||||
mParticle = mPhysics.makeParticle();
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* update the particle system. this applies the gravity to the particle */
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw particle */
|
||||
background(255);
|
||||
stroke(0, 127);
|
||||
fill(0, 32);
|
||||
ellipse(mParticle.position().x, mParticle.position().y, 12, 12);
|
||||
|
||||
/* reset particle s position and velocity */
|
||||
if (mousePressed) {
|
||||
mParticle.position().set(mouseX, mouseY);
|
||||
mParticle.velocity().set(mouseX - pmouseX, mouseY - pmouseY);
|
||||
mParticle.velocity().scale(10);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson01_Gravity.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Gravity;
|
||||
import processing.core.PApplet;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch shows how to create and handle multiple particles and remove
|
||||
* individual particles.
|
||||
*/
|
||||
public class Lesson02_Particles
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a gravitational force and add it to the particle system */
|
||||
Gravity myGravity = new Gravity(0, 30, 0);
|
||||
mPhysics.add(myGravity);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
if (mousePressed) {
|
||||
/* create and add a particle to the system */
|
||||
Particle mParticle = mPhysics.makeParticle();
|
||||
/* set particle to mouse position with random velocity */
|
||||
mParticle.position().set(mouseX, mouseY);
|
||||
mParticle.velocity().set(random(-20, 20), random(-50));
|
||||
}
|
||||
|
||||
/* update the particle system */
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* remove particles right before they hit the edge of the screen */
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
Particle mParticle = mPhysics.particles(i);
|
||||
if (mParticle.position().y > height * 0.9f) {
|
||||
mPhysics.particles().remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw all the particles in the system */
|
||||
background(255);
|
||||
stroke(0, 127);
|
||||
fill(0, 32);
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
Particle mParticle = mPhysics.particles(i);
|
||||
ellipse(mParticle.position().x, mParticle.position().y, 10, 10);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson02_Particles.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.Teleporter;
|
||||
import teilchen.force.Attractor;
|
||||
import teilchen.force.ViscousDrag;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch shows how to create and use attractors.
|
||||
*/
|
||||
public class Lesson03_Attractors
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Attractor mAttractor;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a viscous force that slows down all motion */
|
||||
ViscousDrag myDrag = new ViscousDrag();
|
||||
myDrag.coefficient = 0.75f;
|
||||
mPhysics.add(myDrag);
|
||||
|
||||
/* teleport particles from one edge of the screen to the other */
|
||||
Teleporter mTeleporter = new Teleporter();
|
||||
mTeleporter.min().set(0, 0);
|
||||
mTeleporter.max().set(width, height);
|
||||
mPhysics.add(mTeleporter);
|
||||
|
||||
/* create some particles */
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Particle myParticle = mPhysics.makeParticle();
|
||||
myParticle.position().set(random(width), random(height));
|
||||
}
|
||||
mPhysics.particles().firstElement().fixed(true);
|
||||
|
||||
/* create an attractor */
|
||||
mAttractor = new Attractor();
|
||||
mAttractor.radius(100);
|
||||
mAttractor.strength(150);
|
||||
mPhysics.add(mAttractor);
|
||||
}
|
||||
|
||||
public void mousePressed() {
|
||||
/* flip the direction of the attractors strength. */
|
||||
float myInvertedStrength = -1 * mAttractor.strength();
|
||||
/* a negative strength turns the attractor into a repulsor */
|
||||
mAttractor.strength(myInvertedStrength);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* set attractor to mouse position */
|
||||
mAttractor.position().set(mouseX, mouseY);
|
||||
|
||||
/* update the particle system */
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw */
|
||||
background(255);
|
||||
|
||||
/* draw all the particles in particle system */
|
||||
fill(245);
|
||||
stroke(164);
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
Particle myParticle = mPhysics.particles(i);
|
||||
ellipse(myParticle.position().x, myParticle.position().y, 12, 12);
|
||||
}
|
||||
|
||||
/* draw attractor. green if it is attracting and red if it is repelling */
|
||||
noStroke();
|
||||
if (mAttractor.strength() < 0) {
|
||||
fill(255, 0, 0, 50);
|
||||
} else {
|
||||
fill(0, 255, 0, 50);
|
||||
}
|
||||
ellipse(mAttractor.position().x, mAttractor.position().y,
|
||||
mAttractor.radius(), mAttractor.radius());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson03_Attractors.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.ShortLivedParticle;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.PlaneDeflector;
|
||||
import teilchen.force.ViscousDrag;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch shows 1 how to create and use plane deflectors 2 how to use
|
||||
* 'ShortLivedParticle'
|
||||
*/
|
||||
public class Lesson04_Deflectors
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private PlaneDeflector mDeflector;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a deflector and add it to the particle system.
|
||||
* the that defines the deflection area is defined by an
|
||||
* origin and a normal. this also means that the plane s size
|
||||
* is infinite.
|
||||
* note that there is also a triangle delfector that is constraint
|
||||
* by three points.
|
||||
*/
|
||||
mDeflector = new PlaneDeflector();
|
||||
/* set plane origin into the center of the screen */
|
||||
mDeflector.plane().origin.set(width / 2, height / 2, 0);
|
||||
mDeflector.plane().normal.set(0, -1, 0);
|
||||
/* the coefficient of restitution defines how hard particles bounce of the deflector */
|
||||
mDeflector.coefficientofrestitution(0.7f);
|
||||
mPhysics.add(mDeflector);
|
||||
|
||||
/* create gravitiy */
|
||||
Gravity myGravity = new Gravity();
|
||||
myGravity.force().y = 50;
|
||||
mPhysics.add(myGravity);
|
||||
|
||||
/* create drag */
|
||||
ViscousDrag myViscousDrag = new ViscousDrag();
|
||||
myViscousDrag.coefficient = 0.1f;
|
||||
mPhysics.add(myViscousDrag);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* rotate deflector plane */
|
||||
if (mousePressed) {
|
||||
final float myAngle = 2 * PI * (float) mouseX / width - PI;
|
||||
mDeflector.plane().normal.set(sin(myAngle), -cos(myAngle), 0);
|
||||
}
|
||||
|
||||
/* create a special particle */
|
||||
ShortLivedParticle myNewParticle = new ShortLivedParticle();
|
||||
myNewParticle.position().set(mouseX, mouseY);
|
||||
myNewParticle.velocity().set(0, random(100) + 50);
|
||||
/* this particle is removed after a specific interval */
|
||||
myNewParticle.setMaxAge(4);
|
||||
/* add particle manually to the particle system */
|
||||
mPhysics.add(myNewParticle);
|
||||
|
||||
/* update physics */
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw all the particles in the particle system */
|
||||
background(255);
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
Particle myParticle = mPhysics.particles(i);
|
||||
/* this special particle can tell you how much time it has to live.
|
||||
* we map this information to its transparency.
|
||||
*/
|
||||
float myRatio = 1 - ((ShortLivedParticle) myParticle).ageRatio();
|
||||
stroke(0, 64 * myRatio);
|
||||
fill(0, 32 * myRatio);
|
||||
ellipse(myParticle.position().x, myParticle.position().y, 12, 12);
|
||||
}
|
||||
|
||||
/* draw deflector */
|
||||
stroke(0, 127);
|
||||
line(mDeflector.plane().origin.x - mDeflector.plane().normal.y * -width,
|
||||
mDeflector.plane().origin.y + mDeflector.plane().normal.x * -width,
|
||||
mDeflector.plane().origin.x - mDeflector.plane().normal.y * width,
|
||||
mDeflector.plane().origin.y + mDeflector.plane().normal.x * width);
|
||||
|
||||
stroke(255, 0, 0, 127);
|
||||
line(mDeflector.plane().origin.x,
|
||||
mDeflector.plane().origin.y,
|
||||
mDeflector.plane().origin.x + mDeflector.plane().normal.x * 20,
|
||||
mDeflector.plane().origin.y + mDeflector.plane().normal.y * 20);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson04_Deflectors.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch shows 1 how to create a viscous drag to slow motion eventually
|
||||
* down. 2 how to create a spring that connects two particles.
|
||||
*/
|
||||
public class Lesson05_Spring
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Spring mSpring;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a viscous force that slows down all motion; 0 means no slowing down. */
|
||||
ViscousDrag myDrag = new ViscousDrag(0.25f);
|
||||
mPhysics.add(myDrag);
|
||||
|
||||
/* create two particles that we can connect with a spring */
|
||||
Particle myA = mPhysics.makeParticle();
|
||||
myA.position().set(width / 2 - 50, height / 2);
|
||||
|
||||
Particle myB = mPhysics.makeParticle();
|
||||
myB.position().set(width / 2 + 50, height / 2);
|
||||
|
||||
/* create a spring force that connects two particles.
|
||||
* note that there is more than one way to create a spring.
|
||||
* in our case the restlength of the spring is defined by the
|
||||
* particles current position.
|
||||
*/
|
||||
mSpring = mPhysics.makeSpring(myA, myB);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* set first particle to mouse position */
|
||||
if (mousePressed) {
|
||||
mSpring.a().position().set(mouseX, mouseY);
|
||||
}
|
||||
|
||||
/* update the particle system */
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw particles and connecting line */
|
||||
background(255);
|
||||
noFill();
|
||||
stroke(255, 0, 127, 64);
|
||||
line(mSpring.a().position().x, mSpring.a().position().y,
|
||||
mSpring.b().position().x, mSpring.b().position().y);
|
||||
fill(245);
|
||||
stroke(164);
|
||||
ellipse(mSpring.a().position().x, mSpring.a().position().y, 12, 12);
|
||||
ellipse(mSpring.b().position().x, mSpring.b().position().y, 12, 12);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson05_Spring.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Spring;
|
||||
import processing.core.PApplet;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch shows 1 how to create a viscous drag to slow motion eventually
|
||||
* down. 2 how to create a spring that connects two particles.
|
||||
*/
|
||||
public class Lesson06_Springs
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Particle mRoot;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a particle to which we will connect springs */
|
||||
mRoot = mPhysics.makeParticle(width / 2, height / 2, 0.0f);
|
||||
/* we give the root particle a higher mass so it doesn t move as easily */
|
||||
mRoot.mass(30);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* create a particle at mouse position and connect it to the root particle through a spring */
|
||||
if (mousePressed) {
|
||||
Particle mParticle = mPhysics.makeParticle(mouseX, mouseY, 0);
|
||||
Spring mSpring = mPhysics.makeSpring(mRoot, mParticle);
|
||||
/* restlength defines the desired length of the spring. in this case it is the distance between the two particles. */
|
||||
float mRestlength = mSpring.restlength();
|
||||
/* we modify the restlength to add a bit of energy into the system */
|
||||
mSpring.restlength(mRestlength * 1.5f);
|
||||
}
|
||||
|
||||
/* update the particle system */
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw particles and connecting line */
|
||||
background(255);
|
||||
|
||||
/* draw springs */
|
||||
noFill();
|
||||
stroke(255, 0, 127, 64);
|
||||
for (int i = 0; i < mPhysics.forces().size(); i++) {
|
||||
if (mPhysics.forces().get(i) instanceof Spring) {
|
||||
Spring mSSpring = (Spring) mPhysics.forces().get(i);
|
||||
line(mSSpring.a().position().x, mSSpring.a().position().y,
|
||||
mSSpring.b().position().x, mSSpring.b().position().y);
|
||||
}
|
||||
}
|
||||
/* draw particles */
|
||||
fill(245);
|
||||
stroke(164);
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
ellipse(mPhysics.particles().get(i).position().x,
|
||||
mPhysics.particles().get(i).position().y,
|
||||
12, 12);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson06_Springs.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.util.DrawLib;
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Particle;
|
||||
import teilchen.constraint.Box;
|
||||
import teilchen.integration.RungeKutta;
|
||||
import teilchen.util.StableSpringQuad;
|
||||
|
||||
|
||||
public class Lesson07_StableQuads
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Particle mRoot;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(60);
|
||||
|
||||
mPhysics = new Physics();
|
||||
/* we use 'runge kutta' as it is more stable for this application */
|
||||
mPhysics.setInegratorRef(new RungeKutta());
|
||||
|
||||
Gravity myGravity = new Gravity();
|
||||
myGravity.force().y = 98.1f;
|
||||
mPhysics.add(myGravity);
|
||||
|
||||
/* add drag to smooth the spring interaction */
|
||||
mPhysics.add(new ViscousDrag(0.2f));
|
||||
|
||||
/* add a container */
|
||||
Box myBox = new Box();
|
||||
myBox.min().set(0, 0, 0);
|
||||
myBox.max().set(width, height, 0);
|
||||
mPhysics.add(myBox);
|
||||
|
||||
/* create root */
|
||||
Particle a = mPhysics.makeParticle(0, 0);
|
||||
Particle b = mPhysics.makeParticle(100, 0);
|
||||
Particle c = mPhysics.makeParticle(100, 100);
|
||||
Particle d = mPhysics.makeParticle(0, 100);
|
||||
|
||||
new StableSpringQuad(mPhysics, d, c, mPhysics.makeParticle(100, 200), mPhysics.makeParticle(0, 200));
|
||||
|
||||
/* create stable quad from springs */
|
||||
/* first the edge-springs ... */
|
||||
final float mySpringConstant = 100;
|
||||
final float mySpringDamping = 5;
|
||||
mPhysics.makeSpring(a, b, mySpringConstant, mySpringDamping);
|
||||
mPhysics.makeSpring(b, c, mySpringConstant, mySpringDamping);
|
||||
mPhysics.makeSpring(c, d, mySpringConstant, mySpringDamping);
|
||||
mPhysics.makeSpring(d, a, mySpringConstant, mySpringDamping).restlength();
|
||||
/* ... then the diagonal-springs */
|
||||
mPhysics.makeSpring(a, c, mySpringConstant, mySpringDamping);
|
||||
mPhysics.makeSpring(b, d, mySpringConstant, mySpringDamping).restlength();
|
||||
|
||||
/* define 'a' as root particle for mouse interaction */
|
||||
mRoot = a;
|
||||
mRoot.fixed(true);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
|
||||
/* handle particles */
|
||||
if (mousePressed) {
|
||||
mRoot.fixed(true);
|
||||
mRoot.position().set(mouseX, mouseY);
|
||||
} else {
|
||||
mRoot.fixed(false);
|
||||
}
|
||||
|
||||
mPhysics.step(1f / frameRate);
|
||||
|
||||
/* draw */
|
||||
background(255);
|
||||
DrawLib.drawSprings(g, mPhysics, color(255, 0, 127, 64));
|
||||
DrawLib.drawParticles(g, mPhysics, 12, color(164), color(245));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson07_StableQuads.class.getName()});
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.Stick;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.integration.Verlet;
|
||||
import processing.core.PApplet;
|
||||
|
||||
|
||||
public class Lesson08_Sticks
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Particle[] mParticles;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
frameRate(60);
|
||||
smooth();
|
||||
|
||||
mPhysics = new Physics();
|
||||
/* increase the number of iterations for contraints in each step. this can greatly relaxes tensions in the system. */
|
||||
mPhysics.contraint_iterations_per_steps = 5;
|
||||
|
||||
/* add gravity for extra fun */
|
||||
mPhysics.add(new Gravity());
|
||||
|
||||
/* we chose verlet integration as it integrates much more nicely with sticks ( and constraints in general ) */
|
||||
Verlet myVerlet = new Verlet();
|
||||
myVerlet.damping(0.99f);
|
||||
mPhysics.setInegratorRef(myVerlet);
|
||||
|
||||
/* setup sticks to form a whip */
|
||||
mParticles = new Particle[16];
|
||||
float mSegmentLength = 20.0f;
|
||||
/* create root */
|
||||
for (int x = 0; x < mParticles.length; x++) {
|
||||
mParticles[x] = mPhysics.makeParticle(x * mSegmentLength, 0, 0, 0.1f);
|
||||
if (x > 0) {
|
||||
Stick myStick = new Stick(mParticles[x - 1],
|
||||
mParticles[x],
|
||||
mSegmentLength);
|
||||
/* damp the stick to release tensions from the system */
|
||||
myStick.damping(0.99f);
|
||||
mPhysics.add(myStick);
|
||||
}
|
||||
}
|
||||
|
||||
/* fix root particle so it can stick to the mouse later */
|
||||
mParticles[0].fixed(true);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* stick root particle to mouse */
|
||||
mParticles[0].position().set(mouseX, mouseY);
|
||||
|
||||
/* update */
|
||||
mPhysics.step(1.0f / frameRate);
|
||||
|
||||
/* draw sticks with descending stroke weight */
|
||||
background(255);
|
||||
stroke(0, 192);
|
||||
for (int x = 1; x < mParticles.length; x++) {
|
||||
Particle p1 = mParticles[x - 1];
|
||||
Particle p2 = mParticles[x];
|
||||
final float mStrokeWeight = 4.0f * (1.0f - (float) x / mParticles.length);
|
||||
strokeWeight(mStrokeWeight);
|
||||
line(p1.position().x, p1.position().y, p1.position().z,
|
||||
p2.position().x, p2.position().y, p2.position().z);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson08_Sticks.class.getName()});
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.IConstraint;
|
||||
import teilchen.constraint.Stick;
|
||||
import teilchen.force.Attractor;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.integration.Verlet;
|
||||
|
||||
|
||||
public class Lesson09_Cloth
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Particle[][] mParticles;
|
||||
|
||||
private final int GRID_WIDTH = 32;
|
||||
|
||||
private final int GRID_HEIGHT = 16;
|
||||
|
||||
private Attractor mAttractor;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
frameRate(60);
|
||||
|
||||
mPhysics = new Physics();
|
||||
mPhysics.contraint_iterations_per_steps = 5;
|
||||
|
||||
Verlet myVerlet = new Verlet();
|
||||
myVerlet.damping(0.9f);
|
||||
mPhysics.setInegratorRef(myVerlet);
|
||||
mPhysics.add(new Gravity(new Vector3f(0, 1000f, 0)));
|
||||
|
||||
mAttractor = new Attractor();
|
||||
mAttractor.strength(-15000);
|
||||
mAttractor.radius(300);
|
||||
mPhysics.add(mAttractor);
|
||||
|
||||
mParticles = new Particle[GRID_WIDTH][GRID_HEIGHT];
|
||||
|
||||
/* setup cloth */
|
||||
float mGridStepX = ((float) width / GRID_WIDTH);
|
||||
float mGridStepY = (((float) height * 0.5f) / GRID_HEIGHT);
|
||||
for (int y = 0; y < GRID_HEIGHT; y++) {
|
||||
for (int x = 0; x < GRID_WIDTH; x++) {
|
||||
mParticles[x][y] = mPhysics.makeParticle();
|
||||
mParticles[x][y].position().set((x + 0.5f) * mGridStepX,
|
||||
y * mGridStepY,
|
||||
random(0, 1));
|
||||
mParticles[x][y].old_position().set(mParticles[x][y].position());
|
||||
mParticles[x][y].mass(0.1f);
|
||||
|
||||
final float DAMPING = 0.9f;
|
||||
if (y > 0) {
|
||||
Stick myStick = new Stick(mParticles[x][y - 1],
|
||||
mParticles[x][y],
|
||||
mGridStepY);
|
||||
myStick.damping(DAMPING);
|
||||
mPhysics.add(myStick);
|
||||
}
|
||||
if (x > 0) {
|
||||
Stick myStick = new Stick(mParticles[x - 1][y],
|
||||
mParticles[x][y],
|
||||
mGridStepX);
|
||||
myStick.damping(DAMPING);
|
||||
mPhysics.add(myStick);
|
||||
}
|
||||
if (x > 0 && y > 0) {
|
||||
Stick myStick1 = new Stick(mParticles[x - 1][y - 1],
|
||||
mParticles[x][y],
|
||||
new Vector3f(mGridStepX, mGridStepY).length());
|
||||
mPhysics.add(myStick1);
|
||||
Stick myStick2 = new Stick(mParticles[x][y - 1],
|
||||
mParticles[x - 1][y],
|
||||
new Vector3f(mGridStepX, mGridStepY).length());
|
||||
mPhysics.add(myStick2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fix first row */
|
||||
for (int x = 0; x < mParticles.length; x++) {
|
||||
mParticles[x][0].fixed(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
|
||||
/* update */
|
||||
mAttractor.position().set(mouseX, mouseY, 50);
|
||||
mPhysics.step(1.0f / frameRate);
|
||||
|
||||
background(255);
|
||||
|
||||
/* draw sticks */
|
||||
stroke(0, 127);
|
||||
for (final IConstraint myIConstraint : mPhysics.constraints()) {
|
||||
if (myIConstraint instanceof Stick) {
|
||||
final Stick myStick = (Stick) myIConstraint;
|
||||
line(myStick.a().position().x,
|
||||
myStick.a().position().y,
|
||||
myStick.a().position().z,
|
||||
myStick.b().position().x,
|
||||
myStick.b().position().y,
|
||||
myStick.b().position().z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson09_Cloth.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.BehaviorParticle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.behavior.Motor;
|
||||
import teilchen.behavior.Wander;
|
||||
import teilchen.force.ViscousDrag;
|
||||
|
||||
import static processing.core.PConstants.OPENGL;
|
||||
import static processing.core.PConstants.RGB;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch shows how to assign an 'wander' behavior to a particle.
|
||||
*/
|
||||
public class Lesson10_WanderBehavior
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private BehaviorParticle mParticle;
|
||||
|
||||
private Wander mWander;
|
||||
|
||||
private Motor mMotor;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(120);
|
||||
|
||||
/* physics */
|
||||
mPhysics = new Physics();
|
||||
mPhysics.add(new ViscousDrag());
|
||||
|
||||
/* create particles */
|
||||
mParticle = mPhysics.makeParticle(BehaviorParticle.class);
|
||||
mParticle.position().set(width / 2, height / 2);
|
||||
mParticle.maximumInnerForce(100);
|
||||
mParticle.radius(10);
|
||||
|
||||
/* create behavior */
|
||||
mWander = new Wander();
|
||||
mParticle.behaviors().add(mWander);
|
||||
|
||||
/* a motor is required to push the particle forward - wander manipulats the direction the particle is pushed in */
|
||||
mMotor = new Motor();
|
||||
mMotor.auto_update_direction(true); /* the direction the motor pushes into is each step automatically set to the velocity */
|
||||
mMotor.strength(25);
|
||||
mParticle.behaviors().add(mMotor);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* update particle system */
|
||||
mPhysics.step(1.0f / frameRate);
|
||||
|
||||
/* draw behavior particle */
|
||||
background(255);
|
||||
|
||||
fill(1);
|
||||
stroke(0, 127);
|
||||
line(mParticle.position().x,
|
||||
mParticle.position().y,
|
||||
mParticle.position().x + mParticle.velocity().x,
|
||||
mParticle.position().y + mParticle.velocity().y);
|
||||
ellipse(mParticle.position().x, mParticle.position().y,
|
||||
mParticle.radius() * 2, mParticle.radius() * 2);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson10_WanderBehavior.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.BehaviorParticle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.behavior.Arrival;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch shows how to assign an 'arrival' behavior to a particle.
|
||||
*/
|
||||
public class Lesson11_ArrivalBehavior
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private BehaviorParticle mParticle;
|
||||
|
||||
private Arrival mArrival;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(120);
|
||||
colorMode(RGB, 1.0f);
|
||||
noFill();
|
||||
|
||||
/* physics */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create particles */
|
||||
mParticle = mPhysics.makeParticle(BehaviorParticle.class);
|
||||
mParticle.maximumInnerForce(100);
|
||||
|
||||
/* create behavior */
|
||||
mArrival = new Arrival();
|
||||
mArrival.breakforce(mParticle.maximumInnerForce() * 0.25f);
|
||||
mArrival.breakradius(mParticle.maximumInnerForce() * 0.25f);
|
||||
mParticle.behaviors().add(mArrival);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
|
||||
/* set the arrival position to the mouse position */
|
||||
mArrival.position().set(mouseX, mouseY);
|
||||
|
||||
/* update particle system */
|
||||
mPhysics.step(1.0f / frameRate);
|
||||
|
||||
/* draw behavior particle */
|
||||
background(1);
|
||||
stroke(0, 0.5f);
|
||||
if (mArrival.arriving()) {
|
||||
/* color particle red while it is arriving */
|
||||
stroke(1, 0, 0, 0.5f);
|
||||
}
|
||||
if (mArrival.arrived()) {
|
||||
/* color particle green when it has arrived */
|
||||
stroke(0, 1, 0, 0.5f);
|
||||
}
|
||||
|
||||
line(mParticle.position().x,
|
||||
mParticle.position().y,
|
||||
mParticle.position().x + mParticle.velocity().x,
|
||||
mParticle.position().y + mParticle.velocity().y);
|
||||
fill(1);
|
||||
ellipse(mParticle.position().x, mParticle.position().y, 12, 12);
|
||||
|
||||
/* draw arrival */
|
||||
stroke(0, 0.25f);
|
||||
noFill();
|
||||
ellipse(mArrival.position().x,
|
||||
mArrival.position().y,
|
||||
mArrival.breakradius() * 2,
|
||||
mArrival.breakradius() * 2);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{Lesson11_ArrivalBehavior.class.getName()});
|
||||
}
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.util.Overlap;
|
||||
import teilchen.util.Packing;
|
||||
|
||||
|
||||
/**
|
||||
* this sketch is exactly like Lesson06_Springs, except that it also shows how
|
||||
* to resolveOverlap overlaps.
|
||||
*/
|
||||
public class LessonX01_Overlap
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Particle mRoot;
|
||||
|
||||
private static final float PARTICLE_RADIUS = 13;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create drag */
|
||||
mPhysics.add(new ViscousDrag());
|
||||
mPhysics.add(new Gravity(new Vector3f(0, 100f, 0)));
|
||||
|
||||
|
||||
mRoot = mPhysics.makeParticle(width / 2, height / 2, 0.0f);
|
||||
mRoot.mass(30);
|
||||
mRoot.fixed(true);
|
||||
mRoot.radius(PARTICLE_RADIUS);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
if (mousePressed) {
|
||||
Particle mParticle = mPhysics.makeParticle(mouseX, mouseY, 0);
|
||||
mPhysics.makeSpring(mRoot, mParticle);
|
||||
|
||||
/*
|
||||
* we define a radius for the particle so the particle has
|
||||
* dimensions
|
||||
*/
|
||||
mParticle.radius(random(PARTICLE_RADIUS / 2) + PARTICLE_RADIUS);
|
||||
}
|
||||
|
||||
|
||||
/* move overlapping particles away from each other */
|
||||
for (int i = 0; i < 10; i++) {
|
||||
mRoot.position().set(width / 2, height / 2, 0.0f); // a bit of a 'hack'
|
||||
Overlap.resolveOverlap(mPhysics.particles());
|
||||
}
|
||||
|
||||
/* update the particle system */
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw particles and connecting line */
|
||||
background(255);
|
||||
|
||||
/* draw springs */
|
||||
noFill();
|
||||
stroke(255, 0, 127, 64);
|
||||
for (int i = 0; i < mPhysics.forces().size(); i++) {
|
||||
if (mPhysics.forces().get(i) instanceof Spring) {
|
||||
Spring mSSpring = (Spring) mPhysics.forces().get(i);
|
||||
line(mSSpring.a().position().x, mSSpring.a().position().y,
|
||||
mSSpring.b().position().x, mSSpring.b().position().y);
|
||||
}
|
||||
}
|
||||
/* draw particles */
|
||||
fill(255, 127);
|
||||
stroke(164);
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
ellipse(mPhysics.particles().get(i).position().x,
|
||||
mPhysics.particles().get(i).position().y,
|
||||
mPhysics.particles().get(i).radius() * 2,
|
||||
mPhysics.particles().get(i).radius() * 2);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{LessonX01_Overlap.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.Box;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.util.CollisionManager;
|
||||
|
||||
|
||||
public class LessonX02_Collisions
|
||||
extends PApplet {
|
||||
|
||||
private static final float PARTICLE_SIZE = 12;
|
||||
|
||||
private CollisionManager mCollision;
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(30);
|
||||
noFill();
|
||||
ellipseMode(CENTER);
|
||||
|
||||
mCollision = new CollisionManager();
|
||||
mCollision.distancemode(CollisionManager.DISTANCE_MODE_FIXED);
|
||||
mCollision.minimumDistance(50);
|
||||
|
||||
mPhysics = new Physics();
|
||||
mPhysics.add(new ViscousDrag(0.85f));
|
||||
mPhysics.add(new Gravity());
|
||||
|
||||
Box myBox = new Box();
|
||||
myBox.min().set(50, 50, 0);
|
||||
myBox.max().set(width - 50, height - 50, 0);
|
||||
myBox.coefficientofrestitution(0.7f);
|
||||
myBox.reflect(true);
|
||||
mPhysics.add(myBox);
|
||||
|
||||
/* create a first particle */
|
||||
final Particle myParticle = mPhysics.makeParticle(new Vector3f(mouseX, mouseY, 0), 10);
|
||||
mCollision.collision().add(myParticle);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* create particles */
|
||||
if (mousePressed) {
|
||||
final Particle myParticle = mPhysics.makeParticle(new Vector3f(mouseX, mouseY, 0), 10);
|
||||
mCollision.collision().add(myParticle);
|
||||
}
|
||||
|
||||
/* collision handler */
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
mCollision.createCollisionResolvers();
|
||||
mCollision.loop(mDeltaTime);
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* draw */
|
||||
background(255);
|
||||
drawThings();
|
||||
|
||||
mCollision.removeCollisionResolver();
|
||||
}
|
||||
|
||||
private void drawThings() {
|
||||
/* collision springs */
|
||||
noFill();
|
||||
stroke(255, 0, 127, 64);
|
||||
for (int i = 0; i < mCollision.collision().forces().size(); ++i) {
|
||||
if (mCollision.collision().forces().get(i) instanceof Spring) {
|
||||
Spring mySpring = (Spring) mCollision.collision_forces().get(i);
|
||||
line(mySpring.a().position().x, mySpring.a().position().y, mySpring.a().position().z,
|
||||
mySpring.b().position().x, mySpring.b().position().y, mySpring.b().position().z);
|
||||
}
|
||||
}
|
||||
|
||||
/* particles */
|
||||
fill(245);
|
||||
stroke(164);
|
||||
for (int i = 0; i < mPhysics.particles().size(); ++i) {
|
||||
Particle myParticle = mPhysics.particles().get(i);
|
||||
pushMatrix();
|
||||
translate(myParticle.position().x, myParticle.position().y, myParticle.position().z);
|
||||
ellipse(0, 0,
|
||||
PARTICLE_SIZE,
|
||||
PARTICLE_SIZE);
|
||||
popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{LessonX02_Collisions.class.getName()});
|
||||
}
|
||||
}
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.ShortLivedParticle;
|
||||
import teilchen.constraint.Box;
|
||||
import teilchen.force.Attractor;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.util.ParticleTrail;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
public class LessonX03_ParticlesLeavingTrails
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Vector<ParticleTrail> mTrails;
|
||||
|
||||
private Attractor mAttractor;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(60);
|
||||
|
||||
/* create a particle system */
|
||||
mPhysics = new Physics();
|
||||
|
||||
/* create a gravitational force */
|
||||
Gravity myGravity = new Gravity();
|
||||
mPhysics.add(myGravity);
|
||||
myGravity.force().y = 20;
|
||||
|
||||
/* create drag */
|
||||
ViscousDrag myViscousDrag = new ViscousDrag();
|
||||
myViscousDrag.coefficient = 0.1f;
|
||||
mPhysics.add(myViscousDrag);
|
||||
|
||||
final float mBorder = 40;
|
||||
Box mBox = new Box(new Vector3f(mBorder, mBorder, mBorder), new Vector3f(width - mBorder, height - mBorder, 100 - mBorder));
|
||||
mBox.reflect(true);
|
||||
mPhysics.add(mBox);
|
||||
|
||||
/* create an attractor */
|
||||
mAttractor = new Attractor();
|
||||
mAttractor.radius(200);
|
||||
mAttractor.strength(-300);
|
||||
mPhysics.add(mAttractor);
|
||||
|
||||
|
||||
/* create trails and particles */
|
||||
mTrails = new Vector<ParticleTrail>();
|
||||
for (int i = 0; i < 500; i++) {
|
||||
Particle mParticle = mPhysics.makeParticle();
|
||||
mParticle.mass(2.0f);
|
||||
ParticleTrail myParticleTrail = new ParticleTrail(mPhysics,
|
||||
mParticle,
|
||||
0.2f,
|
||||
random(0.5f, 1));
|
||||
myParticleTrail.mass(0.5f);
|
||||
mTrails.add(myParticleTrail);
|
||||
}
|
||||
resetParticles(width / 2, height / 2);
|
||||
}
|
||||
|
||||
private void resetParticles(float x, float y) {
|
||||
for (ParticleTrail myTrails : mTrails) {
|
||||
myTrails.particle().position().set(x + random(-10, 10), y + random(-10, 10), 0);
|
||||
myTrails.particle().velocity().set(random(-10, 10), random(-10, 10), random(-10, 10));
|
||||
myTrails.fragments().clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* set attractor to mouse position */
|
||||
mAttractor.position().set(mouseX, mouseY);
|
||||
|
||||
for (ParticleTrail myTrails : mTrails) {
|
||||
myTrails.loop(1f / frameRate);
|
||||
}
|
||||
|
||||
mPhysics.step(1f / frameRate);
|
||||
|
||||
background(255);
|
||||
for (ParticleTrail myTrail : mTrails) {
|
||||
drawTrail(myTrail);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawTrail(ParticleTrail theTrail) {
|
||||
|
||||
final Vector<Particle> mFragments = theTrail.fragments();
|
||||
final Particle mParticle = theTrail.particle();
|
||||
|
||||
/* draw head */
|
||||
if (mFragments.size() > 1) {
|
||||
fill(255, 0, 127);
|
||||
noStroke();
|
||||
pushMatrix();
|
||||
translate(mParticle.position().x,
|
||||
mParticle.position().y,
|
||||
mParticle.position().z);
|
||||
sphereDetail(4);
|
||||
sphere(3);
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
/* draw trail */
|
||||
for (int i = 0; i < mFragments.size() - 1; i++) {
|
||||
if (mFragments.get(i) instanceof ShortLivedParticle) {
|
||||
final float mRatio = 1.0f - ((ShortLivedParticle) mFragments.get(i)).ageRatio();
|
||||
stroke(127, mRatio * 255);
|
||||
strokeWeight(mRatio * 3);
|
||||
}
|
||||
int j = (i + 1) % mFragments.size();
|
||||
line(mFragments.get(i).position().x,
|
||||
mFragments.get(i).position().y,
|
||||
mFragments.get(i).position().z,
|
||||
mFragments.get(j).position().x,
|
||||
mFragments.get(j).position().y,
|
||||
mFragments.get(j).position().z);
|
||||
}
|
||||
if (!mFragments.isEmpty()) {
|
||||
line(mFragments.lastElement().position().x,
|
||||
mFragments.lastElement().position().y,
|
||||
mFragments.lastElement().position().z,
|
||||
mParticle.position().x,
|
||||
mParticle.position().y,
|
||||
mParticle.position().z);
|
||||
}
|
||||
}
|
||||
|
||||
public void mousePressed() {
|
||||
resetParticles(mouseX, mouseY);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{LessonX03_ParticlesLeavingTrails.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.Attractor;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.integration.RungeKutta;
|
||||
import teilchen.util.Overlap;
|
||||
import teilchen.util.StickMan;
|
||||
|
||||
|
||||
/**
|
||||
* this demo shows some advanced use of particles, springs and attractors to
|
||||
* create stickmen.
|
||||
*/
|
||||
public class LessonX04_StickMan
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Attractor mAttractor;
|
||||
|
||||
private Gravity mGravity;
|
||||
|
||||
private ViscousDrag mViscousDrag;
|
||||
|
||||
private StickMan[] mMyStickMan;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
smooth();
|
||||
frameRate(60);
|
||||
noFill();
|
||||
|
||||
mPhysics = new Physics();
|
||||
mPhysics.setInegratorRef(new RungeKutta());
|
||||
|
||||
mGravity = new Gravity();
|
||||
mGravity.force().y = 20;
|
||||
mPhysics.add(mGravity);
|
||||
|
||||
mViscousDrag = new ViscousDrag();
|
||||
mViscousDrag.coefficient = 0.85f;
|
||||
mPhysics.add(mViscousDrag);
|
||||
|
||||
mAttractor = new Attractor();
|
||||
mAttractor.radius(500);
|
||||
mAttractor.strength(0);
|
||||
mAttractor.position().set(width / 2, height / 2);
|
||||
mPhysics.add(mAttractor);
|
||||
|
||||
mMyStickMan = new StickMan[20];
|
||||
for (int i = 0; i < mMyStickMan.length; i++) {
|
||||
mMyStickMan[i] = new StickMan(mPhysics, random(0, width), random(0.3f, 0.6f));
|
||||
}
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
|
||||
mPhysics.step(1f / 60f);
|
||||
Overlap.resolveOverlap(mPhysics.particles());
|
||||
|
||||
/* constraint particles */
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
if (mPhysics.particles(i).position().y > height - 10) {
|
||||
mPhysics.particles(i).position().y = height - 10;
|
||||
}
|
||||
if (mPhysics.particles(i).position().x > width) {
|
||||
mPhysics.particles(i).position().x = width;
|
||||
}
|
||||
if (mPhysics.particles(i).position().x < 0) {
|
||||
mPhysics.particles(i).position().x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle particles */
|
||||
if (mousePressed) {
|
||||
mAttractor.position().set(mouseX, mouseY);
|
||||
if (mouseButton == RIGHT) {
|
||||
mAttractor.strength(-500);
|
||||
mAttractor.radius(500);
|
||||
} else {
|
||||
mAttractor.strength(500);
|
||||
mAttractor.radius(100);
|
||||
}
|
||||
} else {
|
||||
mAttractor.strength(0);
|
||||
}
|
||||
|
||||
if (keyPressed) {
|
||||
mGravity.force().y = -10;
|
||||
} else {
|
||||
mGravity.force().y = 20;
|
||||
}
|
||||
|
||||
/* draw */
|
||||
background(255);
|
||||
|
||||
/* draw springs */
|
||||
stroke(0, 20);
|
||||
for (int i = 0; i < mPhysics.forces().size(); i++) {
|
||||
if (mPhysics.forces(i) instanceof Spring) {
|
||||
Spring mySpring = (Spring) mPhysics.forces(i);
|
||||
line(mySpring.a().position().x,
|
||||
mySpring.a().position().y,
|
||||
mySpring.b().position().x,
|
||||
mySpring.b().position().y);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw particles */
|
||||
for (int i = 0; i < mPhysics.particles().size(); i++) {
|
||||
ellipse(mPhysics.particles(i).position().x,
|
||||
mPhysics.particles(i).position().y, 5, 5);
|
||||
}
|
||||
|
||||
/* draw man */
|
||||
for (int i = 0; i < mMyStickMan.length; i++) {
|
||||
mMyStickMan[i].draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{LessonX04_StickMan.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.AngleConstraintStick;
|
||||
import teilchen.constraint.Stick;
|
||||
import teilchen.force.AngleConstraintSpring;
|
||||
import teilchen.force.Gravity;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.integration.RungeKutta;
|
||||
|
||||
|
||||
public class LessonX05_AngleConstraints
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Particle mParticleA;
|
||||
|
||||
private Particle mParticleB;
|
||||
|
||||
private Particle mParticleC;
|
||||
|
||||
private Particle mParticleD;
|
||||
|
||||
private AngleConstraintSpring mAngleConstraintABC;
|
||||
|
||||
private AngleConstraintStick mAngleConstraintBCD;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480);
|
||||
frameRate(30);
|
||||
smooth();
|
||||
|
||||
mPhysics = new Physics();
|
||||
mPhysics.setInegratorRef(new RungeKutta());
|
||||
|
||||
ViscousDrag myViscousDrag = new ViscousDrag();
|
||||
myViscousDrag.coefficient = 1f;
|
||||
mPhysics.add(myViscousDrag);
|
||||
|
||||
Gravity myGravity = new Gravity();
|
||||
myGravity.force().y = 50;
|
||||
mPhysics.add(myGravity);
|
||||
|
||||
/* particles */
|
||||
mParticleA = mPhysics.makeParticle();
|
||||
mParticleB = mPhysics.makeParticle();
|
||||
mParticleC = mPhysics.makeParticle();
|
||||
mParticleD = mPhysics.makeParticle();
|
||||
|
||||
mParticleA.position().set(width / 2 + 50, height / 3);
|
||||
mParticleB.position().set(width / 2, height - height / 1.75f);
|
||||
mParticleC.position().set(width / 2, height - height / 4);
|
||||
mParticleD.position().set(width / 2, height - height / 8);
|
||||
|
||||
mParticleA.radius(7);
|
||||
mParticleB.radius(3);
|
||||
mParticleC.radius(10);
|
||||
mParticleD.radius(2);
|
||||
|
||||
mParticleB.fixed(true);
|
||||
|
||||
/* springs */
|
||||
Spring mSpringAB = new Spring(mParticleA, mParticleB);
|
||||
mSpringAB.strength(250);
|
||||
mSpringAB.damping(10);
|
||||
mPhysics.add(mSpringAB);
|
||||
|
||||
Spring mSpringBC = new Spring(mParticleB, mParticleC);
|
||||
mSpringBC.strength(250);
|
||||
mSpringBC.damping(10);
|
||||
mPhysics.add(mSpringBC);
|
||||
|
||||
Stick mSpringCD = new Stick(mParticleC, mParticleD);
|
||||
mSpringCD.damping(1);
|
||||
mPhysics.add(mSpringCD);
|
||||
|
||||
/* angle constraint */
|
||||
mAngleConstraintABC = new AngleConstraintSpring(mParticleA, mParticleB, mParticleC);
|
||||
mAngleConstraintABC.min_angle(PI * 0.5f);
|
||||
mAngleConstraintABC.damping(1);
|
||||
mAngleConstraintABC.strength(200);
|
||||
mPhysics.add(mAngleConstraintABC);
|
||||
|
||||
mAngleConstraintBCD = new AngleConstraintStick(mParticleB, mParticleC, mParticleD);
|
||||
mAngleConstraintBCD.min_angle(PI * 0.8f);
|
||||
mAngleConstraintBCD.damping(0.5f);
|
||||
mPhysics.add(mAngleConstraintBCD);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* attach particle to mouse */
|
||||
if (mousePressed) {
|
||||
mParticleA.position().set(mouseX, mouseY);
|
||||
}
|
||||
|
||||
/* apply constraints */
|
||||
mAngleConstraintABC.pre_step();
|
||||
mAngleConstraintBCD.pre_step();
|
||||
draw_physics();
|
||||
|
||||
mPhysics.step(1f / frameRate);
|
||||
|
||||
/* remove contraints */
|
||||
mAngleConstraintABC.post_step();
|
||||
mAngleConstraintBCD.post_step();
|
||||
}
|
||||
|
||||
private void draw_physics() {
|
||||
background(255);
|
||||
|
||||
drawSprings();
|
||||
drawSticks();
|
||||
drawParticles();
|
||||
}
|
||||
|
||||
private void drawSprings() {
|
||||
for (int i = 0; i < mPhysics.forces().size(); i++) {
|
||||
if (mPhysics.forces(i) instanceof Spring) {
|
||||
final Spring mSpring = (Spring) mPhysics.forces(i);
|
||||
if (mSpring instanceof AngleConstraintSpring) {
|
||||
strokeWeight(1);
|
||||
if (mSpring.active()) {
|
||||
stroke(255, 0, 0, 64);
|
||||
} else {
|
||||
stroke(255, 0, 0, 16);
|
||||
}
|
||||
} else {
|
||||
strokeWeight(3);
|
||||
stroke(0, 128);
|
||||
}
|
||||
line(mSpring.a(), mSpring.b());
|
||||
}
|
||||
}
|
||||
strokeWeight(1);
|
||||
}
|
||||
|
||||
private void drawSticks() {
|
||||
for (int i = 0; i < mPhysics.constraints().size(); i++) {
|
||||
if (mPhysics.constraints(i) instanceof Stick) {
|
||||
final Stick mStick = (Stick) mPhysics.constraints(i);
|
||||
if (mStick instanceof AngleConstraintStick) {
|
||||
strokeWeight(1);
|
||||
if (mStick.active()) {
|
||||
stroke(0, 127, 255, 64);
|
||||
} else {
|
||||
stroke(0, 127, 255, 16);
|
||||
}
|
||||
} else {
|
||||
strokeWeight(3);
|
||||
stroke(0, 128);
|
||||
}
|
||||
line(mStick.a(), mStick.b());
|
||||
}
|
||||
}
|
||||
strokeWeight(1);
|
||||
}
|
||||
|
||||
private void drawParticles() {
|
||||
stroke(0);
|
||||
fill(92);
|
||||
drawParticle(mParticleA);
|
||||
fill(127);
|
||||
drawParticle(mParticleB);
|
||||
fill(192);
|
||||
drawParticle(mParticleC);
|
||||
fill(64);
|
||||
drawParticle(mParticleD);
|
||||
}
|
||||
|
||||
private void drawParticle(Particle p) {
|
||||
ellipse(p.position().x,
|
||||
p.position().y,
|
||||
p.radius() * 2, p.radius() * 2);
|
||||
}
|
||||
|
||||
private void line(Particle p1, Particle p2) {
|
||||
line(p1.position().x, p1.position().y,
|
||||
p2.position().x, p2.position().y);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{LessonX05_AngleConstraints.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.BehaviorParticle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.behavior.Arrival;
|
||||
import teilchen.force.Spring;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.util.CollisionManager;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* this demo shows how to add behaviors to particles. in this example the
|
||||
* arrival behavior.
|
||||
*/
|
||||
public class LessonX06_Ducklings
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Vector<Duckling> mDucklings;
|
||||
|
||||
private CollisionManager mCollision;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
frameRate(60);
|
||||
smooth();
|
||||
colorMode(RGB, 1.0f);
|
||||
|
||||
/* physics */
|
||||
mPhysics = new Physics();
|
||||
|
||||
ViscousDrag myViscousDrag = new ViscousDrag();
|
||||
myViscousDrag.coefficient = 0.25f;
|
||||
mPhysics.add(myViscousDrag);
|
||||
|
||||
mCollision = new CollisionManager();
|
||||
mCollision.minimumDistance(25);
|
||||
|
||||
/* ducklings */
|
||||
mDucklings = new Vector<Duckling>();
|
||||
for (int i = 0; i < 13; i++) {
|
||||
final Duckling mDuckling = new Duckling();
|
||||
if (!mDucklings.isEmpty()) {
|
||||
mDuckling.arrival.setPositionRef(mDucklings.lastElement().particle.position());
|
||||
}
|
||||
mCollision.collision().add(mDuckling.particle);
|
||||
mDucklings.add(mDuckling);
|
||||
}
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
background(1);
|
||||
|
||||
/* update particles */
|
||||
mCollision.createCollisionResolvers();
|
||||
mCollision.loop(mDeltaTime);
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
drawCollisionSprings();
|
||||
mCollision.removeCollisionResolver();
|
||||
|
||||
mDucklings.firstElement().arrival.oversteer(!mousePressed);
|
||||
mDucklings.firstElement().arrival.position().set(mouseX, mouseY);
|
||||
|
||||
/* draw */
|
||||
for (Duckling mDuckling : mDucklings) {
|
||||
drawParticle(mDuckling);
|
||||
}
|
||||
|
||||
/* draw arrival */
|
||||
stroke(0, 0.25f);
|
||||
noFill();
|
||||
ellipse(mDucklings.firstElement().arrival.position().x,
|
||||
mDucklings.firstElement().arrival.position().y,
|
||||
20, 20);
|
||||
}
|
||||
|
||||
private void drawParticle(Duckling pDuckling) {
|
||||
final BehaviorParticle mParticle = pDuckling.particle;
|
||||
final Arrival mArrival = pDuckling.arrival;
|
||||
|
||||
/* draw particle */
|
||||
stroke(0, 0.5f);
|
||||
noFill();
|
||||
if (mArrival.arriving()) {
|
||||
stroke(1, 0, 0, 0.5f);
|
||||
}
|
||||
if (mArrival.arrived()) {
|
||||
stroke(0, 1, 0, 0.5f);
|
||||
}
|
||||
ellipse(mParticle.position().x, mParticle.position().y,
|
||||
mParticle.radius() * 2, mParticle.radius() * 2);
|
||||
|
||||
/* - */
|
||||
pushMatrix();
|
||||
translate(mParticle.position().x,
|
||||
mParticle.position().y);
|
||||
|
||||
/* draw velocity */
|
||||
stroke(1, 0, 0, 0.5f);
|
||||
line(0, 0, mParticle.velocity().x, mParticle.velocity().y);
|
||||
|
||||
/* draw break force */
|
||||
stroke(0, 0.5f, 1, 0.5f);
|
||||
line(0, 0, mArrival.force().x, mArrival.force().y);
|
||||
|
||||
/* - */
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
private void drawCollisionSprings() {
|
||||
stroke(0, 1, 0, 0.25f);
|
||||
for (int i = 0; i < mCollision.collision().forces().size(); ++i) {
|
||||
if (mCollision.collision().forces().get(i) instanceof Spring) {
|
||||
Spring mySpring = (Spring) mCollision.collision_forces().get(i);
|
||||
line(mySpring.a().position().x, mySpring.a().position().y, mySpring.a().position().z,
|
||||
mySpring.b().position().x, mySpring.b().position().y, mySpring.b().position().z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Duckling {
|
||||
|
||||
BehaviorParticle particle;
|
||||
|
||||
Arrival arrival;
|
||||
|
||||
Duckling() {
|
||||
/* create particles */
|
||||
particle = mPhysics.makeParticle(BehaviorParticle.class);
|
||||
particle.position().set(random(width), random(height));
|
||||
particle.maximumInnerForce(random(50, 150));
|
||||
particle.radius(random(6, 10));
|
||||
|
||||
arrival = new Arrival();
|
||||
arrival.breakforce(random(12, 28));
|
||||
arrival.breakradius(random(45, 55));
|
||||
|
||||
particle.behaviors().add(arrival);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{LessonX06_Ducklings.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import mathematik.Vector3i;
|
||||
|
||||
import processing.core.PApplet;
|
||||
import teilchen.cubicle.CubicleWorld;
|
||||
import teilchen.cubicle.ICubicleEntity;
|
||||
import teilchen.util.CubicleWorldView;
|
||||
import teilchen.util.DrawLib;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
public class LessonX07_CubicleWorld
|
||||
extends PApplet {
|
||||
|
||||
private final int WORLD_NUMBER_OF_CUBICLES = 15;
|
||||
|
||||
private final float WORLD_CUBICLE_SCALE = 20;
|
||||
|
||||
private final float WORLD_SCALE = WORLD_NUMBER_OF_CUBICLES * WORLD_CUBICLE_SCALE;
|
||||
|
||||
private boolean showCubicles = true;
|
||||
|
||||
private float mRotationZ = 0.1f;
|
||||
|
||||
private Vector3f mPosition = new Vector3f();
|
||||
|
||||
private CubicleWorld mCubicleWorld;
|
||||
|
||||
private CubicleWorldView mCubicleWorldView;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
textFont(createFont("Courier", 11));
|
||||
hint(DISABLE_DEPTH_SORT);
|
||||
hint(DISABLE_DEPTH_TEST);
|
||||
|
||||
/* setup world */
|
||||
mCubicleWorld = new CubicleWorld(WORLD_NUMBER_OF_CUBICLES, WORLD_NUMBER_OF_CUBICLES, WORLD_NUMBER_OF_CUBICLES);
|
||||
mCubicleWorld.cellscale().set(WORLD_CUBICLE_SCALE, WORLD_CUBICLE_SCALE, WORLD_CUBICLE_SCALE);
|
||||
mCubicleWorld.transform().translation.set(-WORLD_SCALE / 2, -WORLD_SCALE / 2, -WORLD_SCALE / 2);
|
||||
|
||||
mCubicleWorldView = new CubicleWorldView(mCubicleWorld);
|
||||
mCubicleWorldView.color_empty = color(0, 1);
|
||||
mCubicleWorldView.color_full = color(0, 4);
|
||||
|
||||
mCubicleWorld.add(new MCubicleEntity());
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
/* handle entities */
|
||||
if (frameRate > 30) {
|
||||
addRandomEntities(2);
|
||||
}
|
||||
|
||||
mCubicleWorld.update();
|
||||
Vector<ICubicleEntity> mEntities = mCubicleWorld.getLocalEntities(mPosition, 1);
|
||||
|
||||
/* draw things */
|
||||
background(255);
|
||||
|
||||
pushMatrix();
|
||||
translate(width / 2, height / 2, 0);
|
||||
|
||||
/* rotate */
|
||||
if (mousePressed) {
|
||||
mRotationZ += (mouseX * 0.01f - mRotationZ) * 0.05f;
|
||||
} else {
|
||||
mPosition.x = mouseX - width / 2;
|
||||
mPosition.y = mouseY - height / 2;
|
||||
}
|
||||
rotateX(THIRD_PI);
|
||||
rotateZ(mRotationZ);
|
||||
|
||||
/* draw cubicle world */
|
||||
if (showCubicles) {
|
||||
stroke(0, 127);
|
||||
noFill();
|
||||
mCubicleWorldView.draw(g);
|
||||
}
|
||||
|
||||
/* draw entities */
|
||||
int mNumberOfPointsSelected = 0;
|
||||
stroke(0, 127, 255, 127);
|
||||
noFill();
|
||||
if (mEntities != null) {
|
||||
mNumberOfPointsSelected = mEntities.size();
|
||||
for (ICubicleEntity mEntity : mEntities) {
|
||||
MCubicleEntity m = (MCubicleEntity) mEntity;
|
||||
stroke(m.color);
|
||||
DrawLib.cross3(g, mEntity.position(), 5.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw crosshair */
|
||||
stroke(255, 0, 0, 63);
|
||||
noFill();
|
||||
beginShape(LINES);
|
||||
vertex(mPosition.x, -WORLD_SCALE / 2, 0);
|
||||
vertex(mPosition.x, WORLD_SCALE / 2, 0);
|
||||
vertex(-WORLD_SCALE / 2, mPosition.y, 0);
|
||||
vertex(WORLD_SCALE / 2, mPosition.y, 0);
|
||||
endShape();
|
||||
|
||||
/* draw selection sphere */
|
||||
stroke(255, 0, 0, 63);
|
||||
noFill();
|
||||
translate(mPosition.x, mPosition.y, 0);
|
||||
box(WORLD_CUBICLE_SCALE);
|
||||
popMatrix();
|
||||
|
||||
fill(0);
|
||||
noStroke();
|
||||
text("POINTS : " + mCubicleWorld.entities().size(), 10, 12);
|
||||
text("SELECTED : " + mNumberOfPointsSelected, 10, 24);
|
||||
text("FPS : " + frameRate, 10, 36);
|
||||
}
|
||||
|
||||
private void addRandomEntities(int pNumberParticles) {
|
||||
for (int i = 0; i < pNumberParticles; i++) {
|
||||
MCubicleEntity mEntity = new MCubicleEntity();
|
||||
mEntity.position().x = random(-WORLD_SCALE / 2, WORLD_SCALE / 2);
|
||||
mEntity.position().y = random(-WORLD_SCALE / 2, WORLD_SCALE / 2);
|
||||
mEntity.position().z = random(-WORLD_SCALE / 2, WORLD_SCALE / 2);
|
||||
mCubicleWorld.add(mEntity);
|
||||
}
|
||||
}
|
||||
|
||||
class MCubicleEntity
|
||||
implements ICubicleEntity {
|
||||
|
||||
int color = color(0, 127, random(0, 255), 127);
|
||||
|
||||
private Vector3i mCubiclePosition;
|
||||
|
||||
private final Vector3f mPosition;
|
||||
|
||||
public MCubicleEntity() {
|
||||
mCubiclePosition = new Vector3i();
|
||||
mPosition = new Vector3f();
|
||||
}
|
||||
|
||||
public Vector3i cubicle() {
|
||||
return mCubiclePosition;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
public boolean leaving(int theX, int theY, int theZ) {
|
||||
if (theX == cubicle().x
|
||||
&& theY == cubicle().y
|
||||
&& theZ == cubicle().z) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{LessonX07_CubicleWorld.class.getName()});
|
||||
}
|
||||
}
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.demo;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import processing.core.PApplet;
|
||||
import processing.core.PGraphics;
|
||||
import processing.core.PMatrix3D;
|
||||
import teilchen.BehaviorParticle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.behavior.Alignment;
|
||||
import teilchen.behavior.Cohesion;
|
||||
import teilchen.behavior.Motor;
|
||||
import teilchen.behavior.Separation;
|
||||
import teilchen.behavior.Wander;
|
||||
import teilchen.constraint.Teleporter;
|
||||
import teilchen.force.ViscousDrag;
|
||||
import teilchen.util.Util;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
public class LessonX08_Schwarm
|
||||
extends PApplet {
|
||||
|
||||
private Physics mPhysics;
|
||||
|
||||
private Vector<SwarmEntity> mSwarmEntities;
|
||||
|
||||
public void setup() {
|
||||
size(640, 480, OPENGL);
|
||||
frameRate(60);
|
||||
smooth();
|
||||
rectMode(CENTER);
|
||||
hint(DISABLE_DEPTH_TEST);
|
||||
|
||||
/* physics */
|
||||
mPhysics = new Physics();
|
||||
|
||||
Teleporter mTeleporter = new Teleporter();
|
||||
mTeleporter.min().set(0, 0, height / -2);
|
||||
mTeleporter.max().set(width, height, height / 2);
|
||||
mPhysics.add(mTeleporter);
|
||||
|
||||
ViscousDrag myViscousDrag = new ViscousDrag();
|
||||
mPhysics.add(myViscousDrag);
|
||||
|
||||
/* setup entities */
|
||||
mSwarmEntities = new Vector<SwarmEntity>();
|
||||
for (int i = 0; i < 60; i++) {
|
||||
SwarmEntity mSwarmEntity = new SwarmEntity();
|
||||
mSwarmEntity.position().set(random(mTeleporter.min().x, mTeleporter.max().x),
|
||||
random(mTeleporter.min().y, mTeleporter.max().y),
|
||||
random(mTeleporter.min().z, mTeleporter.max().z));
|
||||
mSwarmEntities.add(mSwarmEntity);
|
||||
mPhysics.add(mSwarmEntity);
|
||||
}
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
final float mDeltaTime = 1.0f / frameRate;
|
||||
|
||||
/* physics */
|
||||
mPhysics.step(mDeltaTime);
|
||||
|
||||
/* entities */
|
||||
for (SwarmEntity s : mSwarmEntities) {
|
||||
s.update(mDeltaTime);
|
||||
}
|
||||
|
||||
/* draw */
|
||||
background(255);
|
||||
for (SwarmEntity s : mSwarmEntities) {
|
||||
s.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
private class SwarmEntity
|
||||
extends BehaviorParticle {
|
||||
|
||||
private Separation separation;
|
||||
|
||||
private Alignment alignment;
|
||||
|
||||
private Cohesion cohesion;
|
||||
|
||||
private Wander wander;
|
||||
|
||||
private Motor motor;
|
||||
|
||||
public SwarmEntity() {
|
||||
maximumInnerForce(random(100.0f, 1000.0f));
|
||||
radius(10f);
|
||||
|
||||
separation = new Separation();
|
||||
separation.proximity(20);
|
||||
separation.weight(50.0f);
|
||||
behaviors().add(separation);
|
||||
|
||||
alignment = new Alignment();
|
||||
alignment.proximity(30);
|
||||
alignment.weight(30.0f);
|
||||
behaviors().add(alignment);
|
||||
|
||||
cohesion = new Cohesion();
|
||||
cohesion.proximity(100);
|
||||
cohesion.weight(5.0f);
|
||||
behaviors().add(cohesion);
|
||||
|
||||
wander = new Wander();
|
||||
behaviors().add(wander);
|
||||
|
||||
motor = new Motor();
|
||||
motor.auto_update_direction(true);
|
||||
motor.strength(20.0f);
|
||||
behaviors().add(motor);
|
||||
}
|
||||
|
||||
public void update(float theDeltaTime) {
|
||||
separation.neighbors(mSwarmEntities);
|
||||
alignment.neighbors(mSwarmEntities);
|
||||
cohesion.neighbors(mSwarmEntities);
|
||||
}
|
||||
|
||||
private void draw(PGraphics g) {
|
||||
pushMatrix();
|
||||
|
||||
translate(position().x, position().y, position().z);
|
||||
|
||||
pushMatrix();
|
||||
|
||||
PMatrix3D p = new PMatrix3D();
|
||||
Util.pointAt(p, position(), new Vector3f(0, 1, 0), mathematik.Util.add(position(), velocity()));
|
||||
applyMatrix(p);
|
||||
|
||||
noStroke();
|
||||
fill(0);
|
||||
scale(1, 0.25f, 3);
|
||||
box(6);
|
||||
|
||||
popMatrix();
|
||||
|
||||
/* velocity */
|
||||
stroke(0, 31);
|
||||
line(0, 0, 0, velocity().x, velocity().y, velocity().z);
|
||||
|
||||
popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PApplet.main(new String[]{LessonX08_Schwarm.class.getName()});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
|
||||
|
||||
public class AngleConstraintSpring
|
||||
extends Spring {
|
||||
|
||||
private final Particle mParticleA;
|
||||
|
||||
private final Particle mParticleB;
|
||||
|
||||
private final Particle mParticleC;
|
||||
|
||||
private float mMinAngle;
|
||||
|
||||
/**
|
||||
*
|
||||
* particles are connected like this: A -- B -- C
|
||||
*
|
||||
* @param pParticleA
|
||||
* @param pParticleB
|
||||
* @param pParticleC
|
||||
*/
|
||||
public AngleConstraintSpring(Particle pParticleA, Particle pParticleB, Particle pParticleC) {
|
||||
super(pParticleA, pParticleC);
|
||||
mParticleA = pParticleA;
|
||||
mParticleB = pParticleB;
|
||||
mParticleC = pParticleC;
|
||||
mMinAngle = Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
public void min_angle(float pAngle) {
|
||||
mMinAngle = pAngle;
|
||||
}
|
||||
|
||||
public void pre_step() {
|
||||
Vector3f ab = mathematik.Util.sub(mParticleA.position(), mParticleB.position());
|
||||
Vector3f cb = mathematik.Util.sub(mParticleC.position(), mParticleB.position());
|
||||
final float mCurrentAngle = ab.angle(cb);
|
||||
|
||||
if (mCurrentAngle < mMinAngle) {
|
||||
final int TINY_FACTOR_MODELL = 0;
|
||||
final int TRIG_MODELL = 1;
|
||||
final int MAX_DISTANCE_MODELL = 2;
|
||||
|
||||
final int mModell = TRIG_MODELL;
|
||||
|
||||
switch (mModell) {
|
||||
case TINY_FACTOR_MODELL: {
|
||||
final float TINY_FACTOR = 1.1f;
|
||||
final float mDistance = mParticleA.position().distance(mParticleC.position()) * TINY_FACTOR;
|
||||
restlength(mDistance);
|
||||
}
|
||||
break;
|
||||
case TRIG_MODELL: {
|
||||
// a = sqrt ( b*b + c*c - 2bc*cosA )
|
||||
final float b = ab.length();
|
||||
final float c = cb.length();
|
||||
final float mDistance = (float) Math.sqrt(b * b + c * c - 2 * b * c * (float) Math.cos(mMinAngle));
|
||||
restlength(mDistance);
|
||||
}
|
||||
break;
|
||||
case MAX_DISTANCE_MODELL: {
|
||||
final float mDistance = mParticleA.position().distance(mParticleB.position()) + mParticleC.position().distance(mParticleB.position());
|
||||
restlength(mDistance);
|
||||
}
|
||||
break;
|
||||
}
|
||||
active(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void post_step() {
|
||||
active(false);
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class Attractor
|
||||
implements IForce {
|
||||
|
||||
protected Vector3f _myPosition;
|
||||
|
||||
protected float _myStrength;
|
||||
|
||||
protected float _myRadius;
|
||||
|
||||
protected final Vector3f myTemp = new Vector3f();
|
||||
|
||||
private boolean _myActive;
|
||||
|
||||
public Attractor() {
|
||||
_myPosition = new Vector3f();
|
||||
_myRadius = 100;
|
||||
_myStrength = 1;
|
||||
_myActive = true;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return _myPosition;
|
||||
}
|
||||
|
||||
public void setPositionRef(Vector3f thePosition) {
|
||||
_myPosition = thePosition;
|
||||
}
|
||||
|
||||
public float strength() {
|
||||
return _myStrength;
|
||||
}
|
||||
|
||||
public void strength(float theStrength) {
|
||||
_myStrength = theStrength;
|
||||
}
|
||||
|
||||
public float radius() {
|
||||
return _myRadius;
|
||||
}
|
||||
|
||||
public void radius(float theRadius) {
|
||||
_myRadius = theRadius;
|
||||
}
|
||||
|
||||
public void apply(float theDeltaTime, Physics theParticleSystem) {
|
||||
if (_myStrength != 0) {
|
||||
for (final Particle myParticle : theParticleSystem.particles()) {
|
||||
/* each particle */
|
||||
if (!myParticle.fixed()) {
|
||||
myTemp.sub(_myPosition, myParticle.position());
|
||||
final float myDistance = fastInverseSqrt(1 / myTemp.lengthSquared());
|
||||
if (myDistance < _myRadius) {
|
||||
float myFallOff = 1f - myDistance / _myRadius;
|
||||
final float myForce = myFallOff * myFallOff * _myStrength;
|
||||
myTemp.scale(myForce / myDistance);
|
||||
if (!myParticle.fixed()) {
|
||||
myParticle.force().add(myTemp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static float fastInverseSqrt(float v) {
|
||||
final float half = 0.5f * v;
|
||||
int i = Float.floatToIntBits(v);
|
||||
i = 0x5f375a86 - (i >> 1);
|
||||
v = Float.intBitsToFloat(i);
|
||||
return v * (1.5f - half * v * v);
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return _myActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
_myActive = theActiveState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class DirectedAttractor
|
||||
extends Attractor {
|
||||
|
||||
private final Vector3f myVectorA = new Vector3f();
|
||||
|
||||
private final Vector3f myVectorB = new Vector3f();
|
||||
|
||||
public DirectedAttractor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void apply(float theDeltaTime, Physics theParticleSystem) {
|
||||
for (final Particle myParticle : theParticleSystem.particles()) {
|
||||
/* each particle */
|
||||
if (!myParticle.fixed()) {
|
||||
myTemp.sub(_myPosition, myParticle.position());
|
||||
|
||||
final float myDistance = fastInverseSqrt(1 / myTemp.lengthSquared());
|
||||
if (myDistance < _myRadius) {
|
||||
|
||||
myVectorA.scale(1 / myDistance, myTemp);
|
||||
myVectorB.normalize(myParticle.velocity());
|
||||
float myAngle = myVectorA.dot(myVectorB);
|
||||
|
||||
float myFallOff = 1f - myDistance / _myRadius;
|
||||
final float myForce = myAngle * myFallOff * myFallOff * _myStrength;
|
||||
myTemp.scale(myForce / myDistance);
|
||||
myParticle.force().add(myTemp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class Gravity
|
||||
implements IForce {
|
||||
|
||||
private boolean _myActive;
|
||||
|
||||
private Vector3f _myForce;
|
||||
|
||||
public Gravity(final Vector3f theForce) {
|
||||
_myActive = true;
|
||||
_myForce = theForce;
|
||||
}
|
||||
|
||||
public Gravity() {
|
||||
this(new Vector3f(0, 9.81f, 0));
|
||||
}
|
||||
|
||||
public Gravity(float theX, float theY, float theZ) {
|
||||
this(new Vector3f(theX, theY, theZ));
|
||||
}
|
||||
|
||||
public Vector3f force() {
|
||||
return _myForce;
|
||||
}
|
||||
|
||||
public void apply(final float theDeltaTime, final Physics theParticleSystem) {
|
||||
for (final Particle myParticle : theParticleSystem.particles()) {
|
||||
if (!myParticle.fixed()) {
|
||||
myParticle.force().add(_myForce);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return _myActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
_myActive = theActiveState;
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public interface IForce {
|
||||
|
||||
void apply(final float theDeltaTime, final Physics theParticleSystem);
|
||||
|
||||
boolean dead();
|
||||
|
||||
boolean active();
|
||||
|
||||
void active(boolean theActiveState);
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class MuscleSpring
|
||||
extends Spring {
|
||||
|
||||
private float mAmplitude = 1;
|
||||
|
||||
private float mOffset = 0;
|
||||
|
||||
private float mFrequency = 1;
|
||||
|
||||
private float mInitialRestLength;
|
||||
|
||||
private float mCurrentTime;
|
||||
|
||||
private boolean mAutomaticContraction = true;
|
||||
|
||||
public MuscleSpring(Particle theA, Particle theB) {
|
||||
super(theA, theB);
|
||||
mInitialRestLength = mRestLength;
|
||||
}
|
||||
|
||||
public MuscleSpring(final Particle theA,
|
||||
final Particle theB,
|
||||
final float theSpringConstant,
|
||||
final float theSpringDamping,
|
||||
final float theRestLength) {
|
||||
super(theA,
|
||||
theB,
|
||||
theSpringConstant,
|
||||
theSpringDamping,
|
||||
theRestLength);
|
||||
mInitialRestLength = mRestLength;
|
||||
}
|
||||
|
||||
public void setRestLengthByPosition() {
|
||||
mInitialRestLength = mA.position().distance(mB.position());
|
||||
}
|
||||
|
||||
public float restlength() {
|
||||
return mInitialRestLength;
|
||||
}
|
||||
|
||||
public void restlength(float theRestLength) {
|
||||
mInitialRestLength = theRestLength;
|
||||
}
|
||||
|
||||
public void frequency(final float theFrequency) {
|
||||
mFrequency = theFrequency;
|
||||
}
|
||||
|
||||
public float frequency() {
|
||||
return mFrequency;
|
||||
}
|
||||
|
||||
public void amplitude(final float theAmplitude) {
|
||||
mAmplitude = theAmplitude;
|
||||
}
|
||||
|
||||
public float amplitude() {
|
||||
return mAmplitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the offset of the contraction in radians.
|
||||
*
|
||||
* @param theOffset float
|
||||
*/
|
||||
public void offset(final float theOffset) {
|
||||
mOffset = theOffset;
|
||||
}
|
||||
|
||||
public float offset() {
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
public void apply(final float theDeltaTime, final Physics theParticleSystem) {
|
||||
|
||||
if (mAutomaticContraction) {
|
||||
mCurrentTime += theDeltaTime;
|
||||
|
||||
final float myOffset = (float) Math.sin(mCurrentTime * mFrequency + mOffset) * mAmplitude;
|
||||
mRestLength = mInitialRestLength + myOffset;
|
||||
}
|
||||
|
||||
super.apply(theDeltaTime, theParticleSystem);
|
||||
}
|
||||
}
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
import mathematik.Plane3f;
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class PlaneDeflector
|
||||
implements IForce {
|
||||
|
||||
private final Plane3f mPlane;
|
||||
|
||||
private float mCoefficientOfRestitution;
|
||||
|
||||
private final Vector3f _myTempDiff;
|
||||
|
||||
private final Vector3f mTempReflectionVector;
|
||||
|
||||
private final Vector3f mTempNormalComponent;
|
||||
|
||||
private final Vector3f mTempTangentComponent;
|
||||
|
||||
private boolean _myActive;
|
||||
|
||||
public PlaneDeflector() {
|
||||
mPlane = new Plane3f();
|
||||
mPlane.normal = new Vector3f(0, 1, 0);
|
||||
mCoefficientOfRestitution = 1.0f;
|
||||
|
||||
_myTempDiff = new Vector3f();
|
||||
mTempReflectionVector = new Vector3f();
|
||||
mTempNormalComponent = new Vector3f();
|
||||
mTempTangentComponent = new Vector3f();
|
||||
_myActive = true;
|
||||
}
|
||||
|
||||
public void apply(final float theDeltaTime, final Physics theParticleSystem) {
|
||||
for (final Particle myParticle : theParticleSystem.particles()) {
|
||||
if (!myParticle.fixed()) {
|
||||
/* test if particle passed plane */
|
||||
if (testParticlePosition(myParticle, mPlane) < 0) {
|
||||
|
||||
/* find intersection with plane */
|
||||
Vector3f myResult = new Vector3f();
|
||||
/**
|
||||
* using the normal of the plane instead of the velocity of
|
||||
* the particle. though less correct it seems to be more
|
||||
* stable.
|
||||
*/
|
||||
final float myIntersectionResult = intersectLinePlane(myParticle.position(),
|
||||
mPlane.normal,
|
||||
mPlane,
|
||||
myResult);
|
||||
|
||||
/* remove particle from collision */
|
||||
if (myIntersectionResult != Float.NEGATIVE_INFINITY
|
||||
&& !myResult.isNaN()) {
|
||||
myParticle.position().set(myResult);
|
||||
}
|
||||
|
||||
/* change direction */
|
||||
seperateComponents(myParticle, mPlane);
|
||||
myParticle.velocity().set(mTempReflectionVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Plane3f plane() {
|
||||
return mPlane;
|
||||
}
|
||||
|
||||
public void coefficientofrestitution(float theCoefficientOfRestitution) {
|
||||
mCoefficientOfRestitution = theCoefficientOfRestitution;
|
||||
}
|
||||
|
||||
public float coefficientofrestitution() {
|
||||
return mCoefficientOfRestitution;
|
||||
}
|
||||
|
||||
private final float testParticlePosition(Particle theParticle, Plane3f thePlane) {
|
||||
_myTempDiff.sub(theParticle.position(), thePlane.origin);
|
||||
_myTempDiff.normalize();
|
||||
final float myAngle = _myTempDiff.dot(thePlane.normal);
|
||||
return myAngle;
|
||||
}
|
||||
|
||||
private final void seperateComponents(Particle theParticle, Plane3f thePlane) {
|
||||
/* normal */
|
||||
mTempNormalComponent.set(thePlane.normal);
|
||||
mTempNormalComponent.scale(thePlane.normal.dot(theParticle.velocity()));
|
||||
/* tangent */
|
||||
mTempTangentComponent.sub(theParticle.velocity(), mTempNormalComponent);
|
||||
/* negate normal */
|
||||
mTempNormalComponent.scale(-mCoefficientOfRestitution);
|
||||
/* set reflection vector */
|
||||
mTempReflectionVector.add(mTempTangentComponent, mTempNormalComponent);
|
||||
}
|
||||
|
||||
private final float intersectLinePlane(final Vector3f theRayOrigin,
|
||||
final Vector3f theRayDirection,
|
||||
final Plane3f thePlane,
|
||||
final Vector3f theIntersectionPoint) {
|
||||
float myT;
|
||||
final float myDenominator = thePlane.normal.dot(theRayDirection);
|
||||
|
||||
if (myDenominator == 0) {
|
||||
System.err.println("### ERROR @ Intersection / NEGATIVE_INFINITY");
|
||||
return Float.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
final float numer = thePlane.normal.dot(theRayOrigin);
|
||||
final float D = -thePlane.origin.dot(thePlane.normal);
|
||||
myT = -((numer + D) / myDenominator);
|
||||
|
||||
if (theIntersectionPoint != null) {
|
||||
theIntersectionPoint.set(theRayDirection);
|
||||
theIntersectionPoint.scale((float) myT);
|
||||
theIntersectionPoint.add(theRayOrigin);
|
||||
}
|
||||
|
||||
return myT;
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return _myActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
_myActive = theActiveState;
|
||||
}
|
||||
}
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
import teilchen.IConnection;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class Spring
|
||||
implements IForce,
|
||||
IConnection {
|
||||
|
||||
protected float mSpringConstant;
|
||||
|
||||
protected float mSpringDamping;
|
||||
|
||||
protected float mRestLength;
|
||||
|
||||
protected Particle mA;
|
||||
|
||||
protected Particle mB;
|
||||
|
||||
protected boolean mOneWay;
|
||||
|
||||
protected boolean mActive;
|
||||
|
||||
public Spring(Particle theA, Particle theB) {
|
||||
this(theA,
|
||||
theB,
|
||||
2.0f, 0.1f,
|
||||
theA.position().distance(theB.position()));
|
||||
}
|
||||
|
||||
public Spring(Particle theA, Particle theB, float theRestLength) {
|
||||
this(theA,
|
||||
theB,
|
||||
2.0f, 0.1f,
|
||||
theRestLength);
|
||||
}
|
||||
|
||||
public Spring(Particle theA,
|
||||
Particle theB,
|
||||
final float theSpringConstant,
|
||||
final float theSpringDamping) {
|
||||
this(theA,
|
||||
theB,
|
||||
theSpringConstant,
|
||||
theSpringDamping,
|
||||
theA.position().distance(theB.position()));
|
||||
}
|
||||
|
||||
public Spring(final Particle theA,
|
||||
final Particle theB,
|
||||
final float theSpringConstant,
|
||||
final float theSpringDamping,
|
||||
final float theRestLength) {
|
||||
mSpringConstant = theSpringConstant;
|
||||
mSpringDamping = theSpringDamping;
|
||||
mRestLength = theRestLength;
|
||||
mA = theA;
|
||||
mB = theB;
|
||||
mOneWay = false;
|
||||
mActive = true;
|
||||
}
|
||||
|
||||
public void setRestLengthByPosition() {
|
||||
mRestLength = mA.position().distance(mB.position());
|
||||
}
|
||||
|
||||
public float restlength() {
|
||||
return mRestLength;
|
||||
}
|
||||
|
||||
public void restlength(float theRestLength) {
|
||||
mRestLength = theRestLength;
|
||||
}
|
||||
|
||||
public final Particle a() {
|
||||
return mA;
|
||||
}
|
||||
|
||||
public final Particle b() {
|
||||
return mB;
|
||||
}
|
||||
|
||||
public final Particle a(Particle theA) {
|
||||
return mA = theA;
|
||||
}
|
||||
|
||||
public final Particle b(Particle theB) {
|
||||
return mB = theB;
|
||||
}
|
||||
|
||||
public final float currentLength() {
|
||||
return mA.position().distance(mB.position());
|
||||
}
|
||||
|
||||
/**
|
||||
* spring constant.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public final float strength() {
|
||||
return mSpringConstant;
|
||||
}
|
||||
|
||||
/**
|
||||
* spring constant.
|
||||
*
|
||||
* @param theSpringConstant float
|
||||
*/
|
||||
public final void strength(float theSpringConstant) {
|
||||
mSpringConstant = theSpringConstant;
|
||||
}
|
||||
|
||||
public final float damping() {
|
||||
return mSpringDamping;
|
||||
}
|
||||
|
||||
public final void damping(float theSpringDamping) {
|
||||
mSpringDamping = theSpringDamping;
|
||||
}
|
||||
|
||||
public void setOneWay(boolean theOneWayState) {
|
||||
mOneWay = theOneWayState;
|
||||
}
|
||||
|
||||
public void apply(final float theDeltaTime, final Physics theParticleSystem) {
|
||||
// if (!mA.fixed() || !mB.fixed()) {
|
||||
float a2bX = mA.position().x - mB.position().x;
|
||||
float a2bY = mA.position().y - mB.position().y;
|
||||
float a2bZ = mA.position().z - mB.position().z;
|
||||
final float myInversDistance = fastInverseSqrt(a2bX * a2bX + a2bY * a2bY + a2bZ * a2bZ);
|
||||
final float myDistance = 1.0F / myInversDistance;
|
||||
|
||||
if (myDistance == 0.0F) {
|
||||
a2bX = 0.0F;
|
||||
a2bY = 0.0F;
|
||||
a2bZ = 0.0F;
|
||||
} else {
|
||||
a2bX *= myInversDistance;
|
||||
a2bY *= myInversDistance;
|
||||
a2bZ *= myInversDistance;
|
||||
}
|
||||
|
||||
final float mSpringForce = -(myDistance - mRestLength) * mSpringConstant;
|
||||
final float Va2bX = mA.velocity().x - mB.velocity().x;
|
||||
final float Va2bY = mA.velocity().y - mB.velocity().y;
|
||||
final float Va2bZ = mA.velocity().z - mB.velocity().z;
|
||||
final float mDampingForce = -mSpringDamping * (a2bX * Va2bX + a2bY * Va2bY + a2bZ * Va2bZ);
|
||||
final float r = mSpringForce + mDampingForce;
|
||||
a2bX *= r;
|
||||
a2bY *= r;
|
||||
a2bZ *= r;
|
||||
|
||||
if (mOneWay) {
|
||||
if (!mB.fixed()) {
|
||||
mB.force().add(-2 * a2bX, -2 * a2bY, -2 * a2bZ);
|
||||
}
|
||||
} else {
|
||||
if (!mA.fixed()) {
|
||||
mA.force().add(a2bX, a2bY, a2bZ);
|
||||
}
|
||||
if (!mB.fixed()) {
|
||||
mB.force().add(-a2bX, -a2bY, -a2bZ);
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
protected static float fastInverseSqrt(float v) {
|
||||
final float half = 0.5f * v;
|
||||
int i = Float.floatToIntBits(v);
|
||||
i = 0x5f375a86 - (i >> 1);
|
||||
v = Float.intBitsToFloat(i);
|
||||
return v * (1.5f - half * v * v);
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return mA.dead() || mB.dead();
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return mActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
mActive = theActiveState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class TearableSpring
|
||||
extends Spring {
|
||||
|
||||
private boolean _myTornApart = false;
|
||||
|
||||
private float _myTearDistance = -1;
|
||||
|
||||
public TearableSpring(Particle theA, Particle theB) {
|
||||
super(theA,
|
||||
theB,
|
||||
2.0f, 0.1f,
|
||||
theA.position().distance(theB.position()));
|
||||
}
|
||||
|
||||
public TearableSpring(final Particle theA,
|
||||
final Particle theB,
|
||||
final float theSpringConstant,
|
||||
final float theSpringDamping,
|
||||
final float theRestLength,
|
||||
final float theTearDistance) {
|
||||
super(theA,
|
||||
theB,
|
||||
theSpringConstant,
|
||||
theSpringDamping,
|
||||
theRestLength);
|
||||
_myTearDistance = theTearDistance;
|
||||
}
|
||||
|
||||
public final float teardistance() {
|
||||
return _myTearDistance;
|
||||
}
|
||||
|
||||
public final void teardistance(float theTearDistance) {
|
||||
_myTearDistance = theTearDistance;
|
||||
}
|
||||
|
||||
public void apply(final float theDeltaTime, final Physics theParticleSystem) {
|
||||
/* check if spring will tear */
|
||||
if (_myTearDistance > 0) {
|
||||
final float myActualDistance = a().position().distance(b().position());
|
||||
if (myActualDistance > restlength() + _myTearDistance) {
|
||||
_myTornApart = true;
|
||||
}
|
||||
}
|
||||
/* apply force if spring is ok */
|
||||
if (!_myTornApart) {
|
||||
super.apply(theDeltaTime, theParticleSystem);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return _myTornApart || super.dead();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
package teilchen.force;
|
||||
|
||||
import mathematik.Intersection;
|
||||
import mathematik.Intersection.IntersectionResult;
|
||||
import mathematik.Vector3f;
|
||||
import mathematik.WorldAxisAlignedBoundingBox;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.IConstraint;
|
||||
|
||||
public class TriangleDeflector
|
||||
implements IConstraint {
|
||||
|
||||
private final Vector3f a;
|
||||
|
||||
private final Vector3f b;
|
||||
|
||||
private final Vector3f c;
|
||||
|
||||
private final Vector3f mNormal;
|
||||
|
||||
private float mCoefficientOfRestitution;
|
||||
|
||||
private final Vector3f mTempReflectionVector;
|
||||
|
||||
private final Vector3f mTempNormalComponent;
|
||||
|
||||
private final Vector3f mTempTangentComponent;
|
||||
|
||||
private final IntersectionResult mIntersectionResult;
|
||||
|
||||
private final Vector3f mTempPointOfIntersection = new Vector3f();
|
||||
|
||||
private final WorldAxisAlignedBoundingBox mWorldAxisAlignedBoundingBox;
|
||||
|
||||
private final Vector3f[] mVectorCollection;
|
||||
|
||||
public boolean AUTO_UPDATE = true;
|
||||
|
||||
private boolean mGotHit = false;
|
||||
|
||||
private boolean mActive;
|
||||
|
||||
public TriangleDeflector() {
|
||||
a = new Vector3f();
|
||||
b = new Vector3f();
|
||||
c = new Vector3f();
|
||||
|
||||
/* hmmm. */
|
||||
mVectorCollection = new Vector3f[3];
|
||||
mVectorCollection[0] = a;
|
||||
mVectorCollection[1] = b;
|
||||
mVectorCollection[2] = c;
|
||||
|
||||
mNormal = new Vector3f();
|
||||
mCoefficientOfRestitution = 1.0f;
|
||||
|
||||
mTempReflectionVector = new Vector3f();
|
||||
mTempNormalComponent = new Vector3f();
|
||||
mTempTangentComponent = new Vector3f();
|
||||
mIntersectionResult = new IntersectionResult();
|
||||
mWorldAxisAlignedBoundingBox = new WorldAxisAlignedBoundingBox();
|
||||
|
||||
mActive = true;
|
||||
}
|
||||
|
||||
public Vector3f a() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public Vector3f b() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public Vector3f c() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public WorldAxisAlignedBoundingBox boundingbox() {
|
||||
return mWorldAxisAlignedBoundingBox;
|
||||
}
|
||||
|
||||
public void updateProperties() {
|
||||
mVectorCollection[0] = a;
|
||||
mVectorCollection[1] = b;
|
||||
mVectorCollection[2] = c;
|
||||
mathematik.Util.calculateNormal(a, b, c, mNormal);
|
||||
mathematik.Util.updateBoundingBox(mWorldAxisAlignedBoundingBox, mVectorCollection);
|
||||
}
|
||||
|
||||
private float mPreviousT = -1.0f;
|
||||
|
||||
public void apply(Physics pParticleSystem) {
|
||||
// public void apply(final float pDeltaTime, final Physics pParticleSystem) {
|
||||
|
||||
/* update triangle properties -- maybe this is better not done automatically */
|
||||
if (AUTO_UPDATE) {
|
||||
updateProperties();
|
||||
}
|
||||
|
||||
mGotHit = false;
|
||||
for (final Particle myParticle : pParticleSystem.particles()) {
|
||||
if (!myParticle.fixed()) {
|
||||
final boolean IGNORE_BOUNDING_BOX = true;
|
||||
|
||||
/* adjust boundingbox width to particle velocity to avoid particle shooting through the boundingbox */
|
||||
final Vector3f myTempBoundingBoxScale = new Vector3f(mWorldAxisAlignedBoundingBox.scale);
|
||||
if (!IGNORE_BOUNDING_BOX) {
|
||||
if (myParticle.velocity().x > mWorldAxisAlignedBoundingBox.scale.x) {
|
||||
mWorldAxisAlignedBoundingBox.scale.x = myParticle.velocity().x;
|
||||
}
|
||||
if (myParticle.velocity().y > mWorldAxisAlignedBoundingBox.scale.y) {
|
||||
mWorldAxisAlignedBoundingBox.scale.y = myParticle.velocity().y;
|
||||
}
|
||||
if (myParticle.velocity().z > mWorldAxisAlignedBoundingBox.scale.z) {
|
||||
mWorldAxisAlignedBoundingBox.scale.z = myParticle.velocity().z;
|
||||
}
|
||||
}
|
||||
|
||||
/* only test if in bounding box */
|
||||
if (IGNORE_BOUNDING_BOX || mathematik.Util.contains(myParticle.position(), mWorldAxisAlignedBoundingBox)) {
|
||||
final Vector3f mRay;
|
||||
final int RAY_FROM_VELOCITY = 0;
|
||||
final int RAY_FROM_NORMAL = 1;
|
||||
final int RAY_FROM_OLD_POSITION = 2;
|
||||
final int CREATE_RAY_FROM = RAY_FROM_OLD_POSITION;
|
||||
|
||||
switch (CREATE_RAY_FROM) {
|
||||
case RAY_FROM_VELOCITY:
|
||||
mRay = myParticle.velocity();
|
||||
break;
|
||||
case RAY_FROM_NORMAL:
|
||||
mRay = mathematik.Util.scale(mNormal, -myParticle.velocity().length());
|
||||
break;
|
||||
case RAY_FROM_OLD_POSITION:
|
||||
mRay = mathematik.Util.sub(myParticle.position(), myParticle.old_position());
|
||||
break;
|
||||
default:
|
||||
mRay = new Vector3f(1, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mRay.isNaN()) {
|
||||
break;
|
||||
}
|
||||
if (mRay.lengthSquared() == 0) {
|
||||
break;
|
||||
}
|
||||
final boolean mSuccess = Intersection.intersectRayTriangle(myParticle.position(),
|
||||
mRay,
|
||||
a, b, c,
|
||||
mIntersectionResult,
|
||||
true);
|
||||
/* is particle past plane. */
|
||||
if (mSuccess && mIntersectionResult.t <= 0 && mPreviousT > 0) {
|
||||
mTempPointOfIntersection.set(mRay);
|
||||
mTempPointOfIntersection.scale(mIntersectionResult.t);
|
||||
mTempPointOfIntersection.add(myParticle.position());
|
||||
myParticle.position().set(mTempPointOfIntersection);
|
||||
|
||||
/* reflect velocity i.e. change direction */
|
||||
seperateComponents(myParticle, mNormal);
|
||||
myParticle.velocity().set(mTempReflectionVector);
|
||||
|
||||
mGotHit = true;
|
||||
myParticle.tag(true);
|
||||
markParticle(myParticle);
|
||||
// mPreviousT = 0.0f; /* ??? */
|
||||
|
||||
}
|
||||
if (mSuccess) {
|
||||
mPreviousT = mIntersectionResult.t;
|
||||
} else {
|
||||
mPreviousT = 0.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* reset boundingbox scale */
|
||||
if (!IGNORE_BOUNDING_BOX) {
|
||||
mWorldAxisAlignedBoundingBox.scale.set(myTempBoundingBoxScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void markParticle(Particle pParticle) {
|
||||
}
|
||||
|
||||
public boolean hit() {
|
||||
return mGotHit;
|
||||
}
|
||||
|
||||
public void coefficientofrestitution(float pCoefficientOfRestitution) {
|
||||
mCoefficientOfRestitution = pCoefficientOfRestitution;
|
||||
}
|
||||
|
||||
public float coefficientofrestitution() {
|
||||
return mCoefficientOfRestitution;
|
||||
}
|
||||
|
||||
private void seperateComponents(Particle pParticle, Vector3f pNormal) {
|
||||
/* normal */
|
||||
mTempNormalComponent.set(pNormal);
|
||||
mTempNormalComponent.scale(pNormal.dot(pParticle.velocity()));
|
||||
/* tangent */
|
||||
mTempTangentComponent.sub(pParticle.velocity(), mTempNormalComponent);
|
||||
/* negate normal */
|
||||
mTempNormalComponent.scale(-mCoefficientOfRestitution);
|
||||
/* set reflection vector */
|
||||
mTempReflectionVector.add(mTempTangentComponent, mTempNormalComponent);
|
||||
}
|
||||
|
||||
public Vector3f normal() {
|
||||
return mNormal;
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return mActive;
|
||||
}
|
||||
|
||||
public void active(boolean pActiveState) {
|
||||
mActive = pActiveState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
public class TriangleDeflectorIndexed
|
||||
extends TriangleDeflector {
|
||||
|
||||
private final int a_index;
|
||||
|
||||
private final int b_index;
|
||||
|
||||
private final int c_index;
|
||||
|
||||
private final float[] _myVertices;
|
||||
|
||||
public TriangleDeflectorIndexed(float[] theVertices, int theA, int theB, int theC) {
|
||||
super();
|
||||
_myVertices = theVertices;
|
||||
a_index = theA;
|
||||
b_index = theB;
|
||||
c_index = theC;
|
||||
updateProperties();
|
||||
}
|
||||
|
||||
public void updateProperties() {
|
||||
updateVertices();
|
||||
super.updateProperties();
|
||||
}
|
||||
|
||||
private void updateVertices() {
|
||||
a().set(_myVertices[a_index + 0],
|
||||
_myVertices[a_index + 1],
|
||||
_myVertices[a_index + 2]);
|
||||
b().set(_myVertices[b_index + 0],
|
||||
_myVertices[b_index + 1],
|
||||
_myVertices[b_index + 2]);
|
||||
c().set(_myVertices[c_index + 0],
|
||||
_myVertices[c_index + 1],
|
||||
_myVertices[c_index + 2]);
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force;
|
||||
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.integration.Verlet;
|
||||
|
||||
|
||||
public class ViscousDrag
|
||||
implements IForce {
|
||||
|
||||
public float coefficient;
|
||||
|
||||
private boolean _myActive;
|
||||
|
||||
public ViscousDrag(float theCoefficient) {
|
||||
coefficient = theCoefficient;
|
||||
_myActive = true;
|
||||
}
|
||||
|
||||
public ViscousDrag() {
|
||||
this(1.0f);
|
||||
}
|
||||
|
||||
public final void apply(final float theDeltaTime, final Physics theParticleSystem) {
|
||||
if (theParticleSystem.getIntegrator() instanceof Verlet) {
|
||||
return;
|
||||
}
|
||||
if (coefficient != 0) {
|
||||
for (final Particle myParticle : theParticleSystem.particles()) {
|
||||
if (!myParticle.fixed()) {
|
||||
myParticle.force().add(myParticle.velocity().x * -coefficient,
|
||||
myParticle.velocity().y * -coefficient,
|
||||
myParticle.velocity().z * -coefficient);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return _myActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
_myActive = theActiveState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,503 @@
|
||||
package teilchen.force.flowfield;
|
||||
|
||||
|
||||
import java.util.Vector;
|
||||
import mathematik.TransformMatrix4f;
|
||||
import mathematik.Vector3f;
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.force.IForce;
|
||||
|
||||
|
||||
/*
|
||||
* todo:
|
||||
* make density switchable
|
||||
* clean redundancies
|
||||
*/
|
||||
public class FlowField implements IForce {
|
||||
|
||||
public int n = 100; // The size of the calculation grid
|
||||
|
||||
private int _myGridSize = n + 2; // Extra grid space for boundary
|
||||
|
||||
private int _myPixelSize = 10; // The size of each grid square on the screen
|
||||
|
||||
// I unravelled the 1D arrays from Jos Stam's paper back to 2D arrays, as we don't have compile time macros in Java...
|
||||
private float[][] u = new float[_myGridSize][_myGridSize];
|
||||
|
||||
private float[][] v = new float[_myGridSize][_myGridSize];
|
||||
|
||||
private float[][] uPrev = new float[_myGridSize][_myGridSize];
|
||||
|
||||
private float[][] vPrev = new float[_myGridSize][_myGridSize];
|
||||
|
||||
private float[][] dens = new float[_myGridSize][_myGridSize];
|
||||
|
||||
private float[][] densPrev = new float[_myGridSize][_myGridSize];
|
||||
|
||||
private float viscosity = 0.0001f; // Viscosity of fluid
|
||||
|
||||
public float deltatime = 0.2f; // Rate of change
|
||||
|
||||
private float diff = 0.0001f; // Degree of diffusion of density over time
|
||||
|
||||
private int densityBrushSize = n / 10; // Size of the density area applied with the mouse
|
||||
|
||||
public int velocityBrushSize = n / 20; // Ditto velocity
|
||||
|
||||
private int lineSpacing = n / n; // Spacing between velocity and normal lines
|
||||
|
||||
public boolean showHair = true;
|
||||
|
||||
public boolean showVelocity = true;
|
||||
|
||||
public boolean calculateDensity = true;
|
||||
|
||||
public boolean calculateVelocity = true;
|
||||
|
||||
private Vector3f _myScale;
|
||||
|
||||
private TransformMatrix4f _myTransform;
|
||||
|
||||
private Vector<FlowFieldForce> _myForces;
|
||||
|
||||
public float forceScale = 1;
|
||||
|
||||
public FlowField() {
|
||||
n = 100;
|
||||
init();
|
||||
}
|
||||
|
||||
public FlowField(int theResolutionX, int theResolutionY, Vector3f theScale) {
|
||||
n = theResolutionX;
|
||||
init();
|
||||
_myScale.set(theScale);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
_myScale = new Vector3f();
|
||||
_myTransform = new TransformMatrix4f();
|
||||
_myForces = new Vector<FlowFieldForce>();
|
||||
_myGridSize = n + 2;
|
||||
u = new float[_myGridSize][_myGridSize];
|
||||
v = new float[_myGridSize][_myGridSize];
|
||||
uPrev = new float[_myGridSize][_myGridSize];
|
||||
vPrev = new float[_myGridSize][_myGridSize];
|
||||
dens = new float[_myGridSize][_myGridSize];
|
||||
densPrev = new float[_myGridSize][_myGridSize];
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
initVelocity();
|
||||
initDensity();
|
||||
}
|
||||
|
||||
public void addForce(FlowFieldForce theForce) {
|
||||
_myForces.add(theForce);
|
||||
}
|
||||
|
||||
private void updateForces() {
|
||||
for (FlowFieldForce myForce : _myForces) {
|
||||
myForce.applyForce(this);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector<FlowFieldForce> forces() {
|
||||
return _myForces;
|
||||
}
|
||||
|
||||
public void setForce() {
|
||||
initField(densPrev);
|
||||
initField(uPrev);
|
||||
initField(vPrev);
|
||||
}
|
||||
|
||||
public float[][] u() {
|
||||
return u;
|
||||
}
|
||||
|
||||
public float[][] v() {
|
||||
return v;
|
||||
}
|
||||
|
||||
//float[][] field, int x, int y, float s, float r
|
||||
public void setForceArea(float[][] field, int x, int y, float s, float r) {
|
||||
for (int i = (int) (clamp(x - r, 1, n)); i <= (int) (clamp(x + r, 1, n)); i++) {
|
||||
int dx = x - i;
|
||||
for (int j = (int) (clamp(y - r, 1, n)); j <= (int) (clamp(y + r, 1, n)); j++) {
|
||||
int dy = y - j;
|
||||
float f = 1 - ((float) Math.sqrt(dx * dx + dy * dy) / r);
|
||||
field[i][j] += clamp(f, 0, 1) * s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setForce(float theX, float theY, Vector3f theStrength, float theRadius) {
|
||||
int x = (int) (theX / _myScale.x * n);
|
||||
int y = (int) (theY / _myScale.y * n);
|
||||
for (int i = (int) (clamp(x - theRadius, 1, n)); i <= (int) (clamp(x + theRadius, 1, n)); i++) {
|
||||
int dx = x - i;
|
||||
for (int j = (int) (clamp(y - theRadius, 1, n)); j <= (int) (clamp(y + theRadius, 1, n)); j++) {
|
||||
int dy = y - j;
|
||||
float f = 1 - ((float) Math.sqrt(dx * dx + dy * dy) / theRadius);
|
||||
u[i][j] += clamp(f, 0, 1) * theStrength.x;
|
||||
v[i][j] += clamp(f, 0, 1) * theStrength.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//public void calculateVelocity(float[][] u, float[][] v, float[][] u0, float[][] v0, float visc, float dt
|
||||
public void calculateVelocity() {
|
||||
|
||||
addSource(u, uPrev, deltatime);
|
||||
addSource(v, vPrev, deltatime);
|
||||
|
||||
float[][] tmp;
|
||||
tmp = u;
|
||||
u = uPrev;
|
||||
uPrev = tmp;
|
||||
tmp = v;
|
||||
v = vPrev;
|
||||
vPrev = tmp;
|
||||
|
||||
diffuse(1, u, uPrev, viscosity, deltatime);
|
||||
diffuse(2, v, vPrev, viscosity, deltatime);
|
||||
|
||||
project(u, v, uPrev, vPrev);
|
||||
|
||||
tmp = u;
|
||||
u = uPrev;
|
||||
uPrev = tmp;
|
||||
tmp = v;
|
||||
v = vPrev;
|
||||
vPrev = tmp;
|
||||
|
||||
advect(1, u, uPrev, uPrev, vPrev, deltatime);
|
||||
advect(2, v, vPrev, uPrev, vPrev, deltatime);
|
||||
|
||||
project(u, v, uPrev, vPrev);
|
||||
}
|
||||
|
||||
// public void calculateDensity(float[][] x, float[][] x0, float[][] u, float[][] v, float diff, float dt) {
|
||||
public void calculateDensity() {
|
||||
float[][] tmp;
|
||||
|
||||
addSource(dens, densPrev, deltatime);
|
||||
tmp = dens;
|
||||
dens = densPrev;
|
||||
densPrev = tmp;
|
||||
diffuse(0, dens, densPrev, diff, deltatime);
|
||||
tmp = dens;
|
||||
dens = densPrev;
|
||||
densPrev = tmp;
|
||||
advect(0, dens, densPrev, u, v, deltatime);
|
||||
}
|
||||
|
||||
public void loop(final float theDeltaTime) {
|
||||
updateForces();
|
||||
setForce();
|
||||
deltatime = theDeltaTime;
|
||||
|
||||
if (calculateVelocity) {
|
||||
calculateVelocity();
|
||||
}
|
||||
if (calculateDensity) {
|
||||
calculateDensity();
|
||||
}
|
||||
}
|
||||
|
||||
// public void draw(GLContext theRenderContext) {
|
||||
// GL gl = ( theRenderContext).gl;
|
||||
// float vu;
|
||||
// float vv;
|
||||
//
|
||||
// gl.glPushMatrix();
|
||||
// JoglUtil.applyTransform(gl,
|
||||
// _myTransformMode,
|
||||
// transform,
|
||||
// rotation,
|
||||
// scale);
|
||||
//
|
||||
// material.begin(theRenderContext);
|
||||
//
|
||||
// for (int y = 1; y <= n; y++) {
|
||||
// for (int x = 1; x <= n; x++) {
|
||||
// if (showHair) {
|
||||
// if ((x % lineSpacing) == 0 && (y % lineSpacing) == 0) {
|
||||
//
|
||||
// float myRatioX = x / (float) n;
|
||||
// float myRatioY = y / (float) n;
|
||||
// vu = u[x][y];
|
||||
// vv = v[x][y];
|
||||
// Vector2f myDirection = new Vector2f(vu, vv);
|
||||
// float VIEW_VECTOR_LENGTH = myDirection.length();
|
||||
// float myAlpha = material.color.a * VIEW_VECTOR_LENGTH;
|
||||
// gl.glLineWidth(10);
|
||||
//
|
||||
// float myTargetLength = VIEW_VECTOR_LENGTH;
|
||||
//
|
||||
// gl.glBegin(GL.GL_LINES);
|
||||
// gl.glColor4f(material.color.r, material.color.g, material.color.b, 0);
|
||||
// gl.glVertex3f(myRatioX,
|
||||
// myRatioY,
|
||||
// 0);
|
||||
//
|
||||
// myTargetLength = VIEW_VECTOR_LENGTH * 0.05f;
|
||||
// gl.glColor4f(material.color.r, material.color.g, material.color.b, myAlpha);
|
||||
// gl.glVertex3f(myRatioX + vu * myTargetLength,
|
||||
// myRatioY + vv * myTargetLength,
|
||||
// 0);
|
||||
// gl.glEnd();
|
||||
//
|
||||
// gl.glBegin(GL.GL_LINES);
|
||||
// gl.glColor4f(material.color.r, material.color.g, material.color.b, myAlpha);
|
||||
// gl.glVertex3f(myRatioX + vu * myTargetLength,
|
||||
// myRatioY + vv * myTargetLength,
|
||||
// 0);
|
||||
//
|
||||
// myTargetLength = VIEW_VECTOR_LENGTH * 0.6f;
|
||||
// gl.glColor4f(material.color.r, material.color.g, material.color.b, 0);
|
||||
// gl.glVertex3f(myRatioX + vu * myTargetLength,
|
||||
// myRatioY + vv * myTargetLength,
|
||||
// 0);
|
||||
// gl.glEnd();
|
||||
// }
|
||||
// }
|
||||
// if (showVelocity) {
|
||||
// if ((x % lineSpacing) == 0 && (y % lineSpacing) == 0) {
|
||||
//
|
||||
// float myRatioX = x / (float) n;
|
||||
// float myRatioY = y / (float) n;
|
||||
// vu = u[x][y];
|
||||
// vv = v[x][y];
|
||||
// Vector2f myDirection = new Vector2f(vu, vv);
|
||||
// myDirection.normalize();
|
||||
// myDirection.scale(3);
|
||||
//
|
||||
// gl.glBegin(GL.GL_LINES);
|
||||
// gl.glVertex3f(myRatioX,
|
||||
// myRatioY,
|
||||
// 0);
|
||||
// gl.glVertex3f(myRatioX + vu,
|
||||
// myRatioY + vv,
|
||||
// 0);
|
||||
// gl.glEnd();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// gl.glPopMatrix();
|
||||
// material.end(theRenderContext);
|
||||
// }
|
||||
public Vector3f scale() {
|
||||
return _myScale;
|
||||
}
|
||||
|
||||
public TransformMatrix4f transform() {
|
||||
return _myTransform;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return _myTransform.translation;
|
||||
}
|
||||
|
||||
private float clamp(float f, float minf, float maxf) {
|
||||
return Math.max(Math.min(f, maxf), minf);
|
||||
}
|
||||
|
||||
private void initField(float[][] f) {
|
||||
for (int i = 0; i < _myGridSize; i++) {
|
||||
for (int j = 0; j < _myGridSize; j++) {
|
||||
f[i][j] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initVelocity() {
|
||||
initField(u);
|
||||
initField(v);
|
||||
initField(uPrev);
|
||||
initField(vPrev);
|
||||
}
|
||||
|
||||
private void initDensity() {
|
||||
initField(dens);
|
||||
initField(densPrev);
|
||||
}
|
||||
|
||||
public Vector3f getForce(Vector3f thePosition) {
|
||||
Vector3f myDeltaPos = new Vector3f(thePosition);
|
||||
myDeltaPos.sub(position());
|
||||
float myRatioX = myDeltaPos.x / _myScale.x;
|
||||
float myRatioY = myDeltaPos.y / _myScale.y;
|
||||
if (myRatioX >= 0 && myRatioX <= 1 && myRatioY >= 0 && myRatioY <= 1) {
|
||||
int myIndexX = (int) (myRatioX * (u.length - 1));
|
||||
int myIndexY = (int) (myRatioY * (v.length - 1));
|
||||
if (u[myIndexX] == null || v[myIndexY] == null) {
|
||||
System.out.println(myIndexX + " " + myIndexY);
|
||||
}
|
||||
Vector3f myForce = new Vector3f(u()[myIndexX][myIndexY], v()[myIndexX][myIndexY], 0);
|
||||
return myForce;
|
||||
}
|
||||
return new Vector3f();
|
||||
}
|
||||
|
||||
private void addSource(float[][] x, float[][] s, float dt) {
|
||||
for (int i = 0; i < _myGridSize; i++) {
|
||||
for (int j = 0; j < _myGridSize; j++) {
|
||||
x[i][j] += s[i][j] * dt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setBnd(int b, float[][] x) {
|
||||
// for (int i = 1; i <= n; i++) {
|
||||
// if (b == 1) {
|
||||
// x[0][i] = -x[1][i];
|
||||
// } else {
|
||||
// x[0][i] = x[1][i];
|
||||
// }
|
||||
// if (b == 1) {
|
||||
// x[n + 1][i] = -x[n][i];
|
||||
// } else {
|
||||
// x[n + 1][i] = x[n][i];
|
||||
// }
|
||||
// if (b == 2) {
|
||||
// x[i][0] = -x[i][1];
|
||||
// } else {
|
||||
// x[i][0] = x[i][1];
|
||||
// }
|
||||
// if (b == 2) {
|
||||
// x[i][n + 1] = -x[i][n];
|
||||
// } else {
|
||||
// x[i][n + 1] = x[i][n];
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// x[0][0] = 0.5f * (x[1][0] + x[0][1]);
|
||||
// x[0][n + 1] = 0.5f * (x[1][n + 1] + x[0][n]);
|
||||
// x[n + 1][0] = 0.5f * (x[n][0] + x[n + 1][1]);
|
||||
// x[n + 1][n + 1] = 0.5f * (x[n][n + 1] + x[n + 1][n]);
|
||||
}
|
||||
|
||||
private void diffuse(int b, float[][] x, float[][] x0, float diff, float dt) {
|
||||
|
||||
int i, j, k;
|
||||
float a = dt * diff * n * n;
|
||||
|
||||
/* todo: why is it '20' */
|
||||
// for (k = 0; k < 20; k++) {
|
||||
for (i = 1; i <= n; i++) {
|
||||
for (j = 1; j <= n; j++) {
|
||||
x[i][j] = (x0[i][j] + a * (x[i - 1][j] + x[i + 1][j] + x[i][j - 1] + x[i][j + 1])) / (1 + 4 * a);
|
||||
}
|
||||
}
|
||||
setBnd(b, x);
|
||||
// }
|
||||
}
|
||||
|
||||
private void project(float[][] u, float[][] v, float[][] p, float[][] div) {
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
float h;
|
||||
|
||||
h = 1.0f / n;
|
||||
/* todo check loop */
|
||||
for (i = 1; i <= n; i++) {
|
||||
for (j = 1; j <= n; j++) {
|
||||
div[i][j] = -0.5f * h * (u[i + 1][j] - u[i - 1][j] + v[i][j + 1] - v[i][j - 1]);
|
||||
p[i][j] = 0;
|
||||
}
|
||||
}
|
||||
setBnd(0, div);
|
||||
setBnd(0, p);
|
||||
|
||||
/* todo: why is it '20' */
|
||||
for (k = 0; k < 20; k++) {
|
||||
for (i = 1; i <= n; i++) {
|
||||
for (j = 1; j <= n; j++) {
|
||||
p[i][j] = (div[i][j] + p[i - 1][j] + p[i + 1][j] + p[i][j - 1] + p[i][j + 1]) / 4;
|
||||
}
|
||||
}
|
||||
setBnd(0, p);
|
||||
}
|
||||
|
||||
/* todo check loop */
|
||||
for (i = 1; i <= n; i++) {
|
||||
for (j = 1; j <= n; j++) {
|
||||
u[i][j] -= 0.5f * (p[i + 1][j] - p[i - 1][j]) / h;
|
||||
v[i][j] -= 0.5f * (p[i][j + 1] - p[i][j - 1]) / h;
|
||||
}
|
||||
}
|
||||
setBnd(1, u);
|
||||
setBnd(2, v);
|
||||
}
|
||||
|
||||
private void advect(int b, float[][] d, float[][] d0, float[][] u, float[][] v, float dt) {
|
||||
int i;
|
||||
int j;
|
||||
int i0;
|
||||
int j0;
|
||||
int i1;
|
||||
int j1;
|
||||
float x;
|
||||
float y;
|
||||
float s0;
|
||||
float t0;
|
||||
float s1;
|
||||
float t1;
|
||||
float dt0;
|
||||
|
||||
dt0 = dt * n;
|
||||
/* todo check loop */
|
||||
for (i = 1; i <= n; i++) {
|
||||
for (j = 1; j <= n; j++) {
|
||||
x = i - dt0 * u[i][j];
|
||||
y = j - dt0 * v[i][j];
|
||||
|
||||
x = Math.max(0.5f, x);
|
||||
x = Math.min(n + 0.5f, x);
|
||||
|
||||
i0 = (int) Math.floor(x);
|
||||
i1 = i0 + 1;
|
||||
|
||||
y = Math.max(0.5f, y);
|
||||
y = Math.min(n + 0.5f, y);
|
||||
|
||||
j0 = (int) Math.floor(y);
|
||||
j1 = j0 + 1;
|
||||
|
||||
s1 = x - i0;
|
||||
s0 = 1 - s1;
|
||||
t1 = y - j0;
|
||||
t0 = 1 - t1;
|
||||
|
||||
d[i][j] = s0 * (t0 * d0[i0][j0] + t1 * d0[i0][j1])
|
||||
+ s1 * (t0 * d0[i1][j0] + t1 * d0[i1][j1]);
|
||||
}
|
||||
}
|
||||
setBnd(b, d);
|
||||
}
|
||||
|
||||
public void apply(float theDeltaTime, Physics theParticleSystem) {
|
||||
for (Particle myParticle : theParticleSystem.particles()) {
|
||||
if (!myParticle.fixed()) {
|
||||
Vector3f myForce = getForce(myParticle.position());
|
||||
myForce.scale(forceScale);
|
||||
myParticle.force().add(myForce);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force.flowfield;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
|
||||
public abstract class FlowFieldForce {
|
||||
|
||||
public Vector3f strength = new Vector3f();
|
||||
|
||||
public float range;
|
||||
|
||||
public Vector3f position = new Vector3f();
|
||||
|
||||
public abstract void applyForce(FlowField theField);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force.flowfield;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
|
||||
public class FlowFieldForceMOUSE extends FlowFieldForce {
|
||||
|
||||
private Vector3f _myOldPosition;
|
||||
|
||||
public FlowFieldForceMOUSE() {
|
||||
_myOldPosition = new Vector3f();
|
||||
}
|
||||
|
||||
public void setPosition(Vector3f thePosition) {
|
||||
position.set(thePosition);
|
||||
strength.set(thePosition);
|
||||
strength.sub(_myOldPosition);
|
||||
_myOldPosition.set(position);
|
||||
}
|
||||
|
||||
public void applyForce(FlowField theField) {
|
||||
theField.setForce(position.x, position.y, strength, range);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force.vectorfield;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
import mathematik.Vector3i;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.VectorfieldParticle;
|
||||
import teilchen.force.IForce;
|
||||
|
||||
|
||||
public class VectorField
|
||||
implements IForce {
|
||||
|
||||
private VectorFieldUnit[][][] _myField;
|
||||
|
||||
public float strength;
|
||||
|
||||
private Vector3f _myPosition;
|
||||
|
||||
private Vector3f _myScale;
|
||||
|
||||
private boolean _myActive;
|
||||
|
||||
public VectorField(VectorFieldGenerator theGenerator) {
|
||||
/* init fields */
|
||||
strength = 1;
|
||||
_myPosition = new Vector3f();
|
||||
_myScale = new Vector3f(1f, 1f, 1f);
|
||||
_myField = theGenerator.data();
|
||||
_myActive = true;
|
||||
}
|
||||
|
||||
public VectorFieldUnit[][][] data() {
|
||||
return _myField;
|
||||
}
|
||||
|
||||
public Vector3f getPosition() {
|
||||
return _myPosition;
|
||||
}
|
||||
|
||||
public void setPosition(final Vector3f thePosition) {
|
||||
_myPosition.set(thePosition);
|
||||
for (int x = 0; x < _myField.length; x++) {
|
||||
for (int y = 0; y < _myField[x].length; y++) {
|
||||
for (int z = 0; z < _myField[x][y].length; z++) {
|
||||
Vector3f myPosition = new Vector3f(x
|
||||
* (_myScale.x / (float) _myField.length),
|
||||
y * (_myScale.y / (float) _myField[x].length),
|
||||
z * (_myScale.z / (float) _myField[x][y].length));
|
||||
_myField[x][y][z].getPosition().set(myPosition);
|
||||
_myField[x][y][z].getPosition().add(thePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final Vector3f getScale() {
|
||||
return _myScale;
|
||||
}
|
||||
|
||||
public void setScale(final Vector3f theScale) {
|
||||
_myScale.set(theScale);
|
||||
for (int x = 0; x < _myField.length; x++) {
|
||||
for (int y = 0; y < _myField[x].length; y++) {
|
||||
for (int z = 0; z < _myField[x][y].length; z++) {
|
||||
Vector3f myUnitScale = new Vector3f(_myScale.x
|
||||
/ (float) _myField.length,
|
||||
_myScale.y / (float) _myField[x].length,
|
||||
_myScale.z / (float) _myField[x][y].length);
|
||||
_myField[x][y][z].setScale(myUnitScale);
|
||||
Vector3f myPosition = new Vector3f(x
|
||||
* (_myScale.x / (float) _myField.length),
|
||||
y * (_myScale.y / (float) _myField[x].length),
|
||||
z * (_myScale.z / (float) _myField[x][y].length));
|
||||
myPosition.add(_myPosition);
|
||||
_myField[x][y][z].setPosition(myPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// public void setScale(final Vector3f theScale) {
|
||||
// _myScale.set(theScale);
|
||||
// for (int x = 0; x < _myField.length; x++) {
|
||||
// for (int y = 0; y < _myField[x].length; y++) {
|
||||
// for (int z = 0; z < _myField[x][y].length; z++) {
|
||||
// Vector3f myUnitScale = new Vector3f(_myScale.x,
|
||||
// _myScale.y,
|
||||
// _myScale.z);
|
||||
// _myField[x][y][z].setScale(myUnitScale);
|
||||
// Vector3f myPosition = new Vector3f(x *
|
||||
// (_myScale.x),
|
||||
// y * (_myScale.y),
|
||||
// z * (_myScale.z));
|
||||
// myPosition.add(_myPosition);
|
||||
// _myField[x][y][z].setPosition(myPosition);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
/* IForce */
|
||||
private Vector3f force(float theDeltaTime, VectorfieldParticle theParticle) {
|
||||
if (isInBoundingBox(theParticle)) {
|
||||
Vector3i myUnit = checkIfIsInside(theParticle, 1);
|
||||
if (myUnit != null) {
|
||||
Vector3f myAcceleration = new Vector3f(_myField[myUnit.x][
|
||||
myUnit.y][
|
||||
myUnit.z].
|
||||
getAcceleration());
|
||||
myAcceleration.scale(strength);
|
||||
theParticle.setLastUnit(myUnit);
|
||||
return myAcceleration;
|
||||
}
|
||||
for (int x = 0; x < _myField.length; x++) {
|
||||
for (int y = 0; y < _myField[x].length; y++) {
|
||||
for (int z = 0; z < _myField[x][y].length; z++) {
|
||||
if (_myField[x][y][z].isInside(theParticle.position())) {
|
||||
Vector3f myAcceleration = new Vector3f(_myField[x][
|
||||
y][z].
|
||||
getAcceleration());
|
||||
myAcceleration.scale(strength);
|
||||
theParticle.setLastUnit(new Vector3i(x, y, z));
|
||||
return myAcceleration;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Vector3f();
|
||||
}
|
||||
|
||||
private boolean isInBoundingBox(VectorfieldParticle theParticle) {
|
||||
if (theParticle.position().x >= _myPosition.x
|
||||
&& theParticle.position().x <= _myPosition.x + _myScale.x
|
||||
&& theParticle.position().y >= _myPosition.y
|
||||
&& theParticle.position().y <= _myPosition.y + _myScale.y
|
||||
&& theParticle.position().z >= _myPosition.z
|
||||
&& theParticle.position().z <= _myPosition.z + _myScale.z) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Vector3i checkIfIsInside(VectorfieldParticle theParticle,
|
||||
int theRadius) {
|
||||
Vector3i myUnit = new Vector3i(theParticle.getLastUnit());
|
||||
for (int x = myUnit.x - theRadius; x < myUnit.x + theRadius; x++) {
|
||||
for (int y = myUnit.y - theRadius; y < myUnit.y + theRadius; y++) {
|
||||
for (int z = myUnit.z - theRadius; z < myUnit.z + theRadius; z++) {
|
||||
if (x >= 0 && x < _myField.length
|
||||
&& y >= 0 && y < _myField[x].length
|
||||
&& z >= 0 && z < _myField[x][y].length) {
|
||||
if (_myField[x][y][z].isInside(theParticle.position())) {
|
||||
return new Vector3i(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void apply(final float theDeltaTime,
|
||||
final Physics theParticleSystem) {
|
||||
/**
|
||||
* @todo clean up force method
|
||||
*/
|
||||
for (final Particle myParticle : theParticleSystem.particles()) {
|
||||
if (!myParticle.fixed()) {
|
||||
if (myParticle instanceof VectorfieldParticle) {
|
||||
myParticle.force().add(force(theDeltaTime,
|
||||
(VectorfieldParticle) myParticle));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean dead() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
return _myActive;
|
||||
}
|
||||
|
||||
public void active(boolean theActiveState) {
|
||||
_myActive = theActiveState;
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force.vectorfield;
|
||||
|
||||
|
||||
public interface VectorFieldGenerator {
|
||||
|
||||
VectorFieldUnit[][][] data();
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force.vectorfield;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
|
||||
public class VectorFieldGeneratorAVERAGEUNITS
|
||||
implements VectorFieldGenerator {
|
||||
|
||||
private VectorFieldUnit[][][] _myField;
|
||||
|
||||
public VectorFieldGeneratorAVERAGEUNITS(int theSizeX,
|
||||
int theSizeY,
|
||||
int theSizeZ,
|
||||
Vector3f[] theCoordinats,
|
||||
Vector3f[] theAccelerations) {
|
||||
/* populate field */
|
||||
_myField = new VectorFieldUnit[theSizeX][theSizeY][theSizeZ];
|
||||
for (int x = 0; x < theSizeX; x++) {
|
||||
for (int y = 0; y < theSizeY; y++) {
|
||||
for (int z = 0; z < theSizeZ; z++) {
|
||||
Vector3f myPosition = new Vector3f(x
|
||||
* (1f / (float) theSizeX),
|
||||
y * (1f / (float) theSizeY),
|
||||
z * (1f / (float) theSizeZ));
|
||||
Vector3f myScale = new Vector3f(1f
|
||||
/ (float) theSizeX,
|
||||
1f / (float) theSizeY,
|
||||
1f / (float) theSizeZ);
|
||||
Vector3f myAcceleration = new Vector3f(1f, 1f, 1f);
|
||||
VectorFieldUnit myUnit = new VectorFieldUnit(myPosition,
|
||||
myScale,
|
||||
myAcceleration);
|
||||
_myField[x][y][z] = myUnit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float myMaxDistance = (float) Math.sqrt(2);
|
||||
for (int x = 0; x < theSizeX; x++) {
|
||||
for (int y = 0; y < theSizeY; y++) {
|
||||
for (int z = 0; z < theSizeZ; z++) {
|
||||
Vector3f myAcceleration = new Vector3f();
|
||||
VectorFieldUnit myUnit = _myField[x][y][z];
|
||||
for (int i = 0; i < theCoordinats.length; i++) {
|
||||
Vector3f myDistance = new Vector3f();
|
||||
VectorFieldUnit myOtherUnit = _myField[ (int) theCoordinats[i].x][ (int) theCoordinats[i].y][ (int) theCoordinats[i].z];
|
||||
myDistance.set(myOtherUnit.getPosition());
|
||||
myDistance.sub(myUnit.getPosition());
|
||||
float myRatio = myMaxDistance - myDistance.length();
|
||||
Vector3f myTempAcceleration = new Vector3f();
|
||||
myTempAcceleration.set(theAccelerations[i]);
|
||||
myTempAcceleration.scale(myRatio);
|
||||
myAcceleration.add(myTempAcceleration);
|
||||
}
|
||||
myAcceleration.scale(1f / myMaxDistance);
|
||||
myUnit.setAcceleration(myAcceleration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public VectorFieldUnit[][][] data() {
|
||||
return _myField;
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force.vectorfield;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
|
||||
public class VectorFieldGeneratorRANDOM
|
||||
implements VectorFieldGenerator {
|
||||
|
||||
private VectorFieldUnit[][][] _myField;
|
||||
|
||||
public VectorFieldGeneratorRANDOM(int theSizeX,
|
||||
int theSizeY,
|
||||
int theSizeZ) {
|
||||
_myField = new VectorFieldUnit[theSizeX][theSizeY][theSizeZ];
|
||||
for (int x = 0; x < theSizeX; x++) {
|
||||
for (int y = 0; y < theSizeY; y++) {
|
||||
for (int z = 0; z < theSizeZ; z++) {
|
||||
Vector3f myPosition = new Vector3f(x
|
||||
* (1f / (float) theSizeX),
|
||||
y * (1f / (float) theSizeY),
|
||||
z * (1f / (float) theSizeZ));
|
||||
Vector3f myScale = new Vector3f(1f
|
||||
/ (float) theSizeX,
|
||||
1f / (float) theSizeY,
|
||||
1f / (float) theSizeZ);
|
||||
Vector3f myAcceleration = new Vector3f((float) Math.
|
||||
random() - 0.5f,
|
||||
(float) Math.random() - 0.5f,
|
||||
(float) Math.random() - 0.5f);
|
||||
myAcceleration.normalize();
|
||||
VectorFieldUnit myUnit = new VectorFieldUnit(myPosition,
|
||||
myScale,
|
||||
myAcceleration);
|
||||
_myField[x][y][z] = myUnit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public VectorFieldUnit[][][] data() {
|
||||
return _myField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.force.vectorfield;
|
||||
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
|
||||
public class VectorFieldUnit {
|
||||
|
||||
private Vector3f _myPosition;
|
||||
|
||||
private Vector3f _myScale;
|
||||
|
||||
private Vector3f _myAcceleration;
|
||||
|
||||
public VectorFieldUnit(final Vector3f thePosition,
|
||||
final Vector3f theScale,
|
||||
final Vector3f theAcceleration) {
|
||||
_myPosition = new Vector3f(thePosition);
|
||||
_myScale = new Vector3f(theScale);
|
||||
_myAcceleration = new Vector3f(theAcceleration);
|
||||
}
|
||||
|
||||
public void setAcceleration(final Vector3f theAcceleration) {
|
||||
_myAcceleration.set(theAcceleration);
|
||||
}
|
||||
|
||||
public Vector3f getAcceleration() {
|
||||
return _myAcceleration;
|
||||
}
|
||||
|
||||
public Vector3f getPosition() {
|
||||
return _myPosition;
|
||||
}
|
||||
|
||||
public void setPosition(final Vector3f thePosition) {
|
||||
_myPosition.set(thePosition);
|
||||
}
|
||||
|
||||
public Vector3f getScale() {
|
||||
return _myScale;
|
||||
}
|
||||
|
||||
public void setScale(final Vector3f theScale) {
|
||||
_myScale.set(theScale);
|
||||
}
|
||||
|
||||
public boolean isInside(final Vector3f thePosition) {
|
||||
if (thePosition.x >= _myPosition.x
|
||||
&& thePosition.x < _myPosition.x + _myScale.x
|
||||
&& thePosition.y >= _myPosition.y
|
||||
&& thePosition.y < _myPosition.y + _myScale.y
|
||||
&& thePosition.z >= _myPosition.z
|
||||
&& thePosition.z < _myPosition.z + _myScale.z) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.integration;
|
||||
|
||||
|
||||
public final class Derivate3f {
|
||||
|
||||
public float px;
|
||||
|
||||
public float py;
|
||||
|
||||
public float pz;
|
||||
|
||||
public float vx;
|
||||
|
||||
public float vy;
|
||||
|
||||
public float vz;
|
||||
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.integration;
|
||||
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class Euler
|
||||
implements IIntegrator {
|
||||
|
||||
private final Vector3f mTemp1;
|
||||
|
||||
private final Vector3f mTemp2;
|
||||
|
||||
public Euler() {
|
||||
mTemp1 = new Vector3f();
|
||||
mTemp2 = new Vector3f();
|
||||
}
|
||||
|
||||
public void step(final float theDeltaTime, final Physics theParticleSystem) {
|
||||
|
||||
theParticleSystem.applyForces(theDeltaTime);
|
||||
|
||||
synchronized (theParticleSystem.particles()) {
|
||||
final Iterator<Particle> myIterator = theParticleSystem.particles().iterator();
|
||||
while (myIterator.hasNext()) {
|
||||
final Particle myParticle = myIterator.next();
|
||||
if (!myParticle.fixed()) {
|
||||
integrate(theDeltaTime, myParticle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void integrate(final float theDeltaTime, final Particle theParticle) {
|
||||
mTemp1.set(theParticle.force());
|
||||
mTemp1.scale(theDeltaTime / theParticle.mass());
|
||||
|
||||
mTemp2.set(theParticle.velocity());
|
||||
mTemp2.scale(theDeltaTime);
|
||||
|
||||
theParticle.velocity().add(mTemp1);
|
||||
theParticle.position().add(mTemp2);
|
||||
}
|
||||
}
|
||||
|
||||
/* this version scales better with the other integrators but is definitly slower */
|
||||
//import java.util.Vector;
|
||||
//
|
||||
//import particles.IParticle;
|
||||
//import particles.ParticleSystem;
|
||||
//
|
||||
//
|
||||
//public class Euler
|
||||
// implements IIntegrator {
|
||||
//
|
||||
// private final Vector<Derivate3f> myK1 = new Vector<Derivate3f> ();
|
||||
//
|
||||
// public void step(final float theDeltaTime, final ParticleSystem theParticleSystem) {
|
||||
//
|
||||
// Util.checkContainerSize(theParticleSystem.particles().size(), myK1, Derivate3f.class);
|
||||
//
|
||||
// theParticleSystem.applyForces(theDeltaTime);
|
||||
// Util.calculateDerivatives(theParticleSystem.particles(), myK1);
|
||||
// for (int i = 0; i < theParticleSystem.particles().size(); i++) {
|
||||
// Particle myParticle = theParticleSystem.particles().get(i);
|
||||
// if (!myParticle.fixed()) {
|
||||
// myParticle.position().x += myK1.get(i).px * theDeltaTime;
|
||||
// myParticle.position().y += myK1.get(i).py * theDeltaTime;
|
||||
// myParticle.position().z += myK1.get(i).pz * theDeltaTime;
|
||||
// myParticle.velocity().x += myK1.get(i).vx * theDeltaTime;
|
||||
// myParticle.velocity().y += myK1.get(i).vy * theDeltaTime;
|
||||
// myParticle.velocity().z += myK1.get(i).vz * theDeltaTime;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.integration;
|
||||
|
||||
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public interface IIntegrator {
|
||||
|
||||
void step(final float theDeltaTime, final Physics theParticleSystem);
|
||||
}
|
||||
/**
|
||||
* from paul bourke http://astronomy.swin.edu.au/~pbourke/modelling/solver/
|
||||
*/
|
||||
|
||||
/*
|
||||
// A 1st order 1D DE solver.
|
||||
// Assumes the function is not time dependent.
|
||||
// Parameters
|
||||
// h - step size
|
||||
// y0 - last value
|
||||
// method - algorithm to use [0,5]
|
||||
// fcn - evaluate the derivative of the field
|
||||
|
||||
double Solver1D(double h, double y0, int method, double ( * fcn) (double)) {
|
||||
double ynew;
|
||||
double k1, k2, k3, k4, k5, k6;
|
||||
|
||||
switch (method) {
|
||||
case 0: // Euler method
|
||||
k1 = h * ( * fcn) (y0);
|
||||
ynew = y0 + k1;
|
||||
break;
|
||||
case 1: // Modified Euler
|
||||
k1 = h * ( * fcn) (y0);
|
||||
k2 = h * ( * fcn) (y0 + k1);
|
||||
ynew = y0 + (k1 + k2) / 2;
|
||||
break;
|
||||
case 2: // Heuns method
|
||||
k1 = h * ( * fcn) (y0);
|
||||
k2 = h * ( * fcn) (y0 + 2 * k1 / 3);
|
||||
ynew = y0 + k1 / 4 + 3 * k2 / 4;
|
||||
break;
|
||||
case 3: // Midpoint
|
||||
k1 = h * ( * fcn) (y0);
|
||||
k2 = h * ( * fcn) (y0 + k1 / 2);
|
||||
ynew = y0 + k2;
|
||||
break;
|
||||
case 4: // 4'th order Runge-kutta
|
||||
k1 = h * ( * fcn) (y0);
|
||||
k2 = h * ( * fcn) (y0 + k1 / 2);
|
||||
k3 = h * ( * fcn) (y0 + k2 / 2);
|
||||
k4 = h * ( * fcn) (y0 + k3);
|
||||
ynew = y0 + k1 / 6 + k2 / 3 + k3 / 3 + k4 / 6;
|
||||
break;
|
||||
case 5: // England 4'th order, six stage
|
||||
k1 = h * ( * fcn) (y0);
|
||||
k2 = h * ( * fcn) (y0 + k1 / 2);
|
||||
k3 = h * ( * fcn) (y0 + (k1 + k2) / 4);
|
||||
k4 = h * ( * fcn) (y0 - k2 + 2 * k3);
|
||||
k5 = h * ( * fcn) (y0 + (7 * k1 + 10 * k2 + k4) / 27);
|
||||
k6 = h * ( * fcn) (y0 + (28 * k1 - 125 * k2 + 546 * k3 + 54 * k4 - 378 * k5) / 625);
|
||||
ynew = y0 + k1 / 6 + 4 * k3 / 6 + k4 / 6;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ynew);
|
||||
}
|
||||
*/
|
||||
|
||||
/* example C program */
|
||||
|
||||
/*
|
||||
int main(int argc, char * * argv) {
|
||||
double t;
|
||||
double dt = 0.1; // Step size
|
||||
double T = 100; // Simulation duration
|
||||
double y = 1; // Initial value
|
||||
|
||||
for (t = 0; t < T; t += dt) {
|
||||
printf("%g %g\n", t, y);
|
||||
y = Solver1D(dt, y, MIDPOINT, (double ( * ) (double)) EvalFcn);
|
||||
}
|
||||
}
|
||||
|
||||
// Sample derivative function
|
||||
double EvalFcn(double x) {
|
||||
return ( -0.05 * x);
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.integration;
|
||||
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class Midpoint
|
||||
implements IIntegrator {
|
||||
|
||||
private final Vector<Derivate3f> mK1 = new Vector<Derivate3f>();
|
||||
|
||||
public void step(final float theDeltaTime, final Physics theParticleSystem) {
|
||||
|
||||
Util.checkContainerSize(theParticleSystem.particles().size(), mK1, Derivate3f.class);
|
||||
|
||||
/* one */
|
||||
theParticleSystem.applyForces(theDeltaTime);
|
||||
Util.calculateDerivatives(theParticleSystem.particles(), mK1);
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); i++) {
|
||||
Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
myParticle.position().x += mK1.get(i).px * theDeltaTime / 2;
|
||||
myParticle.position().y += mK1.get(i).py * theDeltaTime / 2;
|
||||
myParticle.position().z += mK1.get(i).pz * theDeltaTime / 2;
|
||||
myParticle.position().x += mK1.get(i).vx * theDeltaTime / 2;
|
||||
myParticle.position().y += mK1.get(i).vy * theDeltaTime / 2;
|
||||
myParticle.position().z += mK1.get(i).vz * theDeltaTime / 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* two */
|
||||
theParticleSystem.applyForces(theDeltaTime);
|
||||
Util.calculateDerivatives(theParticleSystem.particles(), mK1);
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); i++) {
|
||||
Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
myParticle.position().x += mK1.get(i).px * theDeltaTime;
|
||||
myParticle.position().y += mK1.get(i).py * theDeltaTime;
|
||||
myParticle.position().z += mK1.get(i).pz * theDeltaTime;
|
||||
myParticle.velocity().x += mK1.get(i).vx * theDeltaTime;
|
||||
myParticle.velocity().y += mK1.get(i).vy * theDeltaTime;
|
||||
myParticle.velocity().z += mK1.get(i).vz * theDeltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.integration;
|
||||
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class RungeKutta
|
||||
implements IIntegrator {
|
||||
|
||||
private final Vector<Vector3f> mOriginalPositions;
|
||||
|
||||
private final Vector<Vector3f> mOriginalVelocities;
|
||||
|
||||
private final Vector<Vector3f> mK1Forces;
|
||||
|
||||
private final Vector<Vector3f> mK1Velocities;
|
||||
|
||||
private final Vector<Vector3f> mK2Forces;
|
||||
|
||||
private final Vector<Vector3f> mK2Velocities;
|
||||
|
||||
private final Vector<Vector3f> mK3Forces;
|
||||
|
||||
private final Vector<Vector3f> mK3Velocities;
|
||||
|
||||
private final Vector<Vector3f> mK4Forces;
|
||||
|
||||
private final Vector<Vector3f> mK4Velocities;
|
||||
|
||||
public RungeKutta() {
|
||||
mOriginalPositions = new Vector<Vector3f>();
|
||||
mOriginalVelocities = new Vector<Vector3f>();
|
||||
mK1Forces = new Vector<Vector3f>();
|
||||
mK1Velocities = new Vector<Vector3f>();
|
||||
mK2Forces = new Vector<Vector3f>();
|
||||
mK2Velocities = new Vector<Vector3f>();
|
||||
mK3Forces = new Vector<Vector3f>();
|
||||
mK3Velocities = new Vector<Vector3f>();
|
||||
mK4Forces = new Vector<Vector3f>();
|
||||
mK4Velocities = new Vector<Vector3f>();
|
||||
}
|
||||
|
||||
public void step(final float theDeltaTime,
|
||||
final Physics theParticleSystem) {
|
||||
|
||||
final int mySize = theParticleSystem.particles().size();
|
||||
Util.checkContainerSize(mySize, mOriginalPositions, Vector3f.class);
|
||||
Util.checkContainerSize(mySize, mOriginalVelocities, Vector3f.class);
|
||||
Util.checkContainerSize(mySize, mK1Forces, Vector3f.class);
|
||||
Util.checkContainerSize(mySize, mK1Velocities, Vector3f.class);
|
||||
Util.checkContainerSize(mySize, mK2Forces, Vector3f.class);
|
||||
Util.checkContainerSize(mySize, mK2Velocities, Vector3f.class);
|
||||
Util.checkContainerSize(mySize, mK3Forces, Vector3f.class);
|
||||
Util.checkContainerSize(mySize, mK3Velocities, Vector3f.class);
|
||||
Util.checkContainerSize(mySize, mK4Forces, Vector3f.class);
|
||||
Util.checkContainerSize(mySize, mK4Velocities, Vector3f.class);
|
||||
|
||||
/* save original position and velocities */
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); ++i) {
|
||||
final Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
mOriginalPositions.get(i).set(myParticle.position());
|
||||
mOriginalVelocities.get(i).set(myParticle.velocity());
|
||||
}
|
||||
}
|
||||
|
||||
/* get all the k1 values */
|
||||
theParticleSystem.applyForces(theDeltaTime);
|
||||
|
||||
/* save the intermediate forces */
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); ++i) {
|
||||
final Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
mK1Forces.get(i).set(myParticle.force());
|
||||
mK1Velocities.get(i).set(myParticle.velocity());
|
||||
}
|
||||
}
|
||||
|
||||
/* get k2 values */
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); ++i) {
|
||||
final Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
final Vector3f originalPosition = mOriginalPositions.get(i);
|
||||
final Vector3f k1Velocity = mK1Velocities.get(i);
|
||||
|
||||
myParticle.position().x = originalPosition.x + k1Velocity.x * 0.5f * theDeltaTime;
|
||||
myParticle.position().y = originalPosition.y + k1Velocity.y * 0.5f * theDeltaTime;
|
||||
myParticle.position().z = originalPosition.z + k1Velocity.z * 0.5f * theDeltaTime;
|
||||
|
||||
final Vector3f originalVelocity = mOriginalVelocities.get(i);
|
||||
final Vector3f k1Force = mK1Forces.get(i);
|
||||
|
||||
myParticle.velocity().x = originalVelocity.x + k1Force.x * 0.5f * theDeltaTime / myParticle.mass();
|
||||
myParticle.velocity().y = originalVelocity.y + k1Force.y * 0.5f * theDeltaTime / myParticle.mass();
|
||||
myParticle.velocity().z = originalVelocity.z + k1Force.z * 0.5f * theDeltaTime / myParticle.mass();
|
||||
}
|
||||
}
|
||||
|
||||
theParticleSystem.applyForces(theDeltaTime);
|
||||
|
||||
/* save the intermediate forces */
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); ++i) {
|
||||
final Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
mK2Forces.get(i).set(myParticle.force());
|
||||
mK2Velocities.get(i).set(myParticle.velocity());
|
||||
}
|
||||
}
|
||||
|
||||
/* get k3 values */
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); ++i) {
|
||||
final Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
final Vector3f originalPosition = mOriginalPositions.get(i);
|
||||
final Vector3f k2Velocity = mK2Velocities.get(i);
|
||||
|
||||
myParticle.position().x = originalPosition.x + k2Velocity.x * 0.5f * theDeltaTime;
|
||||
myParticle.position().y = originalPosition.y + k2Velocity.y * 0.5f * theDeltaTime;
|
||||
myParticle.position().z = originalPosition.z + k2Velocity.z * 0.5f * theDeltaTime;
|
||||
|
||||
final Vector3f originalVelocity = mOriginalVelocities.get(i);
|
||||
final Vector3f k2Force = mK2Forces.get(i);
|
||||
|
||||
myParticle.velocity().x = originalVelocity.x + k2Force.x * 0.5f * theDeltaTime / myParticle.mass();
|
||||
myParticle.velocity().y = originalVelocity.y + k2Force.y * 0.5f * theDeltaTime / myParticle.mass();
|
||||
myParticle.velocity().z = originalVelocity.z + k2Force.z * 0.5f * theDeltaTime / myParticle.mass();
|
||||
}
|
||||
}
|
||||
|
||||
theParticleSystem.applyForces(theDeltaTime);
|
||||
|
||||
/* save the intermediate forces */
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); ++i) {
|
||||
final Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
(mK3Forces.get(i)).set(myParticle.force());
|
||||
(mK3Velocities.get(i)).set(myParticle.velocity());
|
||||
}
|
||||
}
|
||||
|
||||
/* get k4 values */
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); ++i) {
|
||||
final Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
final Vector3f originalPosition = mOriginalPositions.get(i);
|
||||
final Vector3f k3Velocity = mK3Velocities.get(i);
|
||||
|
||||
myParticle.position().x = originalPosition.x + k3Velocity.x * theDeltaTime;
|
||||
myParticle.position().y = originalPosition.y + k3Velocity.y * theDeltaTime;
|
||||
myParticle.position().z = originalPosition.z + k3Velocity.z * theDeltaTime;
|
||||
|
||||
final Vector3f originalVelocity = mOriginalVelocities.get(i);
|
||||
final Vector3f k3Force = mK3Forces.get(i);
|
||||
|
||||
myParticle.velocity().x = originalVelocity.x + k3Force.x * theDeltaTime / myParticle.mass();
|
||||
myParticle.velocity().y = originalVelocity.y + k3Force.y * theDeltaTime / myParticle.mass();
|
||||
myParticle.velocity().z = originalVelocity.z + k3Force.z * theDeltaTime / myParticle.mass();
|
||||
}
|
||||
}
|
||||
|
||||
theParticleSystem.applyForces(theDeltaTime);
|
||||
|
||||
/* save the intermediate forces */
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); ++i) {
|
||||
final Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
mK4Forces.get(i).set(myParticle.force());
|
||||
mK4Velocities.get(i).set(myParticle.velocity());
|
||||
}
|
||||
}
|
||||
|
||||
/* put them all together and what do you get? */
|
||||
for (int i = 0; i < theParticleSystem.particles().size(); ++i) {
|
||||
final Particle myParticle = theParticleSystem.particles().get(i);
|
||||
if (!myParticle.fixed()) {
|
||||
/* update position */
|
||||
final Vector3f originalPosition = mOriginalPositions.get(i);
|
||||
final Vector3f k1Velocity = mK1Velocities.get(i);
|
||||
final Vector3f k2Velocity = mK2Velocities.get(i);
|
||||
final Vector3f k3Velocity = mK3Velocities.get(i);
|
||||
final Vector3f k4Velocity = mK4Velocities.get(i);
|
||||
|
||||
myParticle.position().x = originalPosition.x
|
||||
+ theDeltaTime / 6.0f
|
||||
* (k1Velocity.x + 2.0f * k2Velocity.x + 2.0f * k3Velocity.x + k4Velocity.x);
|
||||
myParticle.position().y = originalPosition.y
|
||||
+ theDeltaTime / 6.0f
|
||||
* (k1Velocity.y + 2.0f * k2Velocity.y + 2.0f * k3Velocity.y + k4Velocity.y);
|
||||
myParticle.position().z = originalPosition.z
|
||||
+ theDeltaTime / 6.0f
|
||||
* (k1Velocity.z + 2.0f * k2Velocity.z + 2.0f * k3Velocity.z + k4Velocity.z);
|
||||
|
||||
/* update velocity */
|
||||
final Vector3f originalVelocity = mOriginalVelocities.get(i);
|
||||
final Vector3f k1Force = mK1Forces.get(i);
|
||||
final Vector3f k2Force = mK2Forces.get(i);
|
||||
final Vector3f k3Force = mK3Forces.get(i);
|
||||
final Vector3f k4Force = mK4Forces.get(i);
|
||||
|
||||
myParticle.velocity().x = originalVelocity.x
|
||||
+ theDeltaTime / (6.0f * myParticle.mass())
|
||||
* (k1Force.x + 2.0f * k2Force.x + 2.0f * k3Force.x + k4Force.x);
|
||||
myParticle.velocity().y = originalVelocity.y
|
||||
+ theDeltaTime / (6.0f * myParticle.mass())
|
||||
* (k1Force.y + 2.0f * k2Force.y + 2.0f * k3Force.y + k4Force.y);
|
||||
myParticle.velocity().z = originalVelocity.z
|
||||
+ theDeltaTime / (6.0f * myParticle.mass())
|
||||
* (k1Force.z + 2.0f * k2Force.z + 2.0f * k3Force.z + k4Force.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.integration;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import teilchen.Particle;
|
||||
|
||||
|
||||
public final class Util {
|
||||
|
||||
public static final <T> void checkContainerSize(final int theSize,
|
||||
final List<T> theContainer,
|
||||
Class<T> theClass) {
|
||||
final int myDiff = theSize - theContainer.size();
|
||||
if (myDiff > 0) {
|
||||
for (int i = 0; i < myDiff; i++) {
|
||||
try {
|
||||
theContainer.add(theClass.newInstance());
|
||||
} catch (Exception ex) {
|
||||
System.err.println(ex);
|
||||
}
|
||||
}
|
||||
} else if (myDiff < 0) {
|
||||
for (int i = 0; i < myDiff; i++) {
|
||||
theContainer.remove(myDiff + theSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final void calculateDerivatives(final List<Particle> theParticles,
|
||||
final List<Derivate3f> theDerivates) {
|
||||
for (int i = 0; i < theParticles.size(); i++) {
|
||||
theDerivates.get(i).px = theParticles.get(i).velocity().x;
|
||||
theDerivates.get(i).py = theParticles.get(i).velocity().y;
|
||||
theDerivates.get(i).pz = theParticles.get(i).velocity().z;
|
||||
theDerivates.get(i).vx = theParticles.get(i).force().x / theParticles.get(i).mass();
|
||||
theDerivates.get(i).vy = theParticles.get(i).force().y / theParticles.get(i).mass();
|
||||
theDerivates.get(i).vz = theParticles.get(i).force().z / theParticles.get(i).mass();
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.integration;
|
||||
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
|
||||
|
||||
public class Verlet
|
||||
implements IIntegrator {
|
||||
|
||||
private final Vector3f temp1;
|
||||
|
||||
private final Vector3f temp2;
|
||||
|
||||
private float _myDamping;
|
||||
|
||||
public Verlet() {
|
||||
this(1.0f);
|
||||
}
|
||||
|
||||
public Verlet(final float theDamping) {
|
||||
_myDamping = theDamping;
|
||||
temp1 = new Vector3f();
|
||||
temp2 = new Vector3f();
|
||||
}
|
||||
|
||||
public float damping() {
|
||||
return _myDamping;
|
||||
}
|
||||
|
||||
public void damping(float theDamping) {
|
||||
_myDamping = theDamping;
|
||||
}
|
||||
|
||||
public void step(final float theDeltaTime, final Physics theParticleSystem) {
|
||||
|
||||
theParticleSystem.applyForces(theDeltaTime);
|
||||
|
||||
synchronized (theParticleSystem.particles()) {
|
||||
final Iterator<Particle> myIterator = theParticleSystem.particles().iterator();
|
||||
while (myIterator.hasNext()) {
|
||||
final Particle myParticle = myIterator.next();
|
||||
if (!myParticle.fixed()) {
|
||||
integrate(theDeltaTime, myParticle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final void integrate(float theDeltaTime, Particle theParticle) {
|
||||
final Vector3f myOldPosition = new Vector3f(theParticle.position());
|
||||
|
||||
/*
|
||||
Physics simulation using Verlet integration
|
||||
sgreen@nvidia.com 6/2002
|
||||
|
||||
based on Thomas Jakobsen's "Advanced Character Physics":
|
||||
http://www.ioi.dk/Homepages/tj/publications/gdc2001.htm
|
||||
|
||||
basic idea:
|
||||
x' = x + v*dt
|
||||
v' = v + a*dt
|
||||
|
||||
x' = x + (v + a*dt) * dt
|
||||
= x + v*dt + a*dt^2
|
||||
|
||||
v ~= (x - ox) / dt
|
||||
|
||||
x' = x + (x - ox) + a*dt^2
|
||||
*/
|
||||
|
||||
/* v ~= (x - ox) / dt */
|
||||
theParticle.velocity().sub(theParticle.position(), theParticle.old_position());
|
||||
theParticle.velocity().scale(1.0f / theDeltaTime);
|
||||
|
||||
/* x' = x + (x - ox) + a*dt^2 */
|
||||
temp1.set(theParticle.force());
|
||||
temp1.scale(1.0f / theParticle.mass());
|
||||
temp1.scale(theDeltaTime * theDeltaTime);
|
||||
temp2.sub(theParticle.position(), theParticle.old_position());
|
||||
|
||||
temp2.scale(_myDamping);
|
||||
|
||||
theParticle.position().add(temp1);
|
||||
theParticle.position().add(temp2);
|
||||
|
||||
/* --- */
|
||||
theParticle.old_position().set(myOldPosition);
|
||||
}
|
||||
}
|
||||
+425
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.util;
|
||||
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import mathematik.Random;
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import teilchen.Particle;
|
||||
import teilchen.Physics;
|
||||
import teilchen.constraint.Stick;
|
||||
import teilchen.cubicle.CubicleParticle;
|
||||
import teilchen.cubicle.CubicleWorld;
|
||||
import teilchen.cubicle.ICubicleEntity;
|
||||
import teilchen.force.IForce;
|
||||
import teilchen.force.Spring;
|
||||
|
||||
|
||||
/**
|
||||
* this manager uses it s own particle system. we could make it more integrated
|
||||
* by using a shared physic world. this would of course make everthing more
|
||||
* slower.
|
||||
*/
|
||||
public class CollisionManager {
|
||||
|
||||
public boolean HINT_IGNORE_STILL_OR_FIXED = false;
|
||||
|
||||
private float mCollisionSpringConstant;
|
||||
|
||||
private float mCollisionSpringDamping;
|
||||
|
||||
private final Physics mCollisionPhysics;
|
||||
|
||||
private float mMinimumDistance;
|
||||
|
||||
private Vector3f mResolveSamePosition;
|
||||
|
||||
public enum ResolverType {
|
||||
// COLLISION_STICK, COLLISION_SPRING,
|
||||
|
||||
SPRING, STICK
|
||||
|
||||
}
|
||||
private final Random mRandom;
|
||||
|
||||
private ResolverType mResolverType;
|
||||
|
||||
private float mCollisionResolverIntervalCounter = 1;
|
||||
|
||||
private float mCollisionResolverInterval = 0;
|
||||
|
||||
private int mDistanceMode = DISTANCE_MODE_FIXED;
|
||||
|
||||
public static final int DISTANCE_MODE_RADIUS = 0;
|
||||
|
||||
public static final int DISTANCE_MODE_FIXED = 1;
|
||||
|
||||
public CollisionManager() {
|
||||
this(new Physics());
|
||||
}
|
||||
|
||||
public CollisionManager(final Physics thePhysics) {
|
||||
mCollisionPhysics = thePhysics;
|
||||
mResolveSamePosition = new Vector3f(1, 1, 1);
|
||||
mCollisionSpringConstant = 20.0f;
|
||||
mCollisionSpringDamping = 1.0f;
|
||||
mMinimumDistance = 20;
|
||||
mResolverType = ResolverType.SPRING;
|
||||
mRandom = new Random();
|
||||
}
|
||||
|
||||
public void distancemode(int theDistanceMode) {
|
||||
mDistanceMode = theDistanceMode;
|
||||
}
|
||||
|
||||
public void setResolverType(ResolverType theResolverType) {
|
||||
mResolverType = theResolverType;
|
||||
}
|
||||
|
||||
public Vector3f resolveSamePosition() {
|
||||
return mResolveSamePosition;
|
||||
}
|
||||
|
||||
public void springDamping(float theSpringDamping) {
|
||||
mCollisionSpringDamping = theSpringDamping;
|
||||
}
|
||||
|
||||
public float springDamping() {
|
||||
return mCollisionSpringDamping;
|
||||
}
|
||||
|
||||
public void springConstant(float theSpringConstant) {
|
||||
mCollisionSpringConstant = theSpringConstant;
|
||||
}
|
||||
|
||||
public float springConstant() {
|
||||
return mCollisionSpringConstant;
|
||||
}
|
||||
|
||||
public void minimumDistance(float theMinimumDistance) {
|
||||
mMinimumDistance = theMinimumDistance;
|
||||
}
|
||||
|
||||
public float minimumDistance() {
|
||||
return mMinimumDistance;
|
||||
}
|
||||
|
||||
public Physics collision() {
|
||||
return mCollisionPhysics;
|
||||
}
|
||||
|
||||
public Vector<IForce> collision_forces() {
|
||||
return mCollisionPhysics.forces();
|
||||
}
|
||||
|
||||
public void loop(float theDeltaTime) {
|
||||
|
||||
// /* collision resolver */
|
||||
// if (mCollisionResolverIntervalCounter > mCollisionResolverInterval) {
|
||||
// mCollisionResolverIntervalCounter = 0;
|
||||
//// createCollisionResolvers();
|
||||
// } else {
|
||||
// mCollisionResolverIntervalCounter += theDeltaTime;
|
||||
// }
|
||||
|
||||
/* physics */
|
||||
mCollisionPhysics.step(theDeltaTime);
|
||||
|
||||
// /* remove collision resolver */
|
||||
// removeCollisionResolver();
|
||||
}
|
||||
|
||||
public void autoloop(float theDeltaTime) {
|
||||
/* collision resolver */
|
||||
if (mCollisionResolverIntervalCounter > mCollisionResolverInterval) {
|
||||
mCollisionResolverIntervalCounter = 0;
|
||||
// mCollisionResolverIntervalCounter -= mCollisionResolverInterval;
|
||||
// mCollisionResolverIntervalCounter %= mCollisionResolverInterval;
|
||||
createCollisionResolvers();
|
||||
} else {
|
||||
mCollisionResolverIntervalCounter += theDeltaTime;
|
||||
}
|
||||
|
||||
/* physics */
|
||||
mCollisionPhysics.step(theDeltaTime);
|
||||
|
||||
/* remove collision resolver */
|
||||
removeCollisionResolver();
|
||||
}
|
||||
|
||||
public void removeCollisionResolver() {
|
||||
mCollisionPhysics.forces().clear();
|
||||
mCollisionPhysics.constraints().clear();
|
||||
}
|
||||
|
||||
public void createCollisionResolvers() {
|
||||
for (int i = 0; i < mCollisionPhysics.particles().size(); i++) {
|
||||
createCollisionResolver(mCollisionPhysics.particles().get(i), i);
|
||||
}
|
||||
}
|
||||
|
||||
private void createCollisionResolver(final Particle theParticle, final int theStart) {
|
||||
if (HINT_IGNORE_STILL_OR_FIXED) {
|
||||
if (theParticle.fixed() || theParticle.still()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (int j = theStart; j < mCollisionPhysics.particles().size(); j++) {
|
||||
Particle myOtherParticle = mCollisionPhysics.particles().get(j);
|
||||
if (theParticle != myOtherParticle) { // && !myOtherParticle.fixed()) {
|
||||
final float myDistance = theParticle.position().distance(myOtherParticle.position());
|
||||
final float myMinimumDistance = getMinimumDistance(theParticle, myOtherParticle);
|
||||
if (myDistance < myMinimumDistance) {
|
||||
if (theParticle.fixed() && myOtherParticle.fixed()) {
|
||||
// continue;
|
||||
}
|
||||
/**
|
||||
* because of the way we handle the collision resolver
|
||||
* creation there is no need to check for multiple spring
|
||||
* connections.
|
||||
* checkSpringConnectionExistence(mCollisionPhysics.getForces(),
|
||||
* myParticle, myOtherParticle);
|
||||
*/
|
||||
if (mResolverType == ResolverType.SPRING) {
|
||||
Spring mySpring = new Spring(theParticle,
|
||||
myOtherParticle,
|
||||
mCollisionSpringConstant,
|
||||
mCollisionSpringDamping,
|
||||
myMinimumDistance);
|
||||
mCollisionPhysics.add(mySpring);
|
||||
} else if (mResolverType == ResolverType.STICK) {
|
||||
Stick mySpring = new Stick(theParticle,
|
||||
myOtherParticle,
|
||||
myMinimumDistance);
|
||||
mCollisionPhysics.add(mySpring);
|
||||
}
|
||||
|
||||
/* hack to prevent particles from being in the same place */
|
||||
if (myDistance < mathematik.Mathematik.EPSILON && myDistance > -mathematik.Mathematik.EPSILON) {
|
||||
myOtherParticle.position().x += mRandom.getFloat(mResolveSamePosition.x * -0.5f,
|
||||
mResolveSamePosition.x * 0.5f);
|
||||
myOtherParticle.position().y += mRandom.getFloat(mResolveSamePosition.y * -0.5f,
|
||||
mResolveSamePosition.y * 0.5f);
|
||||
myOtherParticle.position().z += mRandom.getFloat(mResolveSamePosition.z * -0.5f,
|
||||
mResolveSamePosition.z * 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void createCollisionResolvers(final CubicleWorld theWorld) {
|
||||
for (int i = 0; i < mCollisionPhysics.particles().size(); i++) {
|
||||
final Particle myParticle = mCollisionPhysics.particles().get(i);
|
||||
if (myParticle instanceof CubicleParticle) {
|
||||
createCollisionResolver(theWorld, (CubicleParticle) myParticle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createCollisionResolver(final CubicleWorld theWorld, final CubicleParticle theParticle) {
|
||||
if (HINT_IGNORE_STILL_OR_FIXED) {
|
||||
if (theParticle.fixed() || theParticle.still()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final Vector<ICubicleEntity> myNeigbors = theWorld.getLocalEntities(theParticle);
|
||||
if (myNeigbors.size() > 1) {
|
||||
for (int j = 0; j < myNeigbors.size(); j++) {
|
||||
final ICubicleEntity myEntity = myNeigbors.get(j);
|
||||
if (myEntity instanceof Particle) {
|
||||
final Particle myOtherParticle = (Particle) myEntity;
|
||||
if (theParticle != myOtherParticle) {
|
||||
final float myDistance = theParticle.position().distance(myOtherParticle.position());
|
||||
final float myMinimumDistance = getMinimumDistance(theParticle, myOtherParticle);
|
||||
if (myDistance < myMinimumDistance) {
|
||||
if (theParticle.fixed() && myOtherParticle.fixed()) {
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* because of the way we handle the collision
|
||||
* resolver creation there is no need to check for
|
||||
* multiple spring connections.
|
||||
* checkSpringConnectionExistence(mCollisionPhysics.getForces(),
|
||||
* myParticle, myOtherParticle);
|
||||
*/
|
||||
if (mResolverType == ResolverType.SPRING) {
|
||||
Spring mySpring = new Spring(theParticle,
|
||||
myOtherParticle,
|
||||
mCollisionSpringConstant,
|
||||
mCollisionSpringDamping,
|
||||
myMinimumDistance);
|
||||
mCollisionPhysics.add(mySpring);
|
||||
} else if (mResolverType == ResolverType.STICK) {
|
||||
Stick mySpring = new Stick(theParticle,
|
||||
myOtherParticle,
|
||||
myMinimumDistance);
|
||||
mCollisionPhysics.add(mySpring);
|
||||
}
|
||||
|
||||
/* hack to prevent particles from being in the same place */
|
||||
if (myDistance < mathematik.Mathematik.EPSILON
|
||||
&& myDistance > -mathematik.Mathematik.EPSILON) {
|
||||
myOtherParticle.position().x += mRandom.getFloat(mResolveSamePosition.x * -0.5f,
|
||||
mResolveSamePosition.x * 0.5f);
|
||||
myOtherParticle.position().y += mRandom.getFloat(mResolveSamePosition.y * -0.5f,
|
||||
mResolveSamePosition.y * 0.5f);
|
||||
myOtherParticle.position().z += mRandom.getFloat(mResolveSamePosition.z * -0.5f,
|
||||
mResolveSamePosition.z * 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float getMinimumDistance(Particle theParticle, Particle myOtherParticle) {
|
||||
final float myMinimumDistance;
|
||||
|
||||
if (mDistanceMode == DISTANCE_MODE_RADIUS) {
|
||||
myMinimumDistance = theParticle.radius() + myOtherParticle.radius();
|
||||
} else {
|
||||
myMinimumDistance = mMinimumDistance;
|
||||
}
|
||||
return myMinimumDistance;
|
||||
}
|
||||
|
||||
public static class CollisionSpring
|
||||
extends Spring {
|
||||
|
||||
public CollisionSpring(Particle theA, Particle theB) {
|
||||
super(theA,
|
||||
theB,
|
||||
2.0f, 0.1f,
|
||||
theA.position().distance(theB.position()));
|
||||
}
|
||||
|
||||
public CollisionSpring(Particle theA,
|
||||
Particle theB,
|
||||
final float theSpringConstant,
|
||||
final float theSpringDamping) {
|
||||
super(theA,
|
||||
theB,
|
||||
theSpringConstant,
|
||||
theSpringDamping,
|
||||
theA.position().distance(theB.position()));
|
||||
}
|
||||
|
||||
public CollisionSpring(final Particle theA,
|
||||
final Particle theB,
|
||||
final float theSpringConstant,
|
||||
final float theSpringDamping,
|
||||
final float theRestLength) {
|
||||
super(theA,
|
||||
theB,
|
||||
theSpringConstant,
|
||||
theSpringDamping,
|
||||
theRestLength);
|
||||
}
|
||||
|
||||
public void apply(final float theDeltaTime, final Physics theParticleSystem) {
|
||||
if (!mA.fixed() || !mB.fixed()) {
|
||||
float a2bX = mA.position().x - mB.position().x;
|
||||
float a2bY = mA.position().y - mB.position().y;
|
||||
float a2bZ = mA.position().z - mB.position().z;
|
||||
final float myInversDistance = fastInverseSqrt(a2bX * a2bX + a2bY * a2bY + a2bZ * a2bZ);
|
||||
final float myDistance = 1.0F / myInversDistance;
|
||||
|
||||
if (myDistance < mRestLength) {
|
||||
if (myDistance == 0.0F) {
|
||||
a2bX = 0.0F;
|
||||
a2bY = 0.0F;
|
||||
a2bZ = 0.0F;
|
||||
} else {
|
||||
a2bX *= myInversDistance;
|
||||
a2bY *= myInversDistance;
|
||||
a2bZ *= myInversDistance;
|
||||
}
|
||||
|
||||
final float mSpringForce = -(myDistance - mRestLength) * mSpringConstant;
|
||||
final float Va2bX = mA.velocity().x - mB.velocity().x;
|
||||
final float Va2bY = mA.velocity().y - mB.velocity().y;
|
||||
final float Va2bZ = mA.velocity().z - mB.velocity().z;
|
||||
final float mDampingForce = -mSpringDamping * (a2bX * Va2bX + a2bY * Va2bY + a2bZ * Va2bZ);
|
||||
final float r = mSpringForce + mDampingForce;
|
||||
a2bX *= r;
|
||||
a2bY *= r;
|
||||
a2bZ *= r;
|
||||
if (!mA.fixed()) {
|
||||
mA.force().add(a2bX, a2bY, a2bZ);
|
||||
}
|
||||
|
||||
if (!mB.fixed()) {
|
||||
mB.force().add(-a2bX, -a2bY, -a2bZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CollisionStick
|
||||
extends Stick {
|
||||
|
||||
public CollisionStick(Particle theA, Particle theB) {
|
||||
super(theA, theB);
|
||||
}
|
||||
|
||||
public CollisionStick(final Particle theA,
|
||||
final Particle theB,
|
||||
final float theRestLength) {
|
||||
super(theA, theB, theRestLength);
|
||||
}
|
||||
|
||||
public void apply(Physics theParticleSystem) {
|
||||
if (!mA.fixed() || !mB.fixed()) {
|
||||
mTempDistanceVector.sub(mA.position(), mB.position());
|
||||
final float myDistanceSquared = mTempDistanceVector.lengthSquared();
|
||||
if (myDistanceSquared > 0) {
|
||||
if (myDistanceSquared < mRestLength * mRestLength) {
|
||||
final float myDistance = (float) Math.sqrt(myDistanceSquared);
|
||||
final float myDifference = mRestLength - myDistance;
|
||||
if (myDifference > EPSILON || myDifference < -EPSILON) {
|
||||
if (!mOneWay) {
|
||||
final float myDifferenceScale = 0.5f * myDifference / myDistance;
|
||||
mTempVector.scale(myDifferenceScale, mTempDistanceVector);
|
||||
mA.position().add(mTempVector);
|
||||
mB.position().sub(mTempVector);
|
||||
} else {
|
||||
final float myDifferenceScale = myDifference / myDistance;
|
||||
mTempVector.scale(myDifferenceScale, mTempDistanceVector);
|
||||
mB.position().sub(mTempVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mB.position().set(mA.position());
|
||||
mB.position().x += mRestLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Teilchen
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* {@link http://www.gnu.org/licenses/lgpl.html}
|
||||
*
|
||||
*/
|
||||
package teilchen.util;
|
||||
|
||||
|
||||
import mathematik.TransformMatrix4f;
|
||||
import mathematik.Vector3f;
|
||||
|
||||
import processing.core.PGraphics;
|
||||
import teilchen.cubicle.CubicleAtom;
|
||||
import teilchen.cubicle.CubicleWorld;
|
||||
|
||||
|
||||
public class CubicleWorldView {
|
||||
|
||||
private final CubicleWorld mCubicleWorld;
|
||||
|
||||
public int color_full = -1;
|
||||
|
||||
public int color_empty = -8421505;
|
||||
|
||||
public CubicleWorldView(CubicleWorld theWorld) {
|
||||
mCubicleWorld = theWorld;
|
||||
}
|
||||
|
||||
public void draw(PGraphics theParent) {
|
||||
|
||||
/* collect data */
|
||||
final CubicleAtom[][][] myData = mCubicleWorld.getDataRef();
|
||||
final TransformMatrix4f myTransform = mCubicleWorld.transform();
|
||||
final Vector3f myScale = mCubicleWorld.cellscale();
|
||||
|
||||
/* draw world */
|
||||
theParent.pushMatrix();
|
||||
|
||||
/* rotation */
|
||||
float[] f = myTransform.toArray();
|
||||
theParent.translate(f[12], f[13], f[14]);
|
||||
theParent.applyMatrix(f[0], f[1], f[2], f[3],
|
||||
f[4], f[5], f[6], f[7],
|
||||
f[8], f[9], f[10], f[11],
|
||||
0, 0, 0, f[15]);
|
||||
|
||||
/* scale */
|
||||
theParent.scale(myScale.x, myScale.y, myScale.z);
|
||||
for (int x = 0; x < myData.length; x++) {
|
||||
for (int y = 0; y < myData[x].length; y++) {
|
||||
for (int z = 0; z < myData[x][y].length; z++) {
|
||||
CubicleAtom myCubicle = myData[x][y][z];
|
||||
theParent.pushMatrix();
|
||||
theParent.translate(x, y, z);
|
||||
theParent.translate(mCubicleWorld.cellscale().x / 2 / myScale.x,
|
||||
mCubicleWorld.cellscale().y / 2 / myScale.y,
|
||||
mCubicleWorld.cellscale().z / 2 / myScale.z);
|
||||
if (myCubicle.size() > 0) {
|
||||
theParent.stroke(color_full);
|
||||
} else {
|
||||
theParent.stroke(color_empty);
|
||||
}
|
||||
theParent.box(1);
|
||||
theParent.popMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
theParent.popMatrix();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user