/** * Cast a ray against this shape. * * @param output the ray-cast results. * @param input the ray-cast input parameters. * @param output * @param input */ public bool raycast(RayCastOutput output, RayCastInput input, int childIndex) { return m_shape.raycast(output, input, m_body.m_xf, childIndex); }
/** * From Real-time Collision Detection, p179. * * @param output * @param input */ public bool raycast(RayCastOutput output, RayCastInput input, IWorldPool argPool) { float tmin = float.MinValue; float tmax = float.MaxValue; Vec2 p = argPool.popVec2(); Vec2 d = argPool.popVec2(); Vec2 absD = argPool.popVec2(); Vec2 normal = argPool.popVec2(); p.set(input.p1); d.set(input.p2); d.subLocal(input.p1); Vec2.absToOut(d, ref absD); // x then y if (absD.x < Settings.EPSILON) { // Parallel. if (p.x < lowerBound.x || upperBound.x < p.x) { argPool.pushVec2(4); return false; } } else { float inv_d = 1.0f/d.x; float t1 = (lowerBound.x - p.x)*inv_d; float t2 = (upperBound.x - p.x)*inv_d; // Sign of the normal vector. float s = -1.0f; if (t1 > t2) { float temp = t1; t1 = t2; t2 = temp; s = 1.0f; } // Push the min up if (t1 > tmin) { normal.setZero(); normal.x = s; tmin = t1; } // Pull the max down tmax = MathUtils.min(tmax, t2); if (tmin > tmax) { argPool.pushVec2(4); return false; } } if (absD.y < Settings.EPSILON) { // Parallel. if (p.y < lowerBound.y || upperBound.y < p.y) { argPool.pushVec2(4); return false; } } else { float inv_d = 1.0f/d.y; float t1 = (lowerBound.y - p.y)*inv_d; float t2 = (upperBound.y - p.y)*inv_d; // Sign of the normal vector. float s = -1.0f; if (t1 > t2) { float temp = t1; t1 = t2; t2 = temp; s = 1.0f; } // Push the min up if (t1 > tmin) { normal.setZero(); normal.y = s; tmin = t1; } // Pull the max down tmax = MathUtils.min(tmax, t2); if (tmin > tmax) { argPool.pushVec2(4); return false; } } // Does the ray start inside the box? // Does the ray intersect beyond the max fraction? if (tmin < 0.0f || input.maxFraction < tmin) { argPool.pushVec2(4); return false; } // Intersection. output.fraction = tmin; output.normal.x = normal.x; output.normal.y = normal.y; argPool.pushVec2(4); return true; }
public float raycastCallback(RayCastInput input, int nodeId) { Object userData = broadPhase.getUserData(nodeId); FixtureProxy proxy = (FixtureProxy) userData; Fixture fixture = proxy.fixture; int index = proxy.childIndex; bool hit = fixture.raycast(output, input, index); if (hit) { float fraction = output.fraction; // Vec2 point = (1.0f - fraction) * input.p1 + fraction * input.p2; temp.set(input.p2); temp.mulLocal(fraction); point.set(input.p1); point.mulLocal(1 - fraction); point.addLocal(temp); return callback.reportFixture(fixture, point, output.normal, fraction); } return input.maxFraction; }
/** * @deprecated please use {@link #raycast(RayCastOutput, RayCastInput, IWorldPool)} for better * performance * @param output * @param input * @return */ public bool raycast(RayCastOutput output, RayCastInput input) { return raycast(output, input, new DefaultWorldPool(4, 4)); }
public void set(RayCastInput rci) { p1.set(rci.p1); p2.set(rci.p2); maxFraction = rci.maxFraction; }
public float raycastCallback(RayCastInput input, int proxyId) { Actor actor = (Actor) m_tree.getUserData(proxyId); RayCastOutput output = new RayCastOutput(); bool hit = actor.aabb.raycast(output, input, getWorld().getPool()); if (hit) { m_rayCastOutput = output; m_rayActor = actor; m_rayActor.fraction = output.fraction; return output.fraction; } return input.maxFraction; }
public void RayCast() { m_rayActor = null; RayCastInput input = new RayCastInput(); input.set(m_rayCastInput); // Ray cast against the dynamic tree. m_tree.raycast(this, input); // Brute force ray cast. Actor bruteActor = null; RayCastOutput bruteOutput = new RayCastOutput(); for (int i = 0; i < _e_actorCount; ++i) { if (m_actors[i].proxyId == -1) { continue; } RayCastOutput output = new RayCastOutput(); bool hit = m_actors[i].aabb.raycast(output, input, getWorld().getPool()); if (hit) { bruteActor = m_actors[i]; bruteOutput = output; input.maxFraction = output.fraction; } } if (bruteActor != null) { if (MathUtils.abs(bruteOutput.fraction - m_rayCastOutput.fraction) > Settings.EPSILON) { Debug.WriteLine("wrong!"); Debug.Assert(MathUtils.abs(bruteOutput.fraction - m_rayCastOutput.fraction) <= 20*Settings.EPSILON); } } }
public override void initTest(bool argDeserialized) { worldExtent = 15.0f; m_proxyExtent = 0.5f; m_tree = new DynamicTree(); for (int i = 0; i < _e_actorCount; ++i) { Actor actor = m_actors[i] = new Actor(); GetRandomAABB(actor.aabb); actor.proxyId = m_tree.createProxy(actor.aabb, actor); } m_stepCount = 0; float h = worldExtent; m_queryAABB = new AABB(); m_queryAABB.lowerBound.set(-3.0f, -4.0f + h); m_queryAABB.upperBound.set(5.0f, 6.0f + h); m_rayCastInput = new RayCastInput(); m_rayCastInput.p1.set(-5.0f, 5.0f + h); m_rayCastInput.p2.set(7.0f, -4.0f + h); // m_rayCastInput.p1.set(0.0f, 2.0f + h); // m_rayCastInput.p2.set(0.0f, -2.0f + h); m_rayCastInput.maxFraction = 1.0f; m_rayCastOutput = new RayCastOutput(); m_automated = false; }