// Set up initial bounding shapes for the primary (static) and secondary (moving) // bounding shapes along with relevant camera position information. protected override void Initialize() { Console.WriteLine("DEBUG - Game Initialize!"); debugDraw = new DebugDraw(GraphicsDevice); Components.Add(new FrameRateCounter(this)); // Primary frustum Matrix m1 = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 1.77778F, 0.5f, 10.0f); Matrix m2 = Matrix.CreateTranslation(new Vector3(0, 0, -7)); primaryFrustum = new BoundingFrustum(Matrix.Multiply(m2, m1)); cameraOrigins[FrustumGroupIndex] = Vector3.Zero; // Primary axis-aligned box primaryAABox.Min = new Vector3(CAMERA_SPACING - 3, -4, -5); primaryAABox.Max = new Vector3(CAMERA_SPACING + 3, 4, 5); cameraOrigins[AABoxGroupIndex] = new Vector3(CAMERA_SPACING, 0, 0); // Primary oriented box primaryOBox.Center = new Vector3(-CAMERA_SPACING, 0, 0); primaryOBox.HalfExtent = new Vector3(3, 4, 5); primaryOBox.Orientation = Quaternion.CreateFromYawPitchRoll(0.8f, 0.7f, 0); cameraOrigins[OBoxGroupIndex] = primaryOBox.Center; // Primary sphere primarySphere.Center = new Vector3(0, 0, -CAMERA_SPACING); primarySphere.Radius = 5; cameraOrigins[SphereGroupIndex] = primarySphere.Center; // Primary ray primaryRay.Position = new Vector3(0, 0, CAMERA_SPACING); primaryRay.Direction = Vector3.UnitZ; cameraOrigins[RayGroupIndex] = primaryRay.Position; // Initialize all of the secondary objects with default values Vector3 half = new Vector3(0.5F, 0.5F, 0.5F); for (int i = 0; i < NumGroups; i++) { secondarySpheres[i] = new BoundingSphere(Vector3.Zero, 1.0f); secondaryOBoxes[i] = new BoundingOrientedBox(Vector3.Zero, half, Quaternion.Identity); secondaryAABoxes[i] = new BoundingBox(-half, half); secondaryTris[i] = new Triangle(); } rayHitResult = null; currentCamera = 3; cameraOrtho = false; cameraYaw = (float)Math.PI * 0.75F; cameraPitch = MathHelper.PiOver4; cameraDistance = 20; cameraTarget = cameraOrigins[0]; paused = false; base.Initialize(); }
/// <summary> /// Returns true if the given BoundingOrientedBox intersects the triangle (v0,v1,v2) /// </summary> public static bool Intersects(ref BoundingOrientedBox obox, ref Vector3 v0, ref Vector3 v1, ref Vector3 v2) { // Transform the triangle into the local space of the box, so we can use a // faster axis-aligned box test. // Note than when transforming more than one point, using an intermediate matrix // is faster than doing multiple quaternion transforms directly. Quaternion qinv; Quaternion.Conjugate(ref obox.Orientation, out qinv); Matrix minv = Matrix.CreateFromQuaternion(qinv); Triangle localTri = new Triangle(); localTri.V0 = Vector3.TransformNormal(v0 - obox.Center, minv); localTri.V1 = Vector3.TransformNormal(v1 - obox.Center, minv); localTri.V2 = Vector3.TransformNormal(v2 - obox.Center, minv); return(OriginBoxContains(ref obox.HalfExtent, ref localTri) != ContainmentType.Disjoint); }
/// <summary> /// Renders the outline of an oriented bounding box /// </summary> /// <param name="box">Oriented bounding box to render</param> /// <param name="color">Color of the box lines</param> public void DrawWireBox(BoundingOrientedBox box, Color color) { DrawWireShape(box.GetCorners(), cubeIndices, color); }
/// <summary> /// Determines whether the given BoundingOrientedBox contains/intersects/is disjoint from the /// given triangle. /// </summary> public static ContainmentType Contains(ref BoundingOrientedBox obox, ref Triangle triangle) { return(Contains(ref obox, ref triangle.V0, ref triangle.V1, ref triangle.V2)); }
/// <summary> /// Check each pair of objects for collision/containment and store the results for /// coloring them at render time. /// </summary> private void Collide() { // test collisions between objects and frustum collideResults[FrustumGroupIndex, SphereIndex] = primaryFrustum.Contains(secondarySpheres[FrustumGroupIndex]); collideResults[FrustumGroupIndex, OBoxIndex] = BoundingOrientedBox.Contains(primaryFrustum, ref secondaryOBoxes[FrustumGroupIndex]); collideResults[FrustumGroupIndex, AABoxIndex] = primaryFrustum.Contains(secondaryAABoxes[FrustumGroupIndex]); collideResults[FrustumGroupIndex, TriIndex] = TriangleTest.Contains(primaryFrustum, ref secondaryTris[FrustumGroupIndex]); // test collisions between objects and aligned box collideResults[AABoxGroupIndex, SphereIndex] = primaryAABox.Contains(secondarySpheres[AABoxGroupIndex]); collideResults[AABoxGroupIndex, OBoxIndex] = BoundingOrientedBox.Contains(ref primaryAABox, ref secondaryOBoxes[AABoxGroupIndex]); collideResults[AABoxGroupIndex, AABoxIndex] = primaryAABox.Contains(secondaryAABoxes[AABoxGroupIndex]); collideResults[AABoxGroupIndex, TriIndex] = TriangleTest.Contains(ref primaryAABox, ref secondaryTris[AABoxGroupIndex]); // test collisions between objects and oriented box collideResults[OBoxGroupIndex, SphereIndex] = primaryOBox.Contains(ref secondarySpheres[OBoxGroupIndex]); collideResults[OBoxGroupIndex, OBoxIndex] = primaryOBox.Contains(ref secondaryOBoxes[OBoxGroupIndex]); collideResults[OBoxGroupIndex, AABoxIndex] = primaryOBox.Contains(ref secondaryAABoxes[OBoxGroupIndex]); collideResults[OBoxGroupIndex, TriIndex] = TriangleTest.Contains(ref primaryOBox, ref secondaryTris[OBoxGroupIndex]); // test collisions between objects and sphere collideResults[SphereGroupIndex, SphereIndex] = primarySphere.Contains(secondarySpheres[SphereGroupIndex]); collideResults[SphereGroupIndex, OBoxIndex] = BoundingOrientedBox.Contains(ref primarySphere, ref secondaryOBoxes[SphereGroupIndex]); collideResults[SphereGroupIndex, AABoxIndex] = primarySphere.Contains(secondaryAABoxes[SphereGroupIndex]); collideResults[SphereGroupIndex, TriIndex] = TriangleTest.Contains(ref primarySphere, ref secondaryTris[SphereGroupIndex]); // test collisions between objects and ray float dist = -1; collideResults[RayGroupIndex, SphereIndex] = collideResults[RayGroupIndex, OBoxIndex] = collideResults[RayGroupIndex, AABoxIndex] = collideResults[RayGroupIndex, TriIndex] = ContainmentType.Disjoint; rayHitResult = null; float?r = primaryRay.Intersects(secondarySpheres[RayGroupIndex]); if (r.HasValue) { collideResults[RayGroupIndex, SphereIndex] = ContainmentType.Intersects; dist = r.Value; } r = secondaryOBoxes[RayGroupIndex].Intersects(ref primaryRay); if (r.HasValue) { collideResults[RayGroupIndex, OBoxIndex] = ContainmentType.Intersects; dist = r.Value; } r = primaryRay.Intersects(secondaryAABoxes[RayGroupIndex]); if (r.HasValue) { collideResults[RayGroupIndex, AABoxIndex] = ContainmentType.Intersects; dist = r.Value; } r = TriangleTest.Intersects(ref primaryRay, ref secondaryTris[RayGroupIndex]); if (r.HasValue) { collideResults[RayGroupIndex, TriIndex] = ContainmentType.Intersects; dist = r.Value; } // If one of the ray intersection tests was successful, fDistance will be positive. // If so, compute the intersection location and store it in g_RayHitResultBox. if (dist > 0) { rayHitResult = primaryRay.Position + primaryRay.Direction * dist; } }