예제 #1
0
        /// <summary>
        /// Segment-Mesh collision test, used by the mesh-mesh collision test
        /// Andre Berhtiaume, 2008 
        /// </summary>
        /// <param name="m1"></param>
        /// <param name="segstart"></param>
        /// <param name="segend"></param>
        /// <param name="meshIndex"></param>
        /// <param name="meshPartIndex"></param>
        /// <param name="polyIndex"></param>
        /// <returns></returns>
        private static bool CollisionSegmentMesh(int m1ind, ModelGeo m1, Vector3 segstart, Vector3 segend, out int meshIndex, out int meshPartIndex, out int polyIndex)
        {
            meshIndex = -1;
            polyIndex = -1;
            meshPartIndex = -1;
            float u = 0, v = 0, w = 0, t = 0;
            Vector3 a, b, c;

            Ray meshSpaceRay = new Ray();

            for (int i = 0; i < m1.mModel.Meshes.Count; i++)
            {
                ModelMesh mesh = m1.mModel.Meshes[i];

                Matrix mat = m1.MeshMat(i); //m1.mMatBones[mesh.ParentBone.Index] * m1.mMatWorld;
                Matrix inverseSceneTransform = Matrix.Invert(mat);

                Vector3 rayPosition = Vector3.Transform(segstart, inverseSceneTransform);
                Vector3 rayDirection = Vector3.TransformNormal(Vector3.Normalize(segend - segstart), inverseSceneTransform);
                Vector3 locsegstart = rayPosition;
                Vector3 locsegend = Vector3.Transform(segend, inverseSceneTransform);

                meshSpaceRay.Position = rayPosition;
                meshSpaceRay.Direction = rayDirection;

                //if (mesh.BoundingSphere.Intersects(meshSpaceRay).HasValue == false)
                //{
                //    continue;
                //}

                List<CollisionUtility.collidingPart> collidingParts = new List<CollisionUtility.collidingPart>();

                if (!CollisionUtility.Contains(m1.mModel))
                {
                    CollisionUtility.ModelBoundingInfo.Add(CollisionUtility.CalcBoundingBoxes(m1.mModel));
                }
                else
                {
                    foreach (CollisionUtility.ModelBoundingBoxBuffer mbb in CollisionUtility.modelBoundingInfo)
                    {
                        //Monitor.AddMessage("count " + mbb.MeshList.Count);
                        if (i < mbb.MeshList.Count) // this is a patch: must understand why it's needed
                        {
                            for (int j = 0; j < mbb.MeshList[i].BoundingBoxes.Count; j++)
                            {
                                float? f = meshSpaceRay.Intersects(mbb.MeshList[i].BoundingBoxes[j]);
                                //Monitor.AddMessage("test" + f.HasValue);
                                if (f.HasValue)
                                {
                                    CollisionUtility.collidingPart cp;
                                    cp.MeshIndex = i;
                                    cp.MeshPartIndex = j;
                                    cp.Distance = f.Value;
                                    collidingParts.Add(cp);
                                }
                            }
                        }
                    }
                    //Monitor.AddMessage( "CP count = " + collidingParts.Count);
                    collidingParts.Sort();
                }

                //Monitor.AddMessage("Col part: " + collidingParts.Count);
                if (collidingParts.Count == 0)
                {
                    continue;
                }

                //*
                for (int j = 0; j < collidingParts.Count; j++)
                {
                    CollisionUtility.collidingPart prt = collidingParts[j];

                    ModelMeshPart part = mesh.MeshParts[prt.MeshPartIndex];
                    //*/

                    /*
                    for (int j = 0; j < mesh.MeshParts.Count; j++)
                    {
                        ModelMeshPart part = mesh.MeshParts[j];
                    //*/
                    for (int x = 0; x < part.PrimitiveCount; x++)
                    {
                        a = m1.GetVertex(i, prt.MeshPartIndex, x * 3 + 0);
                        b = m1.GetVertex(i, prt.MeshPartIndex, x * 3 + 1);
                        c = m1.GetVertex(i, prt.MeshPartIndex, x * 3 + 2);

                        if (IntersectSegmentTriangle(locsegstart, locsegend, b, a, c, ref u, ref v, ref w, ref t))
                        {
                            meshIndex = i;
                            meshPartIndex = prt.MeshPartIndex;
                            polyIndex = x;

                            a = Vector3.Transform(a, mat);
                            b = Vector3.Transform(b, mat);
                            c = Vector3.Transform(c, mat);

                            n2 = Vector3.Cross(a - b, c - b);

                            //n2 = Vector3.Transform(n2, transforms[mesh.ParentBone.Index] * sceneTransform);

                            //Console.WriteLine("Test case:");
                            //Monitor.AddMessage( "Event: i1 " + m1ind + "  i2: " + i + "  n1: " + n1 + "  n2: " + n2 );

                            CollisionData.NewEvent(m1ind, i, n1, n2);

                            //Visualize.AddVector( new Vector3(0,2,0), 5* n2, Color.Red);

                            //Monitor.AddMessage("SegmentMesh loop: i1: " + CollisionData.Index1 + "  i2: " + CollisionData.Index2 + "  n1: " + CollisionData.Normal1 + "  n2: " + CollisionData.Normal2);
                        }

                        // Comparison Counter (pedagogical value only)
                        mComparisonCounter++;
                    }
                }
            }

            //return meshIndex != -1 && polyIndex != -1 && meshPartIndex != -1;

            //return true;// Data.ColEvent();

            /*
            if (CollisionData.Event)
                Monitor.AddMessage("SegmentMesh: i1: " + CollisionData.Index1 + "  i2: " + CollisionData.Index2
                                    + "  n1: " + CollisionData.Normal1 + "  n2: " + CollisionData.Normal2);
            //*/

            return CollisionData.Event;
        }
