/// <summary> /// Add array of vertices to the combined mesh. /// </summary> /// <param name="vertices">Vertices array to add.</param> /// <param name="indexes">Draw order / indexes array.</param> /// <param name="material">Material to use with the vertices.</param> public void AddVertices(VertexType[] vertices, ushort[] indexes, Materials.MaterialAPI material) { // sanity check - if build was called assert if (_wasBuilt) { throw new Exceptions.InvalidActionException("Cannot add vertices to Combined Mesh Entity after it was built!"); } // get the combined chunk to add these vertices to CombinedMeshesPart combinedPart = GetCombinedPart(material); // add vertices to combined part combinedPart.Vertices.AddRange(vertices); foreach (var vertex in vertices) { _allPoints.Add(GetPosition(vertex)); } // set indexes combinedPart.PushIndexes(indexes); // increase index offset in combined part combinedPart.IndexOffset += vertices.Length; // update primitives count combinedPart.PrimitiveCount += indexes.Length / 3; }
/// <summary> /// Add a model mesh to the combined mesh. /// </summary> /// <param name="mesh">Mesh to add.</param> /// <param name="transform">World transformations.</param> /// <param name="material">Optional material to use instead of the mesh default materials.</param> public void AddModelMesh(ModelMesh mesh, Matrix transform, Materials.MaterialAPI material = null) { // sanity check - if build was called assert if (_wasBuilt) { throw new Exceptions.InvalidActionException("Cannot add meshes to Combined Mesh Entity after it was built!"); } // did we get material override to set? bool externalMaterial = material != null; // iterate mesh parts foreach (var meshPart in mesh.MeshParts) { // if we didn't get external material to use, get material from mesh part. if (!externalMaterial) { material = meshPart.GetMaterial(); } // get the combined chunk to add this meshpart to CombinedMeshesPart combinedPart = GetCombinedPart(material); // make sure its not readonly if (meshPart.VertexBuffer.BufferUsage == BufferUsage.WriteOnly || meshPart.IndexBuffer.BufferUsage == BufferUsage.WriteOnly) { throw new Exceptions.InvalidValueException("Cannot add mesh with write-only buffers to Combined Mesh!"); } // make sure vertex buffer uses position-normal-texture if (meshPart.VertexBuffer.VertexDeclaration.VertexStride < 8) { throw new Exceptions.InvalidValueException("Combined meshes can only use vertex buffers with position, normal and texture!"); } // get vertex buffer parameters int vertexStride = meshPart.VertexBuffer.VertexDeclaration.VertexStride; int vertexBufferSize = meshPart.NumVertices * vertexStride; // get vertex data as float float[] vertexData = new float[vertexBufferSize / sizeof(float)]; meshPart.VertexBuffer.GetData <float>(vertexData); // iterate through vertices and add them int verticesInPart = 0; for (int i = 0; i < vertexBufferSize / sizeof(float); i += vertexStride / sizeof(float)) { // get curr position with transformations Vector3 currPosition = Vector3.Transform(new Vector3(vertexData[i], vertexData[i + 1], vertexData[i + 2]), transform); // get other vertex properties based on type and add to vertices buffer switch (_vtype) { case VertexTypes.VertexPosition: { // add to buffer var vertexToAdd = new VertexPosition(currPosition); combinedPart.Vertices.Add(ToVertexType(vertexToAdd)); break; } case VertexTypes.VertexPositionColor: { // get color Color currColor = new Color(vertexData[i + 3], vertexData[i + 4], vertexData[i + 5], vertexData[i + 6]); // add to buffer var vertexToAdd = new VertexPositionColor(currPosition, currColor); combinedPart.Vertices.Add(ToVertexType(vertexToAdd)); break; } case VertexTypes.VertexPositionNormalTexture: { // get normal Vector3 normal = new Vector3(vertexData[i + 3], vertexData[i + 4], vertexData[i + 5]); normal = Vector3.Normalize(Vector3.TransformNormal(normal, transform)); // get texture coords Vector2 textcoords = new Vector2(vertexData[i + 6], vertexData[i + 7]); // add to buffer var vertexToAdd = new VertexPositionNormalTexture(currPosition, normal, textcoords); combinedPart.Vertices.Add(ToVertexType(vertexToAdd)); break; } case VertexTypes.VertexPositionNormalTangentTexture: { // get normal Vector3 normal = new Vector3(vertexData[i + 3], vertexData[i + 4], vertexData[i + 5]); normal = Vector3.Normalize(Vector3.TransformNormal(normal, transform)); // get tangent Vector3 tangent = new Vector3(vertexData[i + 6], vertexData[i + 7], vertexData[i + 8]); // get binormal Vector3 binormal = new Vector3(vertexData[i + 9], vertexData[i + 10], vertexData[i + 11]); // get texture coords Vector2 textcoords = new Vector2(vertexData[i + 12], vertexData[i + 13]); // add to buffer var vertexToAdd = new VertexPositionNormalTangentTexture(currPosition, normal, textcoords, tangent, binormal); combinedPart.Vertices.Add(ToVertexType(vertexToAdd)); break; } case VertexTypes.VertexPositionTexture: { // get texture coords Vector2 textcoords = new Vector2(vertexData[i + 3], vertexData[i + 4]); // add to buffer var vertexToAdd = new VertexPositionTexture(currPosition, textcoords); combinedPart.Vertices.Add(ToVertexType(vertexToAdd)); break; } default: throw new Exceptions.InternalError("Forgot to implement type support?"); } // add to temp list of all points and increase vertices count _allPoints.Add(currPosition); verticesInPart++; } // set indexes ushort[] drawOrder = new ushort[meshPart.IndexBuffer.IndexCount]; meshPart.IndexBuffer.GetData <ushort>(drawOrder); combinedPart.PushIndexes(drawOrder); // increase indexes offset combinedPart.IndexOffset += verticesInPart; // increase primitives count combinedPart.PrimitiveCount += meshPart.PrimitiveCount; } }