/// <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) { 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); } } }
/// <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 = new ReadOnlyCollection<Spring>(springs); VertexBodies = new ReadOnlyCollection<MassPoint>(points); Triangles = new ReadOnlyCollection<Triangle>(triangles); 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 = Conversion.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> /// 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); }
public static Octree BuildOctree(Model model) { List<JVector> vertices = new List<JVector>(); List<TriangleVertexIndices> indices = new List<TriangleVertexIndices>(); Matrix[] bones = new Matrix[model.Bones.Count]; model.CopyAbsoluteBoneTransformsTo(bones); foreach (ModelMesh modelMesh in model.Meshes) { JMatrix boneTransform = PhysicsSystem.toJMatrix(bones[modelMesh.ParentBone.Index]); foreach (ModelMeshPart meshPart in modelMesh.MeshParts) { int offset = vertices.Count; var meshVertices = meshPart.VertexBuffer.Resource.Buffer.GetData<JVector>(); for (int i = 0; i < meshVertices.Length; ++i) { JVector.Transform(ref meshVertices[i], ref boneTransform, out meshVertices[i]); } vertices.AddRange(meshVertices); // append transformed vertices // there should DEFINITELY be a check here to ensure that the indices used in the model // don't exceed 65535 (max short int). If the model doesn't use shorts, then they get cast all weird. var indexElements = meshPart.IndexBuffer.Resource.GetData<short>(); // Each TriangleVertexIndices holds the indices that constitute a triangle primitive TriangleVertexIndices[] tvi = new TriangleVertexIndices[indexElements.Length]; for (int i = 0; i <= tvi.Length - 2; i += 3) { tvi[i].I0 = indexElements[i + 0] + offset; tvi[i].I1 = indexElements[i + 1] + offset; tvi[i].I2 = indexElements[i + 2] + offset; } indices.AddRange(tvi); // append triangles } } Octree ot = new Octree(vertices, indices); //ot.BuildOctree(); // (already happens in Octree constructor) return ot; }