public void StartImpulseObject() { if (started) { return; } verts = Vec2.ArrayOf(activePoints.Length); for (int v = 0; v < activePoints.Length; v++) { verts[v].x = activePoints[v].x; verts[v].y = activePoints[v].y; } body = impulse.Add(new Polygon(verts), transform.position.x, transform.position.y); body.SetOrient(0); body.restitution = 0.2f; body.dynamicFriction = 0.2f; body.staticFriction = 0.4f; shape = ((Polygon)body.shape); started = true; }
public override void HandleCollision(Manifold m, Body a, Body b) { Polygon A = (Polygon)a.shape; Polygon B = (Polygon)b.shape; m.contactCount = 0; // Check for a separating axis with A's face planes int[] faceA = { 0 }; float penetrationA = FindAxisLeastPenetration(faceA, A, B); if (penetrationA >= 0.0f) { return; } // Check for a separating axis with B's face planes int[] faceB = { 0 }; float penetrationB = FindAxisLeastPenetration(faceB, B, A); if (penetrationB >= 0.0f) { return; } int referenceIndex; bool flip; // Always point from a to b Polygon RefPoly; // Reference Polygon IncPoly; // Incident // Determine which shape contains reference face if (ImpulseMath.Gt(penetrationA, penetrationB)) { RefPoly = A; IncPoly = B; referenceIndex = faceA[0]; flip = false; } else { RefPoly = B; IncPoly = A; referenceIndex = faceB[0]; flip = true; } // World space incident face Vec2[] incidentFace = Vec2.ArrayOf(2); FindIncidentFace(incidentFace, RefPoly, IncPoly, referenceIndex); // y // ^ .n ^ // +---c ------posPlane-- // x < | i |\ // +---+ c-----negPlane-- // \ v // r // // r : reference face // i : incident poly // c : clipped point // n : incident normal // Setup reference face vertices Vec2 v1 = RefPoly.vertices[referenceIndex]; referenceIndex = referenceIndex + 1 == RefPoly.vertexCount ? 0 : referenceIndex + 1; Vec2 v2 = RefPoly.vertices[referenceIndex]; // Transform vertices to world space // v1 = RefPoly->u * v1 + RefPoly->body->position; // v2 = RefPoly->u * v2 + RefPoly->body->position; v1 = RefPoly.u.Mul(v1).Addi(RefPoly.body.position); v2 = RefPoly.u.Mul(v2).Addi(RefPoly.body.position); // Calculate reference face side normal in world space // Vec2 sidePlaneNormal = (v2 - v1); // sidePlaneNormal.Normalize( ); Vec2 sidePlaneNormal = v2.Sub(v1); sidePlaneNormal.Normalize(); // Orthogonalize // Vec2 refFaceNormal( sidePlaneNormal.y, -sidePlaneNormal.x ); Vec2 refFaceNormal = new Vec2(sidePlaneNormal.y, -sidePlaneNormal.x); // ax + by = c // c is distance from origin // real refC = Dot( refFaceNormal, v1 ); // real negSide = -Dot( sidePlaneNormal, v1 ); // real posSide = Dot( sidePlaneNormal, v2 ); float refC = Vec2.Dot(refFaceNormal, v1); float negSide = -Vec2.Dot(sidePlaneNormal, v1); float posSide = Vec2.Dot(sidePlaneNormal, v2); // Clip incident face to reference face side planes // if(Clip( -sidePlaneNormal, negSide, incidentFace ) < 2) if (Clip(sidePlaneNormal.Neg(), negSide, incidentFace) < 2) { return; // Due to floating point error, possible to not have required // points } // if(Clip( sidePlaneNormal, posSide, incidentFace ) < 2) if (Clip(sidePlaneNormal, posSide, incidentFace) < 2) { return; // Due to floating point error, possible to not have required // points } // Flip m.normal.Set(refFaceNormal); if (flip) { m.normal.Negi(); } // Keep points behind reference face int cp = 0; // clipped points behind reference face float separation = Vec2.Dot(refFaceNormal, incidentFace[0]) - refC; if (separation <= 0.0f) { m.contacts[cp].Set(incidentFace[0]); m.penetration = -separation; ++cp; } else { m.penetration = 0; } separation = Vec2.Dot(refFaceNormal, incidentFace[1]) - refC; if (separation <= 0.0f) { m.contacts[cp].Set(incidentFace[1]); m.penetration += -separation; ++cp; // Average penetration m.penetration /= cp; } m.contactCount = cp; }
void InputImpulseEngine(CommonMonoBehaviour.GameInput input) { if (!playing) { return; } if (input.keyDown[0]) { playing = false; } if (input.keyDown[1]) { if (input.mouseUp[0] || input.mouseDown[0]) { float hw = ImpulseMath.Random(1.0f, 3.0f); float hh = ImpulseMath.Random(1.0f, 3.0f); Body b = impulse.Add(new Polygon(hw, hh), input.rayPosition.x, input.rayPosition.y); b.SetOrient(0.0f); } if (input.mouseUp[1] || input.mouseDown[1]) { float r = ImpulseMath.Random(1.0f, 5.0f); int vertCount = 3; Vec2[] verts = Vec2.ArrayOf(vertCount); for (int i = 0; i < vertCount; i++) { verts[i].Set(ImpulseMath.Random(-r, r), ImpulseMath.Random(-r, r)); } Body b = impulse.Add(new Polygon(verts), input.rayPosition.x, input.rayPosition.y); b.SetOrient(ImpulseMath.Random(-ImpulseMath.PI, ImpulseMath.PI)); b.restitution = 0.2f; b.dynamicFriction = 0.2f; b.staticFriction = 0.4f; } } else { if (input.mouseUp[0] || input.mouseDown[0]) { float r = ImpulseMath.Random(1.0f, 5.0f); int vertCount = ImpulseMath.Random(3, Polygon.MAX_POLY_VERTEX_COUNT); Vec2[] verts = Vec2.ArrayOf(vertCount); for (int i = 0; i < vertCount; i++) { verts[i].Set(ImpulseMath.Random(-r, r), ImpulseMath.Random(-r, r)); } Body b = impulse.Add(new Polygon(verts), input.rayPosition.x, input.rayPosition.y); b.SetOrient(ImpulseMath.Random(-ImpulseMath.PI, ImpulseMath.PI)); b.restitution = 0.2f; b.dynamicFriction = 0.2f; b.staticFriction = 0.4f; } if (input.mouseUp[1] || input.mouseDown[1]) { float r = ImpulseMath.Random(1.0f, 3.0f); impulse.Add(new Circle(r), input.rayPosition.x, input.rayPosition.y); } //Move your cube GameObject to the point where you clicked if (PointerTransform) { PointerTransform.position = input.rayPosition; } } }