Friction in physics engine help
Ok i know this is sort of a non specific question but i am making a verlet integration physics engine for a game similar to, for example angry birds. I am writing a practice engine just to get the jist of it (credits for simpler c++ version go to Benedikt Bitterli) and no matter what i do i cant figure out how to implement friction. I posted the main collision and caluculation methods below if someone could at least tell me where or in which method i should add something and the name of the techneque or somthing.
private void updateVerlet() {
float tempX;
float tempY;
for (int b = 0; b < bodies.size(); b++) {
for (int i = 0; i < bodies.get(b).vertices.size(); i++) {
Vertex v = bodies.get(b).vertices.get(i);
tempX = v.x;
tempY = v.y;
v.x += v.x - v.ox + v.accx * timestep * timestep;
v.y += v.y - v.oy + v.accy * timestep * timestep;
v.ox = tempX;
v.oy = tempY;
}
}
}
private void updateEdges() {
for (int b = 0; b < bodies.size(); b++) {
for (int i = 0; i < bodies.get(b).edges.size(); i++) {
Edge e = bodies.get(b).edges.get(i);
float distX = e.v2.x - e.v1.x;
float distY = e.v2.y - e.v1.y;
float dist = (float)Math.hypot(distX, distY);
float diff = dist - e.length;
float len = 1f / (float)Math.hypot(distX, distY);// Normalize with (float)Math.hypot(distX, distY); again????
distX *= len;
distY *= len;
e.v1.x += distX * diff * 0.5;
e.v1.y += distY * diff * 0.5;
e.v2.x -= distX * diff * 0.5;
e.v2.y -= distY * diff * 0.5;
}
}
}
private void iterateCollisions() {
for (int iteration = 0; iteration < iterations; iteration++) {
// Temporary solution to prevent bodies from falling out of the screen
for (int b = 0; b < bodies.size(); b++) {
for (int i = 0; i < bodies.get(b).vertices.size(); i++) {
bodies.get(b).vertices.get(i).x = Math.max(Math.min(bodies.get(b).vertices.get(i).x, (float)screenWidth), 0.0f);
bodies.get(b).vertices.get(i).y = Math.max(Math.min(bodies.get(b).vertices.get(i).y, (float)screenHeight), 0.0f);
}
}
updateEdges();
for (int b = 0; b < bodies.size(); b++) {
bodies.get(b).calculateCenter();
}
for (int b1 = 0; b1 < bodies.size(); b1++) {
for (int b2 = 0; b2 < bodies.size(); b2++) {
if (bodies.get(b1) != bodies.get(b2)) {
if (bodiesOverlap(bodies.get(b1), bodies.get(b2))) {
if (detectCollision(bodies.get(b1), bodies.get(b2))) {
processCollision();
}
}
}
}
}
}
}
private boolean bodiesOverlap(PhysicsBody b1, PhysicsBody b2) {
return
(b1.minX <= b2.maxX) &a开发者_JS百科mp;&
(b1.minY <= b2.maxY) &&
(b1.maxX >= b2.minX) &&
(b2.maxY >= b1.minY);
}
private boolean detectCollision(PhysicsBody b1, PhysicsBody b2) {
float minDistance = 10000.0f;
Edge e;
for (int i = 0; i < b1.edges.size() + b2.edges.size(); i++) {
if (i < b1.edges.size()) {
e = b1.edges.get(i);
} else {
e= b2.edges.get(i - b1.edges.size());
}
if (!e.boundary)
continue;
axis.x = e.v1.y - e.v2.y;
axis.y = e.v2.x - e.v1.x;
float len = 1f / (float)Math.hypot(axis.x, axis.y);
axis.x *= len;
axis.y *= len;
MinMax dataA = b1.projectToAxis(axis);
MinMax dataB = b2.projectToAxis(axis);
float distance = intervalDistance(dataA, dataB);
if (distance > 0f)
return false;
else if (Math.abs(distance) < minDistance) {
minDistance = Math.abs(distance);
CollisionInfo.normalX = axis.x;
CollisionInfo.normalY = axis.y;
CollisionInfo.e = e;
}
}
CollisionInfo.depth = minDistance;
if (CollisionInfo.e.parent != b2) {
PhysicsBody temp = b2;
b2 = b1;
b1 = temp;
}
float diffX = b1.centerX - b2.centerX;
float diffY = b1.centerY - b2.centerY;
float mult = CollisionInfo.normalX * diffX + CollisionInfo.normalY * diffY;
if (mult < 0) {
CollisionInfo.normalX = 0 - CollisionInfo.normalX;
CollisionInfo.normalY = 0 - CollisionInfo.normalY;
}
minDistance = 10000.0f;
for (int i = 0; i < b1.vertices.size(); i++) {
diffX = b1.vertices.get(i).x - b2.centerX;
diffY = b1.vertices.get(i).y - b2.centerY;
float distance = CollisionInfo.normalX * diffX + CollisionInfo.normalX * diffY;
if (distance < minDistance) {
minDistance = distance;
CollisionInfo.v = b1.vertices.get(i);
}
}
return true;
}
private void processCollision() {
Vertex v1 = CollisionInfo.e.v1;
Vertex v2 = CollisionInfo.e.v2;
float collisionVectorX = CollisionInfo.normalX * CollisionInfo.depth;
float collisionVectorY = CollisionInfo.normalY * CollisionInfo.depth;
float t;
if (Math.abs(v1.x - v2.x) > Math.abs(v1.y - v2.y)) {
t = (CollisionInfo.v.x - collisionVectorX - v1.x) / (v2.x - v1.x);
}
else {
t = (CollisionInfo.v.y - collisionVectorY - v1.y) / (v2.y - v1.y);
}
float lambda = 1.0f / (t * t + (1 - t) * (1 - t));
float edgeMass = t * v2.parent.mass + (1f - t) * v1.parent.mass;
float invCollisionMass = 1.0f / (edgeMass + CollisionInfo.v.parent.mass);
float ratio1 = CollisionInfo.v.parent.mass * invCollisionMass;
float ratio2 = edgeMass*invCollisionMass;
v1.x -= collisionVectorX * ((1 - t) * ratio1 * lambda);
v1.y -= collisionVectorY * (( 1 - t) * ratio1 * lambda);
v2.x -= collisionVectorX * (t * ratio1 * lambda);
v2.y -= collisionVectorY * (t * ratio1 * lambda);
CollisionInfo.v.x += collisionVectorX * ratio2;
CollisionInfo.v.y += collisionVectorY * ratio2;
}
try this code, friction on the bottom world boundary for every particle, limit horizontal movement.
if(Particle.Y >= world_height) { Particle.OldX = Particle.OldX - (Particle.OldX - Particle.X)/2; }
精彩评论