예제 #2
0
        /// <summary>
        /// Mesh-Mesh collision test
        /// Andre Berhtiaume, 2008
        /// </summary>
        /// <param name="m1"></param>
        /// <param name="m2"></param>
        /// <returns>True if a collision is detected, false otherwise.</returns>
        private static bool CollisionMeshMesh(ModelGeo m1, ModelGeo m2)
        {
            int meshIndex = -1;
            int polyIndex = -1;
            int meshPartIndex = -1;

            //Matrix[] transforms = new Matrix[m1.mModel.Bones.Count];
            //m1.mModel.CopyAbsoluteBoneTransformsTo(transforms);

            for (int i = 0; i < m1.mModel.Meshes.Count; i++)
            {
                ModelMesh mesh = m1.mModel.Meshes[i];

                Matrix inverseSceneTransform = Matrix.Invert(m1.mMatBones[mesh.ParentBone.Index] * m1.mMatWorld);

                for (int j = 0; j < mesh.MeshParts.Count; j++)
                {
                    ModelMeshPart part = mesh.MeshParts[j];

                    for (int x = 0; x < part.PrimitiveCount; x++)
                    {
                        Matrix mat = m1.mMatBones[mesh.ParentBone.Index] * m1.mMatWorld;
                        Vector3 a = Vector3.Transform(m1.GetVertex(i, j, x * 3 + 0), mat);
                        Vector3 b = Vector3.Transform(m1.GetVertex(i, j, x * 3 + 1), mat);
                        Vector3 c = Vector3.Transform(m1.GetVertex(i, j, x * 3 + 2), mat);

                        n1 = Vector3.Cross((a - b), (c - b));

                        CollisionSegmentMesh(i, m2, a, b, out meshIndex, out meshPartIndex, out polyIndex);
                        CollisionSegmentMesh(i, m2, b, c, out meshIndex, out meshPartIndex, out polyIndex);
                        CollisionSegmentMesh(i, m2, c, a, out meshIndex, out meshPartIndex, out polyIndex);

                        /*
                        if (CollisionSegmentMesh(m2.mModel, m2.mMatWorld, a, b, out meshIndex, out meshPartIndex, out polyIndex)
                            ||
                            CollisionSegmentMesh(m2.mModel, m2.mMatWorld, b, c, out meshIndex, out meshPartIndex, out polyIndex)
                            ||
                            CollisionSegmentMesh(m2.mModel, m2.mMatWorld, c, a, out meshIndex, out meshPartIndex, out polyIndex))
                        {

                            meshIndex = i;
                            meshPartIndex = j;
                            polyIndex = x;

                            //return true;
                        }
                        //*/
                    }
                }
            }

            //return meshIndex != -1 && polyIndex != -1 && meshPartIndex != -1;
            return CollisionData.Event;
        }
