Skip to content

Commit 299365f

Browse files
Added physics object and some basic constraints
1 parent ca62073 commit 299365f

File tree

6 files changed

+362
-0
lines changed

6 files changed

+362
-0
lines changed

src/polyray/physics/Particle.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package polyray.physics;
2+
3+
import polyray.Vector3d;
4+
5+
public class Particle extends PhysicsObject {
6+
7+
public final double mass;
8+
private final double invMass;
9+
10+
public Particle(double mass, float friction, float restitution) {
11+
super(friction, restitution);
12+
this.mass = mass;
13+
this.invMass = 1.0d / mass;
14+
}
15+
16+
public Particle(double mass, Vector3d pos, float friction, float restitution) {
17+
super(pos, friction, restitution);
18+
this.mass = mass;
19+
this.invMass = 1.0d / mass;
20+
}
21+
22+
public void applyForce(Vector3d f) {
23+
this.acc.x += f.x * invMass;
24+
this.acc.y += f.y * invMass;
25+
this.acc.z += f.z * invMass;
26+
}
27+
28+
public void applyForce(double fx, double fy, double fz) {
29+
this.acc.x += fx * invMass;
30+
this.acc.y += fy * invMass;
31+
this.acc.z += fz * invMass;
32+
}
33+
34+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package polyray.physics;
2+
3+
import polyray.Vector3d;
4+
5+
public class ParticleLine {
6+
7+
public final Particle a, b;
8+
public final double length;
9+
private final double stiffness;
10+
private final double ratioA, ratioB;
11+
12+
public ParticleLine(Particle a, Particle b, double length, double stiffness) {
13+
this.a = a;
14+
this.b = b;
15+
this.length = length;
16+
this.stiffness = stiffness * 0.5d;
17+
double massSum = a.mass + b.mass;
18+
this.ratioA = a.mass / massSum;
19+
this.ratioB = b.mass / massSum;
20+
}
21+
22+
public void applyRotationalForce(Vector3d axis, double force) {
23+
Vector3d midpoint = new Vector3d(
24+
a.pos.x * ratioA + b.pos.x * ratioB,
25+
a.pos.y * ratioA + b.pos.y * ratioB,
26+
a.pos.z * ratioA + b.pos.z * ratioB
27+
);
28+
29+
// This does not account for particle mass but is enough for now
30+
Vector3d ra = new Vector3d(a.pos.x - midpoint.x, a.pos.y - midpoint.y, a.pos.z - midpoint.z);
31+
Vector3d rb = new Vector3d(b.pos.x - midpoint.x, b.pos.y - midpoint.y, b.pos.z - midpoint.z);
32+
33+
Vector3d torqueA = Vector3d.mul(Vector3d.cross(ra, axis), force);
34+
Vector3d torqueB = Vector3d.mul(Vector3d.cross(rb, axis), force);
35+
36+
a.applyForce(torqueA);
37+
b.applyForce(torqueB);
38+
}
39+
40+
public void update() {
41+
double dx = b.pos.x - a.pos.x;
42+
double dy = b.pos.y - a.pos.y;
43+
double dz = b.pos.z - a.pos.z;
44+
double dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
45+
double diff = (dist - length) * stiffness;
46+
double mul = diff / dist;
47+
dx *= mul;
48+
dy *= mul;
49+
dz *= mul;
50+
double sum = a.mass + b.mass;
51+
double ratio1 = a.mass / sum;
52+
double ratio2 = b.mass / sum;
53+
a.pos.x += dx * ratio1;
54+
a.pos.y += dy * ratio1;
55+
a.pos.z += dz * ratio1;
56+
b.pos.x -= dx * ratio2;
57+
b.pos.y -= dy * ratio2;
58+
b.pos.z -= dz * ratio2;
59+
}
60+
61+
public static final ParticleLine[] connectAllLines(Particle p, Particle[] particles, double stiffness) {
62+
ParticleLine[] lines = new ParticleLine[particles.length];
63+
for (int i = 0; i < particles.length; i++) {
64+
lines[i] = new ParticleLine(p, particles[i], Vector3d.length(Vector3d.sub(p.pos, particles[i].pos)), stiffness);
65+
}
66+
return lines;
67+
}
68+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package polyray.physics;
2+
3+
import polyray.Vector3d;
4+
5+
public class ParticleLineN {
6+
7+
private final Particle[] particles;
8+
private final Vector3d[] pointVectors;
9+
private final double invAmt;
10+
private final double[] segmentLengths;
11+
public final Vector3d lineOrigin = new Vector3d();
12+
public final Vector3d lineVector = new Vector3d();
13+
14+
public ParticleLineN(double[] segmentLengths, Particle[] particles) {
15+
this.segmentLengths = segmentLengths;
16+
this.particles = particles;
17+
this.pointVectors = new Vector3d[particles.length];
18+
this.invAmt = 1.0d / particles.length;
19+
}
20+
21+
public void update() {
22+
lineOrigin.x = 0.0d;
23+
lineOrigin.y = 0.0d;
24+
lineOrigin.z = 0.0d;
25+
for (Particle p : particles) {
26+
lineOrigin.x += p.pos.x;
27+
lineOrigin.y += p.pos.y;
28+
lineOrigin.z += p.pos.z;
29+
}
30+
lineOrigin.x *= invAmt;
31+
lineOrigin.y *= invAmt;
32+
lineOrigin.z *= invAmt;
33+
34+
lineVector.x = 0.0d;
35+
lineVector.y = 0.0d;
36+
lineVector.z = 0.0d;
37+
int i = 0;
38+
for (Particle p : particles) {
39+
Vector3d dir = Vector3d.sub(lineOrigin, p.pos);
40+
pointVectors[i++] = dir;
41+
if (Vector3d.dot(lineVector, dir) < 0.0d) {
42+
lineVector.x -= dir.x;
43+
lineVector.y -= dir.y;
44+
lineVector.z -= dir.z;
45+
} else {
46+
lineVector.x += dir.x;
47+
lineVector.y += dir.y;
48+
lineVector.z += dir.z;
49+
}
50+
}
51+
double mul = 1.0d / Vector3d.length(lineVector);
52+
lineVector.x *= mul;
53+
lineVector.y *= mul;
54+
lineVector.z *= mul;
55+
56+
i = 0;
57+
for (Particle p : particles) {
58+
Vector3d pointVector = pointVectors[i++];
59+
Vector3d lineNormalBitangent = Vector3d.cross(lineVector, pointVector);
60+
Vector3d lineNormal = Vector3d.normalize(Vector3d.cross(lineVector, lineNormalBitangent));
61+
double dist = Vector3d.dot(pointVector, lineNormal);
62+
if (Math.abs(dist) < 0.0001d) {
63+
continue;
64+
}
65+
Vector3d correction = Vector3d.mul(lineNormal, dist);
66+
p.pos.x += correction.x;
67+
p.pos.y += correction.y;
68+
p.pos.z += correction.z;
69+
}
70+
for (int j = 0; j < 10; j++) {
71+
Particle a = particles[0];
72+
for (i = 1; i < particles.length; i++) {
73+
Particle b = particles[i];
74+
applyLine(lineVector, a, b, (Vector3d.dot(Vector3d.sub(b.pos, a.pos), lineVector) - segmentLengths[i - 1]) * 0.5d);
75+
a = b;
76+
}
77+
}
78+
}
79+
80+
private void applyLine(Vector3d dir, Particle a, Particle b, double diff) {
81+
double sum = a.mass + b.mass;
82+
double ratio1 = a.mass / sum;
83+
double ratio2 = b.mass / sum;
84+
Vector3d ca = Vector3d.mul(dir, diff * ratio1);
85+
Vector3d cb = Vector3d.mul(dir, -diff * ratio2);
86+
a.pos.x += ca.x;
87+
a.pos.y += ca.y;
88+
a.pos.z += ca.z;
89+
b.pos.x += cb.x;
90+
b.pos.y += cb.y;
91+
b.pos.z += cb.z;
92+
}
93+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package polyray.physics;
2+
3+
import polyray.Vector3d;
4+
5+
public class ParticlePlane {
6+
7+
private final Particle[] particles;
8+
private final Vector3d[] pointVectors;
9+
private final double invAmt;
10+
public final Vector3d planeOrigin = new Vector3d();
11+
public final Vector3d planeNormal = new Vector3d();
12+
13+
public ParticlePlane(Particle[] particles) {
14+
this.particles = particles;
15+
this.pointVectors = new Vector3d[particles.length];
16+
this.invAmt = 1.0d / particles.length;
17+
}
18+
19+
public void update() {
20+
planeOrigin.x = 0.0d;
21+
planeOrigin.y = 0.0d;
22+
planeOrigin.z = 0.0d;
23+
for (Particle p : particles) {
24+
planeOrigin.x += p.pos.x;
25+
planeOrigin.y += p.pos.y;
26+
planeOrigin.z += p.pos.z;
27+
}
28+
planeOrigin.x *= invAmt;
29+
planeOrigin.y *= invAmt;
30+
planeOrigin.z *= invAmt;
31+
32+
int i = 0;
33+
planeNormal.x = 0.0d;
34+
planeNormal.y = 0.0d;
35+
planeNormal.z = 0.0d;
36+
Vector3d prevPointVector = Vector3d.sub(particles[particles.length - 1].pos, planeOrigin);
37+
for (Particle p : particles) {
38+
Vector3d pointVector = Vector3d.sub(p.pos, planeOrigin);
39+
pointVectors[i++] = pointVector;
40+
Vector3d normal = Vector3d.cross(pointVector, prevPointVector);
41+
double weight = Vector3d.length(normal);
42+
if (Vector3d.dot(normal, planeNormal) < 0.0d) {
43+
planeNormal.x -= normal.x * weight;
44+
planeNormal.y -= normal.y * weight;
45+
planeNormal.z -= normal.z * weight;
46+
} else {
47+
planeNormal.x += normal.x * weight;
48+
planeNormal.y += normal.y * weight;
49+
planeNormal.z += normal.z * weight;
50+
}
51+
prevPointVector = pointVector;
52+
}
53+
double mul = 1.0d / Vector3d.length(planeNormal);
54+
planeNormal.x *= mul;
55+
planeNormal.y *= mul;
56+
planeNormal.z *= mul;
57+
58+
i = 0;
59+
for (Particle p : particles) {
60+
double height = Vector3d.dot(pointVectors[i++], planeNormal);
61+
Vector3d correction = Vector3d.mul(planeNormal, -height);
62+
p.pos.x += correction.x;
63+
p.pos.y += correction.y;
64+
p.pos.z += correction.z;
65+
}
66+
}
67+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package polyray.physics;
2+
3+
import polyray.Vector3d;
4+
5+
public class ParticleSphere {
6+
7+
private final Particle[] particles;
8+
private final double invAmt;
9+
private final double radius;
10+
public final Vector3d sphereOrigin = new Vector3d();
11+
12+
public ParticleSphere(double radius, Particle... particles) {
13+
this.radius = radius;
14+
this.particles = particles;
15+
this.invAmt = 1.0d / particles.length;
16+
}
17+
18+
public void update() {
19+
sphereOrigin.x = 0.0d;
20+
sphereOrigin.y = 0.0d;
21+
sphereOrigin.z = 0.0d;
22+
for (Particle p : particles) {
23+
sphereOrigin.x += p.pos.x;
24+
sphereOrigin.y += p.pos.y;
25+
sphereOrigin.z += p.pos.z;
26+
}
27+
sphereOrigin.x *= invAmt;
28+
sphereOrigin.y *= invAmt;
29+
sphereOrigin.z *= invAmt;
30+
31+
for (Particle p : particles) {
32+
Vector3d pointVector = Vector3d.sub(p.pos, sphereOrigin);
33+
double len = Vector3d.length(pointVector);
34+
double mul = (radius - len) / len;
35+
pointVector.x *= mul;
36+
pointVector.y *= mul;
37+
pointVector.z *= mul;
38+
p.pos.x += pointVector.x;
39+
p.pos.y += pointVector.y;
40+
p.pos.z += pointVector.z;
41+
}
42+
}
43+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package polyray.physics;
2+
3+
import polyray.Vector3d;
4+
import polyray.Vector3f;
5+
6+
public class PhysicsObject {
7+
8+
public final Vector3d pos = new Vector3d();
9+
public final Vector3d prevPos = new Vector3d();
10+
public final Vector3d acc = new Vector3d();
11+
public final float friction, restitution;
12+
13+
public PhysicsObject(float friction, float restitution) {
14+
this.friction = friction;
15+
this.restitution = restitution;
16+
}
17+
18+
public PhysicsObject(Vector3d pos, float friction, float restitution) {
19+
this.pos.x = pos.x;
20+
this.pos.y = pos.y;
21+
this.pos.z = pos.z;
22+
this.prevPos.x = pos.x;
23+
this.prevPos.y = pos.y;
24+
this.prevPos.z = pos.z;
25+
this.friction = friction;
26+
this.restitution = restitution;
27+
}
28+
29+
public void accelerate(Vector3d a) {
30+
acc.x += a.x;
31+
acc.y += a.y;
32+
acc.z += a.z;
33+
}
34+
35+
public void update(double dt) {
36+
double tx = pos.x;
37+
double ty = pos.y;
38+
double tz = pos.z;
39+
double ddt = dt * dt;
40+
pos.x += pos.x - prevPos.x + acc.x * ddt;
41+
pos.y += pos.y - prevPos.y + acc.y * ddt;
42+
pos.z += pos.z - prevPos.z + acc.z * ddt;
43+
prevPos.x = tx;
44+
prevPos.y = ty;
45+
prevPos.z = tz;
46+
acc.x = 0.0d;
47+
acc.y = 0.0d;
48+
acc.z = 0.0d;
49+
}
50+
51+
protected Vector3f bounce(Vector3f v, Vector3f n) {
52+
float height = -Vector3f.dot(v, n);
53+
Vector3f normVel = Vector3f.mul(n, height);
54+
Vector3f perp = Vector3f.mul(Vector3f.add(v, normVel), 1.0f - friction);
55+
return Vector3f.add(perp, Vector3f.mul(normVel, restitution));
56+
}
57+
}

0 commit comments

Comments
 (0)