public override float ReportFixture(b2Fixture fixture, b2Vec2 point, b2Vec2 normal, float fraction) { if ((fixture.GetFilterData().categoryBits & _CollisionMask) == 0) { return(-1f); } ICollider collider = _Physics2DControl.GetPhysicsObject(fixture.GetBody().GetUserData().data).GetCollider(fixture.GetUserData().data); return(_Callback.Invoke(collider, point.ToVector2(), normal.ToVector2(), fraction)); }
public override bool ReportFixture(b2Fixture fixture) { if ((fixture.GetFilterData().categoryBits & _CollisionMask) == 0) { return(true); } ICollider collider = _Physics2DControl.GetPhysicsObject(fixture.GetBody().GetUserData().data).GetCollider(fixture.GetUserData().data); return(_Callback.Invoke(collider)); }
/** @private */ virtual public void Reset(b2Fixture fixtureA = null, b2Fixture fixtureB = null) { m_flags = e_enabledFlag; if (fixtureA == null || fixtureB == null) { m_fixtureA = null; m_fixtureB = null; return; } if (fixtureA.IsSensor() || fixtureB.IsSensor()) { m_flags |= e_sensorFlag; } b2Body bodyA = fixtureA.GetBody(); b2Body bodyB = fixtureB.GetBody(); if (bodyA.GetType() != b2Body.b2_dynamicBody || bodyA.IsBullet() || bodyB.GetType() != b2Body.b2_dynamicBody || bodyB.IsBullet()) { m_flags |= e_continuousFlag; } m_fixtureA = fixtureA; m_fixtureB = fixtureB; m_manifold.m_pointCount = 0; m_prev = null; m_next = null; m_nodeA.contact = null; m_nodeA.prev = null; m_nodeA.next = null; m_nodeA.other = null; m_nodeB.contact = null; m_nodeB.prev = null; m_nodeB.next = null; m_nodeB.other = null; }
internal static void Destroy(ref b2Contact contact) { Debug.Assert(s_initialized == true); b2Fixture fixtureA = contact.m_fixtureA; b2Fixture fixtureB = contact.m_fixtureB; if (contact.m_manifold.pointCount > 0 && fixtureA.IsSensor() == false && fixtureB.IsSensor() == false) { fixtureA.GetBody().SetAwake(true); fixtureB.GetBody().SetAwake(true); } b2Shape.Type typeA = fixtureA.GetType(); b2Shape.Type typeB = fixtureB.GetType(); Debug.Assert(0 <= ((int)typeA) && typeB < b2Shape.Type.e_typeCount); Debug.Assert(0 <= ((int)typeA) && typeB < b2Shape.Type.e_typeCount); b2ContactDestroyFcn destroyFcn = s_registers[(int)typeA, (int)typeB].destroyFcn; destroyFcn(ref contact); }
public override byte[] Render(bool toRgbArray = false) { if (Viewer == null) { Viewer = new Rendering.Viewer(VIEWPORT_W, VIEWPORT_H); } Viewer.SetBounds(scroll, VIEWPORT_W / SCALE + scroll, 0, VIEWPORT_H / SCALE); Viewer.DrawPolygon(new List <float[]> { new float[] { scroll, 0 }, new float[] { scroll + VIEWPORT_W / SCALE, 0 }, new float[] { scroll + VIEWPORT_W / SCALE, VIEWPORT_H / SCALE }, new float[] { scroll, VIEWPORT_H / SCALE } }).SetColor(0.9f, 0.9f, 1.0f); foreach (var cloud_data in cloud_poly) { var poly = cloud_data.Item1; var pos_data = cloud_data.Item2; if (pos_data.y < scroll / 2) { continue; } if (pos_data.x > scroll / 2 + VIEWPORT_W / SCALE) { continue; } Viewer.DrawPolygon(poly.Select(p => new[] { p[0] + scroll / 2, p[1] }).ToList()).SetColor(1, 1, 1); } foreach (var terrain_data in terrain_poly) { var poly = terrain_data.Item1; var color = terrain_data.Item2; if (poly[1][0] < scroll) { continue; } if (poly[0][0] > scroll + VIEWPORT_W / SCALE) { continue; } Viewer.DrawPolygon(poly).SetColor(color.x, color.y, color.z); } lidar_render = (lidar_render + 1) % 100; int i = lidar_render; if (i < 2 * lidar.Length) { var l = i < lidar.Length ? lidar[i] : lidar[2 * lidar.Length - i - 1]; Viewer.DrawPolyline(new List <float[]> { new float[] { l.P1.x, l.P1.y }, new float[] { l.P2.x, l.P2.y } }).SetColor(1, 0, 0).SetLineWidth(1); } foreach (var obj in drawlist) { for (b2Fixture f = obj.GetFixtureList(); f != null; f = f.GetNext()) { var xform = f.GetBody().GetTransform(); if (f.GetShape() is b2CircleShape) { var shape = (f.GetShape() as b2CircleShape); var customData = (obj.GetUserData() as CustomBodyData); var trans = Utils.b2Mul(xform, shape.m_p); var t = new Rendering.Transform(new float[] { trans[0], trans[1] }); Viewer.DrawCircle(shape.m_radius, 30).SetColor(customData.Color1.x, customData.Color1.y, customData.Color1.z).AddAttr(t); Viewer.DrawCircle(shape.m_radius, 30, false).SetColor(customData.Color2.x, customData.Color2.y, customData.Color2.z).SetLineWidth(2).AddAttr(t); } else { var shape = f.GetShape(); var customData = (obj.GetUserData() as CustomBodyData); var path = shape.GetVertices().Select(v => { var trans = Utils.b2Mul(xform, v); return(new float[] { trans[0], trans[1] }); }).ToList(); Viewer.DrawPolygon(path).SetColor(customData.Color1.x, customData.Color1.y, customData.Color1.z); path.Add(path[0]); Viewer.DrawPolyline(path).SetColor(customData.Color2.x, customData.Color2.y, customData.Color2.z).SetLineWidth(2); } } } var flagy1 = TERRAIN_HEIGHT; var flagy2 = flagy1 + 50 / SCALE; var x = TERRAIN_STEP * 3; Viewer.DrawPolyline(new List <float[]> { new float[] { x, flagy1 }, new float[] { x, flagy2 } }).SetColor(0, 0, 0).SetLineWidth(2); var flagVert = new List <float[]> { new float[] { x, flagy2 }, new float[] { x, flagy2 - 10 / SCALE }, new float[] { x + 25 / SCALE, flagy2 - 5 / SCALE } }; Viewer.DrawPolygon(flagVert).SetColor(0.9f, 0.2f, 0); flagVert.Add(flagVert[0]); Viewer.DrawPolyline(flagVert).SetColor(0, 0, 0).SetLineWidth(2); Viewer.Render(); return(null); }
public override byte[] Render(bool toRgbArray = false) { if (Viewer == null) { Viewer = new Rendering.Viewer(VIEWPORT_W, VIEWPORT_H); Viewer.SetBounds(0, VIEWPORT_W / SCALE, 0, VIEWPORT_H / SCALE); } foreach (var obj in particles) { var data = obj.GetUserData() as CustomBodyData; data.TimeToLive -= 0.15f; data.Color1 = new b2Vec3((float)Math.Max(0.2, 0.2 + data.TimeToLive), (float)Math.Max(0.2, 0.5 * data.TimeToLive), (float)Math.Max(0.2, 0.5 * data.TimeToLive)); data.Color2 = new b2Vec3((float)Math.Max(0.2, 0.2 + data.TimeToLive), (float)Math.Max(0.2, 0.5 * data.TimeToLive), (float)Math.Max(0.2, 0.5 * data.TimeToLive)); } CleanParticles(false); foreach (var p in sky_polys) { Viewer.DrawPolygon(p).SetColor(0, 0, 0); } foreach (var obj in particles.Concat(drawlist)) { for (b2Fixture f = obj.GetFixtureList(); f != null; f = f.GetNext()) { var xform = f.GetBody().GetTransform(); if (f.GetShape() is b2CircleShape) { var shape = (f.GetShape() as b2CircleShape); var customData = (obj.GetUserData() as CustomBodyData); var trans = Utils.b2Mul(xform, shape.m_p); var t = new Rendering.Transform(new float[] { trans[0], trans[1] }); Viewer.DrawCircle(shape.m_radius, 20).SetColor(customData.Color1.x, customData.Color1.y, customData.Color1.z).AddAttr(t); Viewer.DrawCircle(shape.m_radius, 20, false).SetColor(customData.Color2.x, customData.Color2.y, customData.Color2.z).SetLineWidth(2).AddAttr(t); } else { var shape = f.GetShape(); var customData = (obj.GetUserData() as CustomBodyData); var path = shape.GetVertices().Select(v => { var trans = Utils.b2Mul(xform, v); return(new float[] { trans[0], trans[1] }); }).ToList(); Viewer.DrawPolygon(path).SetColor(customData.Color1.x, customData.Color1.y, customData.Color1.z); path.Add(path[0]); Viewer.DrawPolyline(path).SetColor(customData.Color2.x, customData.Color2.y, customData.Color2.z).SetLineWidth(2); } } } foreach (var x in new[] { helipad_x1, helipad_x2 }) { var flagy1 = helipad_y; var flagy2 = flagy1 + 50 / SCALE; Viewer.DrawPolyline(new List <float[]> { new float[] { x, flagy1 }, new float[] { x, flagy2 } }).SetColor(1, 1, 1); Viewer.DrawPolygon(new List <float[]> { new float[] { x, flagy2 }, new float[] { x, flagy2 - 10 / SCALE }, new float[] { x + 25 / SCALE, flagy2 - 5 / SCALE } }).SetColor(0.8f, 0.8f, 0); } Viewer.Render(); return(null); }
public b2ContactSolver(b2ContactSolverDef def) { m_step = def.step; m_count = def.count; m_positionConstraints = Arrays.InitializeWithDefaultInstances <b2ContactPositionConstraint>(m_count); m_velocityConstraints = Arrays.InitializeWithDefaultInstances <b2ContactVelocityConstraint>(m_count); m_positions = def.positions; m_velocities = def.velocities; m_contacts = def.contacts; // Initialize position independent portions of the constraints. for (int i = 0; i < m_count; ++i) { b2Contact contact = m_contacts[i]; b2Fixture fixtureA = contact.m_fixtureA; b2Fixture fixtureB = contact.m_fixtureB; b2Shape shapeA = fixtureA.GetShape(); b2Shape shapeB = fixtureB.GetShape(); float radiusA = shapeA.m_radius; float radiusB = shapeB.m_radius; b2Body bodyA = fixtureA.GetBody(); b2Body bodyB = fixtureB.GetBody(); b2Manifold manifold = contact.GetManifold(); int pointCount = manifold.pointCount; Debug.Assert(pointCount > 0); b2ContactVelocityConstraint vc = m_velocityConstraints[i]; vc.friction = contact.m_friction; vc.restitution = contact.m_restitution; vc.tangentSpeed = contact.m_tangentSpeed; vc.indexA = bodyA.m_islandIndex; vc.indexB = bodyB.m_islandIndex; vc.invMassA = bodyA.m_invMass; vc.invMassB = bodyB.m_invMass; vc.invIA = bodyA.m_invI; vc.invIB = bodyB.m_invI; vc.contactIndex = i; vc.pointCount = pointCount; vc.K.SetZero(); vc.normalMass.SetZero(); b2ContactPositionConstraint pc = m_positionConstraints[i]; pc.indexA = bodyA.m_islandIndex; pc.indexB = bodyB.m_islandIndex; pc.invMassA = bodyA.m_invMass; pc.invMassB = bodyB.m_invMass; pc.localCenterA = bodyA.m_sweep.localCenter; pc.localCenterB = bodyB.m_sweep.localCenter; pc.invIA = bodyA.m_invI; pc.invIB = bodyB.m_invI; pc.localNormal = manifold.localNormal; pc.localPoint = manifold.localPoint; pc.pointCount = pointCount; pc.radiusA = radiusA; pc.radiusB = radiusB; pc.type = manifold.type; for (int j = 0; j < pointCount; ++j) { b2ManifoldPoint cp = manifold.points[j]; b2VelocityConstraintPoint vcp = vc.points[j]; if (m_step.warmStarting) { vcp.normalImpulse = m_step.dtRatio * cp.normalImpulse; vcp.tangentImpulse = m_step.dtRatio * cp.tangentImpulse; } else { vcp.normalImpulse = 0.0f; vcp.tangentImpulse = 0.0f; } vcp.rA.SetZero(); vcp.rB.SetZero(); vcp.normalMass = 0.0f; vcp.tangentMass = 0.0f; vcp.velocityBias = 0.0f; pc.localPoints[j] = cp.localPoint; } } }
// Broad-phase callback. public void AddPair(object proxyUserDataA, object proxyUserDataB) { b2FixtureProxy proxyA = (b2FixtureProxy)proxyUserDataA; b2FixtureProxy proxyB = (b2FixtureProxy)proxyUserDataB; b2Fixture fixtureA = proxyA.fixture; b2Fixture fixtureB = proxyB.fixture; int indexA = proxyA.childIndex; int indexB = proxyB.childIndex; b2Body bodyA = fixtureA.GetBody(); b2Body bodyB = fixtureB.GetBody(); // Are the fixtures on the same body? if (bodyA == bodyB) { return; } // TODO_ERIN use a hash table to remove a potential bottleneck when both // bodies have a lot of contacts. // Does a contact already exist? b2ContactEdge edge = bodyB.GetContactList(); while (edge != null) { if (edge.other == bodyA) { b2Fixture fA = edge.contact.GetFixtureA(); b2Fixture fB = edge.contact.GetFixtureB(); int iA = edge.contact.GetChildIndexA(); int iB = edge.contact.GetChildIndexB(); if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB) { // A contact already exists. return; } if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA) { // A contact already exists. return; } } edge = edge.next; } // Does a joint override collision? Is at least one body dynamic? if (bodyB.ShouldCollide(bodyA) == false) { return; } // Check user filtering. if (m_contactFilter != null && m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { return; } // Call the factory. b2Contact c = b2Contact.Create(fixtureA, indexA, fixtureB, indexB); if (c == null) { return; } // Contact creation may swap fixtures. fixtureA = c.GetFixtureA(); fixtureB = c.GetFixtureB(); indexA = c.GetChildIndexA(); indexB = c.GetChildIndexB(); bodyA = fixtureA.GetBody(); bodyB = fixtureB.GetBody(); // Insert into the world. c.m_prev = null; c.m_next = m_contactList; if (m_contactList != null) { m_contactList.m_prev = c; } m_contactList = c; // Connect to island graph. // Connect to body A c.m_nodeA.contact = c; c.m_nodeA.other = bodyB; c.m_nodeA.prev = null; c.m_nodeA.next = bodyA.m_contactList; if (bodyA.m_contactList != null) { bodyA.m_contactList.prev = c.m_nodeA; } bodyA.m_contactList = c.m_nodeA; // Connect to body B c.m_nodeB.contact = c; c.m_nodeB.other = bodyA; c.m_nodeB.prev = null; c.m_nodeB.next = bodyB.m_contactList; if (bodyB.m_contactList != null) { bodyB.m_contactList.prev = c.m_nodeB; } bodyB.m_contactList = c.m_nodeB; // Wake up the bodies if (fixtureA.IsSensor() == false && fixtureB.IsSensor() == false) { bodyA.SetAwake(true); bodyB.SetAwake(true); } ++m_contactCount; }
// This is the top level collision call for the time step. Here // all the narrow phase collision is processed for the world // contact list. public void Collide() { // Update awake contacts. b2Contact c = m_contactList; while (c != null) { b2Fixture fixtureA = c.GetFixtureA(); b2Fixture fixtureB = c.GetFixtureB(); int indexA = c.GetChildIndexA(); int indexB = c.GetChildIndexB(); b2Body bodyA = fixtureA.GetBody(); b2Body bodyB = fixtureB.GetBody(); // Is this contact flagged for filtering? if ((c.m_flags & b2Contact.ContactFlags.e_filterFlag) != 0) { // Should these bodies collide? if (bodyB.ShouldCollide(bodyA) == false) { b2Contact cNuke = c; c = cNuke.GetNext(); Destroy(cNuke); continue; } // Check user filtering. if (m_contactFilter != null && m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { b2Contact cNuke = c; c = cNuke.GetNext(); Destroy(cNuke); continue; } // Clear the filtering flag. c.m_flags &= ~b2Contact.ContactFlags.e_filterFlag; } bool activeA = bodyA.IsAwake() && bodyA.m_type != BodyType.b2_staticBody; bool activeB = bodyB.IsAwake() && bodyB.m_type != BodyType.b2_staticBody; // At least one body must be awake and it must be dynamic or kinematic. if (activeA == false && activeB == false) { c = c.GetNext(); continue; } int proxyIdA = fixtureA.m_proxies[indexA].proxyId; int proxyIdB = fixtureB.m_proxies[indexB].proxyId; bool overlap = m_broadPhase.TestOverlap(proxyIdA, proxyIdB); // Here we destroy contacts that cease to overlap in the broad-phase. if (overlap == false) { b2Contact cNuke = c; c = cNuke.GetNext(); Destroy(cNuke); continue; } // The contact persists. c.Update(m_contactListener); c = c.GetNext(); } }
public void Destroy(b2Contact c) { b2Fixture fixtureA = c.GetFixtureA(); b2Fixture fixtureB = c.GetFixtureB(); b2Body bodyA = fixtureA.GetBody(); b2Body bodyB = fixtureB.GetBody(); if (m_contactListener != null && c.IsTouching()) { m_contactListener.EndContact(c); } // Remove from the world. if (c.m_prev != null) { c.m_prev.m_next = c.m_next; } if (c.m_next != null) { c.m_next.m_prev = c.m_prev; } if (c == m_contactList) { m_contactList = c.m_next; } // Remove from body 1 if (c.m_nodeA.prev != null) { c.m_nodeA.prev.next = c.m_nodeA.next; } if (c.m_nodeA.next != null) { c.m_nodeA.next.prev = c.m_nodeA.prev; } if (c.m_nodeA == bodyA.m_contactList) { bodyA.m_contactList = c.m_nodeA.next; } // Remove from body 2 if (c.m_nodeB.prev != null) { c.m_nodeB.prev.next = c.m_nodeB.next; } if (c.m_nodeB.next != null) { c.m_nodeB.next.prev = c.m_nodeB.prev; } if (c.m_nodeB == bodyB.m_contactList) { bodyB.m_contactList = c.m_nodeB.next; } // Call the factory. b2Contact.Destroy(ref c); --m_contactCount; }