예제 #3
0
        /// <summary>
        /// Returns wether a models's meshes collides with a terrain
        /// </summary>
        /// <param name="m1"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        private static bool CollisionMeshTerrain(ModelGeo m1, Terrain t)
        {
            int meshIndex = -1;
            int polyIndex = -1;
            int meshPartIndex = -1;

            for (int i = 0; i < m1.mModel.Meshes.Count; i++)
            {
                ModelMesh mesh = m1.mModel.Meshes[i];

                for (int j = 0; j < mesh.MeshParts.Count; j++)
                {
                    ModelMeshPart part = mesh.MeshParts[j];

                    for (int x = 0; x < part.PrimitiveCount; x++)
                    {
                        Matrix mat = m1.mMatBones[mesh.ParentBone.Index] * m1.mMatWorld;
                        Vector3 a = Vector3.Transform(m1.GetVertex(i, j, x * 3 + 0), mat);
                        Vector3 b = Vector3.Transform(m1.GetVertex(i, j, x * 3 + 1), mat);
                        Vector3 c = Vector3.Transform(m1.GetVertex(i, j, x * 3 + 2), mat);

                        if (a.Y < t.GetHeight(a) || b.Y < t.GetHeight(b) || c.Y < t.GetHeight(c))
                        {

                            meshIndex = i;
                            meshPartIndex = j;
                            polyIndex = x;

                            n1 = Vector3.Cross((a - b), (c - b));
                            n2 = t.GetNormal(a);

                            CollisionData.NewEvent(i, -1, n1, n2);

                            //return true;
                        }
                    }
                }
            }

            //Console.WriteLine(fClosestPoly);
            //return meshIndex != -1 && polyIndex != -1 && meshPartIndex != -1;
            return CollisionData.Event;
        }
예제 #4
0
        /// <summary>
        /// Bounding sphere-Mesh collision test
        /// Andre Berhtiaume, 2008
        /// </summary>
        /// <param name="m1"></param>
        /// <param name="s"></param>
        /// <returns>True if a collision is detected, false otherwise.</returns>
        private static bool CollisionMeshBoundingSphere(ModelGeo m1, int m2ind, BoundingSphere s)
        {
            float t = -1;
            Vector3 q = Vector3.Zero;
            BoundingSphere bs;

            for (int i = 0; i < m1.mModel.Meshes.Count; i++)
            {
                ModelMesh mesh = m1.mModel.Meshes[i];

                Matrix inverseSceneTransform = Matrix.Invert(m1.mMatBones[mesh.ParentBone.Index] * m1.mMatWorld);

                bs = s;
                bs.Center = Vector3.Transform(s.Center, inverseSceneTransform);
                bs.Radius *= 1 / m1.mMinScale;

                //Monitor.AddMessage("center " + bs.Center + "   radius: " + bs.Radius);

                for (int j = 0; j < mesh.MeshParts.Count; j++)
                {
                    ModelMeshPart part = mesh.MeshParts[j];

                    for (int x = 0; x < part.PrimitiveCount; x++)
                    {
                        // Comparison Counter (pedagogical value only
                        mComparisonCounter++;

                        Vector3 a = m1.GetVertex(i, j, x * 3 + 0);
                        Vector3 b = m1.GetVertex(i, j, x * 3 + 1);
                        Vector3 c = m1.GetVertex(i, j, x * 3 + 2);

                        n1 = Vector3.Transform(Vector3.Cross((a - b), (c - b)), m1.mMatWorldRot);

                        if (IntersectRaySphere(a, Vector3.Normalize(b - a), bs, ref t, ref q)
                            && t <= (a - b).Length() //*******************
                            )
                        {
                            //Console.WriteLine("ab t = " + t + "   impact " + q + "from " + a + " and " + b);

                            n2 = Vector3.Transform(q - bs.Center, m1.mMatWorldRot);
                            CollisionData.NewEvent(i, m2ind, n1, n2);
                            //return true;
                        }

                        if (IntersectRaySphere(b, Vector3.Normalize(c - b), bs, ref t, ref q)
                            && t <= (b - c).Length()
                            )
                        {
                            //Console.WriteLine("bc t = " + t + "   impact " + q + "from " + b + " and " + c);
                            n2 = Vector3.Transform(q - bs.Center, m1.mMatWorldRot);
                            CollisionData.NewEvent(i, m2ind, n1, n2);
                            //return true;
                        }

                        if (IntersectRaySphere(c, Vector3.Normalize(a - c), bs, ref t, ref q)
                            && t <= (c - a).Length()
                            )
                        {
                            //Console.WriteLine("ca t = " + t + "   impact " + q + "from " + c + " and " + a);
                            n2 = Vector3.Transform(q - bs.Center, m1.mMatWorldRot);
                            CollisionData.NewEvent(i, m2ind, n1, n2);
                            //return true;
                        }
                        //Monitor.AddMessage("t = " + t);

                    }
                }
            }

            return CollisionData.Event; //false;
        }