public static void ExtractModelMeshPartData(ModelMesh mm, ModelMeshPart mmp, ref Matrix xform, List <Vector3> vertices, List <TriangleVertexIndices> indices, string name) { int offset = vertices.Count; Vector3[] a = new Vector3[mmp.NumVertices]; mm.VertexBuffer.GetData <Vector3>(mmp.StreamOffset + mmp.BaseVertex * mmp.VertexStride, a, 0, mmp.NumVertices, mmp.VertexStride); for (int i = 0; i != a.Length; ++i) { Vector3.Transform(ref a[i], ref xform, out a[i]); } vertices.AddRange(a); if (mm.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits) { throw new Exception( String.Format("Model {0} uses 32-bit indices, which are not supported.", name)); } short[] s = new short[mmp.PrimitiveCount * 3]; mm.IndexBuffer.GetData <short>(mmp.StartIndex * 2, s, 0, mmp.PrimitiveCount * 3); TriangleVertexIndices[] tvi = new TriangleVertexIndices[mmp.PrimitiveCount]; for (int i = 0; i != tvi.Length; ++i) { tvi[i].I0 = s[i * 3 + 0] + offset; tvi[i].I1 = s[i * 3 + 1] + offset; tvi[i].I2 = s[i * 3 + 2] + offset; } indices.AddRange(tvi); }
public static void ExtractModelMeshPartData(ModelMesh mm, ModelMeshPart mmp, ref Matrix xform, List<Vector3> vertices, List<TriangleVertexIndices> indices, string name) { int offset = vertices.Count; Vector3[] a = new Vector3[mmp.NumVertices]; mm.VertexBuffer.GetData<Vector3>(mmp.StreamOffset + mmp.BaseVertex * mmp.VertexStride, a, 0, mmp.NumVertices, mmp.VertexStride); for (int i = 0; i != a.Length; ++i) Vector3.Transform(ref a[i], ref xform, out a[i]); vertices.AddRange(a); if (mm.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits) throw new Exception( String.Format("Model {0} uses 32-bit indices, which are not supported.", name)); short[] s = new short[mmp.PrimitiveCount * 3]; mm.IndexBuffer.GetData<short>(mmp.StartIndex * 2, s, 0, mmp.PrimitiveCount * 3); TriangleVertexIndices[] tvi = new TriangleVertexIndices[mmp.PrimitiveCount]; for (int i = 0; i != tvi.Length; ++i) { tvi[i].I0 = s[i * 3 + 0] + offset; tvi[i].I1 = s[i * 3 + 1] + offset; tvi[i].I2 = s[i * 3 + 2] + offset; } indices.AddRange(tvi); }
public void ExtractData(List <Vector3> vertices, List <TriangleVertexIndices> indices, Model model) { var bones = new Matrix[model.Bones.Count]; model.CopyAbsoluteBoneTransformsTo(bones); foreach (var mm in model.Meshes) { var offset = vertices.Count; var xform = bones[mm.ParentBone.Index]; foreach (var mmp in mm.MeshParts) { var a = new Vector3[mmp.NumVertices]; var stride = mmp.VertexBuffer.VertexDeclaration.VertexStride; mmp.VertexBuffer.GetData(mmp.VertexOffset * stride, a, 0, mmp.NumVertices, stride); for (var i = 0; i != a.Length; ++i) { Vector3.Transform(ref a[i], ref xform, out a[i]); } vertices.AddRange(a); if (mmp.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits) { throw new Exception(string.Format("Model uses 32-bit indices, which are not supported.")); } var s = new short[mmp.PrimitiveCount * 3]; mmp.IndexBuffer.GetData(mmp.StartIndex * 2, s, 0, mmp.PrimitiveCount * 3); var tvi = new TriangleVertexIndices[mmp.PrimitiveCount]; for (var i = 0; i != tvi.Length; ++i) { tvi[i].I0 = s[i * 3 + 2] + offset; tvi[i].I1 = s[i * 3 + 1] + offset; tvi[i].I2 = s[i * 3 + 0] + offset; } indices.AddRange(tvi); } } }
private void AddPointsAndSprings(List <TriangleVertexIndices> indices, List <JVector> vertices) { for (int i = 0; i < vertices.Count; i++) { MassPoint point = new MassPoint(sphere, this, material); point.Position = vertices[i]; point.Mass = 0.1f; points.Add(point); } for (int i = 0; i < indices.Count; i++) { TriangleVertexIndices index = indices[i]; Triangle t = new Triangle(this); t.indices = index; triangles.Add(t); t.boundingBox = JBBox.SmallBox; t.boundingBox.AddPoint(points[t.indices.I0].position); t.boundingBox.AddPoint(points[t.indices.I1].position); t.boundingBox.AddPoint(points[t.indices.I2].position); t.dynamicTreeID = dynamicTree.AddProxy(ref t.boundingBox, t); } HashSet <Edge> edges = GetEdges(indices); int count = 0; foreach (Edge edge in edges) { Spring spring = new Spring(points[edge.Index1], points[edge.Index2]); spring.Softness = 0.01f; spring.BiasFactor = 0.1f; spring.SpringType = SpringType.EdgeSpring; springs.Add(spring); count++; } }
/// <summary> /// Initialize the physic world with the geometric detail of map. /// </summary> /// <param name="map">The base to create the physic world.</param> private void Initialize(Map.Map map) { List <JVector> vertices = new List <JVector>(); List <TriangleVertexIndices> indices = new List <TriangleVertexIndices>(); for (uint i = 0; i < map.Width; i++) { for (uint j = 0; j < map.Length; j++) { for (uint k = 0; k < map.Height; k++) { int pos = 0; Block block = map.GetBlock(new Vector3(i, j, k)); block.CreateColisions(); foreach (JVector vertice in block.CollisionVertices) { vertices.Add(vertice); pos++; } int newPos = vertices.Count - pos; foreach (TriangleVertexIndices indice in block.CollisionTriangles) { TriangleVertexIndices t = new TriangleVertexIndices(indice.I0 + newPos, indice.I1 + newPos, indice.I2 + newPos); indices.Add(t); } } } } //ToDo: The vertices list has duplicated vertices. In the worst case each vertices has 4 different instantiation. //Probably some performance can be expected by remove the duplicated ones. //However it is also necessary to update the indies List with the correct positions. Octree tree = new Octree(vertices, indices); TriangleMeshShape shape = new TriangleMeshShape(tree); RigidBody body = new RigidBody(shape); body.IsStatic = true; world.AddBody(body); }
/// <summary> /// Helper Method to get the vertex and index List from the model. /// </summary> /// <param name="vertices"></param> /// <param name="indices"></param> /// <param name="model"></param> public void ExtractData(List <Vector3> vertices, List <TriangleVertexIndices> indices, Model model) { Demo.Camera.Position = new Vector3(12, 10, 25); Demo.Camera.Target = Demo.Camera.Position + Vector3.Normalize(new Vector3(10, 5, 20)); Matrix[] bones_ = new Matrix[model.Bones.Count]; model.CopyAbsoluteBoneTransformsTo(bones_); foreach (ModelMesh mm in model.Meshes) { Matrix xform = bones_[mm.ParentBone.Index]; foreach (ModelMeshPart mmp in mm.MeshParts) { int offset = vertices.Count; Vector3[] a = new Vector3[mmp.NumVertices]; mmp.VertexBuffer.GetData <Vector3>(mmp.VertexOffset * mmp.VertexBuffer.VertexDeclaration.VertexStride, a, 0, mmp.NumVertices, mmp.VertexBuffer.VertexDeclaration.VertexStride); for (int i = 0; i != a.Length; ++i) { Vector3.Transform(ref a[i], ref xform, out a[i]); } vertices.AddRange(a); if (mmp.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits) { throw new Exception( String.Format("Model uses 32-bit indices, which are not supported.")); } short[] s = new short[mmp.PrimitiveCount * 3]; mmp.IndexBuffer.GetData <short>(mmp.StartIndex * 2, s, 0, mmp.PrimitiveCount * 3); TriangleVertexIndices[] tvi = new TriangleVertexIndices[mmp.PrimitiveCount]; for (int i = 0; i != tvi.Length; ++i) { tvi[i].I0 = s[i * 3 + 0] + offset; tvi[i].I1 = s[i * 3 + 1] + offset; tvi[i].I2 = s[i * 3 + 2] + offset; } indices.AddRange(tvi); } } }
private void RemoveDuplicateVertices(List <TriangleVertexIndices> indices, List <JVector> vertices) { Dictionary <JVector, int> unique = new Dictionary <JVector, int>(vertices.Count); Stack <int> tbr = new Stack <int>(vertices.Count / 3); // get all unique vertices and their indices for (int i = 0; i < vertices.Count; i++) { if (!unique.ContainsKey(vertices[i])) { unique.Add(vertices[i], unique.Count); } else { tbr.Push(i); } } // reconnect indices for (int i = 0; i < indices.Count; i++) { TriangleVertexIndices tvi = indices[i]; tvi.I0 = unique[vertices[tvi.I0]]; tvi.I1 = unique[vertices[tvi.I1]]; tvi.I2 = unique[vertices[tvi.I2]]; indices[i] = tvi; } // remove duplicate vertices while (tbr.Count > 0) { vertices.RemoveAt(tbr.Pop()); } unique.Clear(); }
/// <summary> /// Creates a 2D-Cloth. Connects Nearest Neighbours (4x, called EdgeSprings) and adds additional /// shear/bend constraints (4xShear+4xBend). /// </summary> /// <param name="sizeX"></param> /// <param name="sizeY"></param> /// <param name="scale"></param> public SoftBody(int sizeX, int sizeY, float scale) { List <TriangleVertexIndices> indices = new List <TriangleVertexIndices>(); List <JVector> vertices = new List <JVector>(); for (int i = 0; i < sizeY; i++) { for (int e = 0; e < sizeX; e++) { vertices.Add(new JVector(i, 0, e) * scale); } } for (int i = 0; i < sizeX - 1; i++) { for (int e = 0; e < sizeY - 1; e++) { TriangleVertexIndices index = new TriangleVertexIndices(); { index.I0 = (e + 0) * sizeX + i + 0; index.I1 = (e + 0) * sizeX + i + 1; index.I2 = (e + 1) * sizeX + i + 1; indices.Add(index); index.I0 = (e + 0) * sizeX + i + 0; index.I1 = (e + 1) * sizeX + i + 1; index.I2 = (e + 1) * sizeX + i + 0; indices.Add(index); } } } EdgeSprings = springs.AsReadOnly(); VertexBodies = points.AsReadOnly(); Triangles = triangles.AsReadOnly(); AddPointsAndSprings(indices, vertices); for (int i = 0; i < sizeX - 1; i++) { for (int e = 0; e < sizeY - 1; e++) { Spring spring = new Spring(points[(e + 0) * sizeX + i + 1], points[(e + 1) * sizeX + i + 0]); spring.Softness = 0.01f; spring.BiasFactor = 0.1f; springs.Add(spring); } } foreach (Spring spring in springs) { JVector delta = spring.body1.position - spring.body2.position; if (delta.Z != 0.0f && delta.X != 0.0f) { spring.SpringType = SpringType.ShearSpring; } else { spring.SpringType = SpringType.EdgeSpring; } } for (int i = 0; i < sizeX - 2; i++) { for (int e = 0; e < sizeY - 2; e++) { Spring spring1 = new Spring(points[(e + 0) * sizeX + i + 0], points[(e + 0) * sizeX + i + 2]); spring1.Softness = 0.01f; spring1.BiasFactor = 0.1f; Spring spring2 = new Spring(points[(e + 0) * sizeX + i + 0], points[(e + 2) * sizeX + i + 0]); spring2.Softness = 0.01f; spring2.BiasFactor = 0.1f; spring1.SpringType = SpringType.BendSpring; spring2.SpringType = SpringType.BendSpring; springs.Add(spring1); springs.Add(spring2); } } }
public static void ExtractData(List <JVector> vertices, List <TriangleVertexIndices> indices, Model model) { Matrix[] bones_ = new Matrix[model.Bones.Count]; model.CopyAbsoluteBoneTransformsTo(bones_); foreach (ModelMesh modelmesh in model.Meshes) { JMatrix xform = Helper.ToJitterMatrix(bones_[modelmesh.ParentBone.Index]); foreach (ModelMeshPart meshPart in modelmesh.MeshParts) { // Before we add any more where are we starting from int offset = vertices.Count; // Read the format of the vertex buffer VertexDeclaration declaration = meshPart.VertexBuffer.VertexDeclaration; VertexElement[] vertexElements = declaration.GetVertexElements(); // Find the element that holds the position VertexElement vertexPosition = new VertexElement(); foreach (VertexElement vert in vertexElements) { if (vert.VertexElementUsage == VertexElementUsage.Position && vert.VertexElementFormat == VertexElementFormat.Vector3) { vertexPosition = vert; // There should only be one break; } } // Check the position element found is valid if (vertexPosition == null || vertexPosition.VertexElementUsage != VertexElementUsage.Position || vertexPosition.VertexElementFormat != VertexElementFormat.Vector3) { throw new Exception("Model uses unsupported vertex format!"); } // This where we store the vertices until transformed JVector[] allVertex = new JVector[meshPart.NumVertices]; // Read the vertices from the buffer in to the array meshPart.VertexBuffer.GetData <JVector>( meshPart.VertexOffset * declaration.VertexStride + vertexPosition.Offset, allVertex, 0, meshPart.NumVertices, declaration.VertexStride); // Transform them based on the relative bone location and the world if provided for (int i = 0; i != allVertex.Length; ++i) { JVector.Transform(ref allVertex[i], ref xform, out allVertex[i]); } // Store the transformed vertices with those from all the other meshes in this model vertices.AddRange(allVertex); // Find out which vertices make up which triangles if (meshPart.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits) { // This could probably be handled by using int in place of short but is unnecessary throw new Exception("Model uses 32-bit indices, which are not supported."); } // Each primitive is a triangle short[] indexElements = new short[meshPart.PrimitiveCount * 3]; meshPart.IndexBuffer.GetData <short>( meshPart.StartIndex * 2, indexElements, 0, meshPart.PrimitiveCount * 3); // Each TriangleVertexIndices holds the three indexes to each vertex that makes up a triangle TriangleVertexIndices[] tvi = new TriangleVertexIndices[meshPart.PrimitiveCount]; for (int i = 0; i != tvi.Length; ++i) { // The offset is because we are storing them all in the one array and the // vertices were added to the end of the array. tvi[i].I0 = indexElements[i * 3 + 0] + offset; tvi[i].I1 = indexElements[i * 3 + 1] + offset; tvi[i].I2 = indexElements[i * 3 + 2] + offset; } // Store our triangles indices.AddRange(tvi); } } }
/// <summary> /// Get all the triangles from each mesh part (Changed for XNA 4) /// </summary> public static void ExtractModelMeshPartData(ModelMeshPart meshPart, ref Matrix transform, List<Vector3> vertices, List<TriangleVertexIndices> indices) { // Before we add any more where are we starting from int offset = vertices.Count; // == Vertices (Changed for XNA 4.0) // Read the format of the vertex buffer VertexDeclaration declaration = meshPart.VertexBuffer.VertexDeclaration; VertexElement[] vertexElements = declaration.GetVertexElements(); // Find the element that holds the position VertexElement vertexPosition = new VertexElement(); foreach (VertexElement vert in vertexElements) { if (vert.VertexElementUsage == VertexElementUsage.Position && vert.VertexElementFormat == VertexElementFormat.Vector3) { vertexPosition = vert; // There should only be one break; } } // Check the position element found is valid if (vertexPosition == null || vertexPosition.VertexElementUsage != VertexElementUsage.Position || vertexPosition.VertexElementFormat != VertexElementFormat.Vector3) { throw new Exception("Model uses unsupported vertex format!"); } // This where we store the vertices until transformed Vector3[] allVertex = new Vector3[meshPart.NumVertices]; // Read the vertices from the buffer in to the array meshPart.VertexBuffer.GetData<Vector3>( meshPart.VertexOffset * declaration.VertexStride + vertexPosition.Offset, allVertex, 0, meshPart.NumVertices, declaration.VertexStride); // Transform them based on the relative bone location and the world if provided for (int i = 0; i != allVertex.Length; ++i) { Vector3.Transform(ref allVertex[i], ref transform, out allVertex[i]); } // Store the transformed vertices with those from all the other meshes in this model vertices.AddRange(allVertex); // == Indices (Changed for XNA 4) // Find out which vertices make up which triangles if (meshPart.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits) { // This could probably be handled by using int in place of short but is unnecessary throw new Exception("Model uses 32-bit indices, which are not supported."); } // Each primitive is a triangle short[] indexElements = new short[meshPart.PrimitiveCount * 3]; // It looks like the same index buffer is referenced from each meshPart. meshPart.IndexBuffer.GetData<short>( meshPart.StartIndex * 2, indexElements, 0, meshPart.PrimitiveCount * 3); // Each TriangleVertexIndices holds the three indexes to each vertex that makes up a triangle TriangleVertexIndices[] tvi = new TriangleVertexIndices[meshPart.PrimitiveCount]; for (int i = 0; i != tvi.Length; ++i) { // The offset is because we are storing them all in the one array and the // vertices were added to the end of the array. tvi[i].A = indexElements[i * 3 + 0] + offset; tvi[i].B = indexElements[i * 3 + 1] + offset; tvi[i].C = indexElements[i * 3 + 2] + offset; } // Store our triangles indices.AddRange(tvi); }