public CollisionMesh(Model model, uint subdivLevel)
        {
            int verticesCapacity = 0;
            int facesCapacity = 0;
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    verticesCapacity += part.VertexBuffer.VertexCount;
                    facesCapacity += part.PrimitiveCount;
                }
            }

            vertices = new Vector3[verticesCapacity];
            faces = new CollisionFace[facesCapacity];

            int verticesLength = 0;
            int facesLength = 0;

            Matrix[] modelTransforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(modelTransforms);
            foreach (ModelMesh mesh in model.Meshes)
            {
                Matrix meshTransform = modelTransforms[mesh.ParentBone.Index];

                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    int vertexCount = part.VertexBuffer.VertexCount;
                    CustomVertex[] partVertices = new CustomVertex[vertexCount];
                    part.VertexBuffer.GetData(partVertices);

                    for (int i = 0; i < vertexCount; i++)
                    {
                        vertices[verticesLength + i] =
                            Vector3.Transform(partVertices[i].Position, meshTransform);
                    }

                    int indexCount = part.IndexBuffer.IndexCount;
                    short[] partIndices = new short[indexCount];
                    part.IndexBuffer.GetData(partIndices);

                    for (int i = 0; i < part.PrimitiveCount; i++)
                    {
                        faces[facesLength + i] = new CollisionFace(
                            part.StartIndex + i * 3, partIndices,
                            verticesLength + part.VertexOffset, vertices);
                    }

                    verticesLength += vertexCount;
                    facesLength += part.PrimitiveCount;

                }

            }

            CollisionBox box = new CollisionBox(float.MaxValue, -float.MaxValue);
            for (int i = 0; i < verticesCapacity; i++)
                box.AddPoint(vertices[i]);

            if (subdivLevel > 6)
                subdivLevel = 6; // max 8^6 nodes
            tree = new CollisionTree(box, subdivLevel);
            for (int i = 0; i < facesCapacity; i++)
                tree.AddElement(faces[i]);
        }
        public CollisionMesh(Model model, uint subdiv_level)
        {
            int total_num_faces = 0;
            int total_num_verts = 0;

            foreach (ModelMesh mesh in model.Meshes)
            {
                if (IsDynamicEntity(mesh))
                    continue;

                int nv, ni;
                nv = mesh.VertexBuffer.SizeInBytes / mesh.MeshParts[0].VertexStride;
                if(mesh.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits)
                    ni = mesh.IndexBuffer.SizeInBytes / sizeof(short);
                else
                    ni = mesh.IndexBuffer.SizeInBytes / sizeof(int);

                total_num_verts += nv;
                total_num_faces += ni / 3;
            }

            vertices = new Vector3[total_num_verts];
            faces = new CollisionFace[total_num_faces];

            int vcount = 0;
            int fcount = 0;

            foreach (ModelMesh mesh in model.Meshes)
            {
                if (IsDynamicEntity(mesh))
                    continue;

                int nv = mesh.VertexBuffer.SizeInBytes / mesh.MeshParts[0].VertexStride;

                if (mesh.MeshParts[0].VertexStride == 16)
                {
                    VertexPositionColor[] mesh_vertices = new VertexPositionColor[nv];
                    mesh.VertexBuffer.GetData<VertexPositionColor>(mesh_vertices);

                    for (int i = 0; i < nv; i++)
                        vertices[i + vcount] = mesh_vertices[i].Position;
                }

                if (mesh.MeshParts[0].VertexStride == 20)
                {
                    VertexPositionTexture[] mesh_vertices = new VertexPositionTexture[nv];
                    mesh.VertexBuffer.GetData<VertexPositionTexture>(mesh_vertices);

                    for (int i = 0; i < nv; i++)
                        vertices[i + vcount] = mesh_vertices[i].Position;
                }
                else if (mesh.MeshParts[0].VertexStride == 24)
                {
                    VertexPositionColorTexture[] mesh_vertices = new VertexPositionColorTexture[nv];
                    mesh.VertexBuffer.GetData<VertexPositionColorTexture>(mesh_vertices);

                    for (int i = 0; i < nv; i++)
                        vertices[i + vcount] = mesh_vertices[i].Position;
                }
                else if (mesh.MeshParts[0].VertexStride == 32)
                {
                    VertexPositionNormalTexture[] mesh_vertices = new VertexPositionNormalTexture[nv];
                    mesh.VertexBuffer.GetData<VertexPositionNormalTexture>(mesh_vertices);

                    for (int i = 0; i < nv; i++)
                        vertices[i + vcount] = mesh_vertices[i].Position;
                }

                int nf = 0;

                if (mesh.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits)
                {
                    short[] mesh_indices = new short[mesh.IndexBuffer.SizeInBytes / sizeof(short)];
                    mesh.IndexBuffer.GetData<short>(mesh_indices);

                    int count = 0;
                    foreach (ModelMeshPart mesh_part in mesh.MeshParts)
                    {
                        for (int i = 0; i < mesh_part.PrimitiveCount; i++)
                        {
                            faces[nf + fcount] = new CollisionFace(count, mesh_indices, vcount + mesh_part.BaseVertex, vertices);
                            count += 3;
                            nf++;
                        }
                    }
                }
                else
                {
                    int[] mesh_indices = new int[mesh.IndexBuffer.SizeInBytes / sizeof(int)];
                    mesh.IndexBuffer.GetData<int>(mesh_indices);

                    int count = 0;
                    foreach (ModelMeshPart mesh_part in mesh.MeshParts)
                    {
                        for (int i = 0; i < mesh_part.PrimitiveCount; i++)
                        {
                            faces[nf + fcount] = new CollisionFace(count, mesh_indices, vcount + mesh_part.BaseVertex, vertices);
                            count += 3;
                            nf++;
                        }
                    }
                }

                vcount += nv;
                fcount += nf;
            }

            CollisionBox box = new CollisionBox(float.MaxValue, -float.MaxValue);
            for (int i = 0; i < vcount; i++)
                box.AddPoint(vertices[i]);

            if (subdiv_level > 6)
                subdiv_level = 6; // max 8^6 nodes
            tree = new CollisionTree(box, subdiv_level);
            for (int i = 0; i < fcount; i++)
                tree.AddElement(faces[i]);
        }
        public CollisionMesh(Model model, uint subdivLevel)
        {
            int verticesCapacity = 0;
            int facesCapacity    = 0;

            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    verticesCapacity += part.VertexBuffer.VertexCount;
                    facesCapacity    += part.PrimitiveCount;
                }
            }

            vertices = new Vector3[verticesCapacity];
            faces    = new CollisionFace[facesCapacity];

            int verticesLength = 0;
            int facesLength    = 0;

            Matrix[] modelTransforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(modelTransforms);
            foreach (ModelMesh mesh in model.Meshes)
            {
                Matrix meshTransform = modelTransforms[mesh.ParentBone.Index];

                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    int            vertexCount  = part.VertexBuffer.VertexCount;
                    CustomVertex[] partVertices = new CustomVertex[vertexCount];
                    part.VertexBuffer.GetData(partVertices);

                    for (int i = 0; i < vertexCount; i++)
                    {
                        vertices[verticesLength + i] =
                            Vector3.Transform(partVertices[i].Position, meshTransform);
                    }

                    int     indexCount  = part.IndexBuffer.IndexCount;
                    short[] partIndices = new short[indexCount];
                    part.IndexBuffer.GetData(partIndices);

                    for (int i = 0; i < part.PrimitiveCount; i++)
                    {
                        faces[facesLength + i] = new CollisionFace(
                            part.StartIndex + i * 3, partIndices,
                            verticesLength + part.VertexOffset, vertices);
                    }

                    verticesLength += vertexCount;
                    facesLength    += part.PrimitiveCount;
                }
            }

            CollisionBox box = new CollisionBox(float.MaxValue, -float.MaxValue);

            for (int i = 0; i < verticesCapacity; i++)
            {
                box.AddPoint(vertices[i]);
            }

            if (subdivLevel > 6)
            {
                subdivLevel = 6; // max 8^6 nodes
            }
            tree = new CollisionTree(box, subdivLevel);
            for (int i = 0; i < facesCapacity; i++)
            {
                tree.AddElement(faces[i]);
            }
        }