void TestMesh(Assimp.Mesh netMesh, AssimpSharp.Mesh sharpMesh) { // Vertices Assert.AreEqual(netMesh.HasVertices, sharpMesh.Vertices != null); if (netMesh.HasVertices) { Assert.AreEqual(netMesh.VertexCount, sharpMesh.Vertices.Length); MathAssert.AreEqual(netMesh.Vertices, sharpMesh.Vertices); } // Faces Assert.AreEqual(netMesh.HasFaces, sharpMesh.Faces != null); if (netMesh.HasFaces) { Assert.AreEqual(netMesh.FaceCount, sharpMesh.Faces.Length); for (int i = 0; i < netMesh.FaceCount; i++) { Assert.AreEqual(netMesh.Faces[i].HasIndices, sharpMesh.Faces[i].Indices != null); Assert.AreEqual(netMesh.Faces[i].IndexCount, sharpMesh.Faces[i].Indices.Length); Assert.AreEqual(netMesh.Faces[i].Indices, sharpMesh.Faces[i].Indices); } } // Normals Assert.AreEqual(netMesh.HasNormals, sharpMesh.Normals != null); if (netMesh.HasNormals) { MathAssert.AreEqual(netMesh.Normals, sharpMesh.Normals); } // BiTangents Assert.AreEqual(netMesh.HasTangentBasis, sharpMesh.Bitangents != null && sharpMesh.Bitangents.Length > 0); if (netMesh.HasTangentBasis) { MathAssert.AreEqual(netMesh.BiTangents, sharpMesh.Bitangents); } // PrimitiveType // AssimpNet BUG!! //Assert.AreEqual(netMesh.PrimitiveType.ToString(), Enum.GetName(typeof(AssimpSharp.PrimitiveType), sharpMesh.PrimitiveTypes)); // TexureCoord for (int i = 0; i < netMesh.TextureCoordinateChannelCount; i++) { Assert.AreEqual(netMesh.HasTextureCoords(i), sharpMesh.HasTextureCoords(i)); MathAssert.AreEqual(netMesh.TextureCoordinateChannels[i], sharpMesh.TextureCoords[i]); } // VertexColorChannels for (int i = 0; i < netMesh.VertexColorChannelCount; i++) { Assert.AreEqual(netMesh.HasVertexColors(i), sharpMesh.HasVertexColors(i)); if (netMesh.HasVertexColors(i)) { Assert.AreEqual(netMesh.VertexColorChannels[i], sharpMesh.Colors[i]); } } // MaterialIndex Assert.AreEqual(netMesh.MaterialIndex, sharpMesh.MaterialIndex); // Name Assert.AreEqual(netMesh.Name, sharpMesh.Name); // UVComponentCount Assert.AreEqual(netMesh.UVComponentCount, sharpMesh.NumUVComponents); // MeshAnimationAttachments Assert.AreEqual(netMesh.HasMeshAnimationAttachments, sharpMesh.AnimMeshes != null); if (netMesh.HasMeshAnimationAttachments) { for (int i = 0; i < netMesh.MeshAnimationAttachmentCount; i++) { TestAnimationAttachment(netMesh.MeshAnimationAttachments[i], sharpMesh.AnimMeshes[i]); } } }
void TestAnimationAttachment(Assimp.MeshAnimationAttachment netAnimMesh, AssimpSharp.AnimMesh sharpAnimMesh) { Assert.AreEqual(netAnimMesh.HasVertices, sharpAnimMesh.HasPosition); if (netAnimMesh.HasVertices) { Assert.AreEqual(netAnimMesh.Vertices, sharpAnimMesh.Vertices); } Assert.AreEqual(netAnimMesh.HasNormals, sharpAnimMesh.HasNormals); if (netAnimMesh.HasNormals) { Assert.AreEqual(netAnimMesh.Normals, sharpAnimMesh.Normals); } Assert.AreEqual(netAnimMesh.HasTangentBasis, sharpAnimMesh.HasTangentsAndBitangets); if (netAnimMesh.HasTangentBasis) { Assert.AreEqual(netAnimMesh.Tangents, sharpAnimMesh.Tangents); Assert.AreEqual(netAnimMesh.BiTangents, sharpAnimMesh.Bitangents); } for (int i = 0; i < netAnimMesh.TextureCoordinateChannelCount; i++) { Assert.AreEqual(netAnimMesh.HasTextureCoords(i), sharpAnimMesh.HasTextureCoords(i)); if (netAnimMesh.HasTextureCoords(i)) { Assert.AreEqual(netAnimMesh.TextureCoordinateChannels[i], sharpAnimMesh.TextureCoords[i]); } } for (int i = 0; i < netAnimMesh.VertexColorChannelCount; i++) { Assert.AreEqual(netAnimMesh.HasVertexColors(i), sharpAnimMesh.HasVertexColors(i)); if (netAnimMesh.HasVertexColors(i)) { Assert.AreEqual(netAnimMesh.VertexColorChannels[i], sharpAnimMesh.Colors[i]); } } }
private ModelData.MeshPart Process(ModelData.Mesh mesh, Assimp.Mesh assimpMesh) { var meshPart = new ModelData.MeshPart() { MaterialIndex = assimpMesh.MaterialIndex, VertexBufferRange = new ModelData.BufferRange() { Slot = mesh.VertexBuffers.Count }, IndexBufferRange = new ModelData.BufferRange() { Slot = mesh.IndexBuffers.Count } }; var vertexBuffer = new ModelData.VertexBuffer() { Layout = new List<VertexElement>() }; mesh.VertexBuffers.Add(vertexBuffer); var indexBuffer = new ModelData.IndexBuffer(); mesh.IndexBuffers.Add(indexBuffer); var layout = vertexBuffer.Layout; int vertexBufferElementSize = 0; // Add position layout.Add(VertexElement.PositionTransformed(Format.R32G32B32_Float, 0)); vertexBufferElementSize += Utilities.SizeOf<SharpDX.Vector3>(); // Add normals if (assimpMesh.HasNormals) { layout.Add(VertexElement.Normal(0, Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf<SharpDX.Vector3>(); } // Add colors if (assimpMesh.VertexColorChannelCount > 0) { for (int localIndex = 0, i = 0; i < assimpMesh.VertexColorChannelCount; i++) { if (assimpMesh.HasVertexColors(i)) { layout.Add(VertexElement.Color(localIndex, Format.R32G32B32A32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf<SharpDX.Color4>(); localIndex++; } } } // Add textures if (assimpMesh.TextureCoordsChannelCount > 0) { for (int localIndex = 0, i = 0; i < assimpMesh.TextureCoordsChannelCount; i++) { if (assimpMesh.HasTextureCoords(i)) { var uvCount = assimpMesh.GetUVComponentCount(i); if (uvCount == 2) { layout.Add(VertexElement.TextureCoordinate(localIndex, Format.R32G32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf<SharpDX.Vector2>(); } else if (uvCount == 3) { layout.Add(VertexElement.TextureCoordinate(localIndex, Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf<SharpDX.Vector3>(); } else { throw new InvalidOperationException("Unexpected uv count"); } localIndex++; } } } // Add tangent / bitangent if (assimpMesh.HasTangentBasis) { layout.Add(VertexElement.Tangent(Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf<SharpDX.Vector3>(); layout.Add(VertexElement.BiTangent(Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf<SharpDX.Vector3>(); } // Extract Skinning Indices / Weights bool hasWeights = false; var skinningCount = new int[assimpMesh.VertexCount]; var skinningIndices = new Int4[assimpMesh.VertexCount]; var skinningWeights = new Vector4[assimpMesh.VertexCount]; if (assimpMesh.HasBones) { meshPart.BoneOffsetMatrices = new Matrix[assimpMesh.BoneCount]; for (int i = 0; i < assimpMesh.Bones.Length; i++) { var bone = assimpMesh.Bones[i]; meshPart.BoneOffsetMatrices[i] = ConvertMatrix(bone.OffsetMatrix); if (bone.HasVertexWeights) { var boneNode = scene.RootNode.FindNode(bone.Name); var boneIndex = skinnedBones[boneNode]; for (int j = 0; j < bone.VertexWeightCount; j++) { var weights = bone.VertexWeights[j]; var vertexSkinningCount = skinningCount[weights.VertexID]; skinningIndices[weights.VertexID][vertexSkinningCount] = boneIndex; skinningWeights[weights.VertexID][vertexSkinningCount] = weights.Weight; skinningCount[weights.VertexID] = ++vertexSkinningCount; } hasWeights = true; } } if (hasWeights) { layout.Add(VertexElement.BlendIndices(Format.R16G16B16A16_SInt, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf<SharpDX.Int4>(); layout.Add(VertexElement.BlendWeights(Format.R32G32B32A32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf<SharpDX.Vector4>(); } } // Write all vertices meshPart.VertexBufferRange.Count = assimpMesh.VertexCount; vertexBuffer.Count = assimpMesh.VertexCount; vertexBuffer.Buffer = new byte[vertexBufferElementSize * assimpMesh.VertexCount]; // Update the MaximumBufferSizeInBytes needed to load this model if (vertexBuffer.Buffer.Length > model.MaximumBufferSizeInBytes) { model.MaximumBufferSizeInBytes = vertexBuffer.Buffer.Length; } var vertexStream = DataStream.Create(vertexBuffer.Buffer, true, true); for (int i = 0; i < assimpMesh.VertexCount; i++) { var position = assimpMesh.Vertices[i]; vertexStream.Write(position); // Store bounding points for BoundingSphere pre-calculation boundingPoints[currentBoundingPointIndex++] = new Vector3(position.X, position.Y, position.Z); // Add normals if (assimpMesh.HasNormals) { vertexStream.Write(assimpMesh.Normals[i]); } // Add colors if (assimpMesh.VertexColorChannelCount > 0) { for (int j = 0; j < assimpMesh.VertexColorChannelCount; j++) { if (assimpMesh.HasVertexColors(j)) { vertexStream.Write(assimpMesh.GetVertexColors(j)[i]); } } } // Add textures if (assimpMesh.TextureCoordsChannelCount > 0) { for (int j = 0; j < assimpMesh.TextureCoordsChannelCount; j++) { if (assimpMesh.HasTextureCoords(j)) { var uvCount = assimpMesh.GetUVComponentCount(j); var uv = assimpMesh.GetTextureCoords(j)[i]; if (uvCount == 2) { vertexStream.Write(new Vector2(uv.X, uv.Y)); } else { vertexStream.Write(uv); } } } } // Add tangent / bitangent if (assimpMesh.HasTangentBasis) { vertexStream.Write(assimpMesh.Tangents[i]); vertexStream.Write(assimpMesh.BiTangents[i]); } // Add Skinning Indices/Weights if (assimpMesh.HasBones && hasWeights) { vertexStream.Write(skinningIndices[i]); vertexStream.Write(skinningWeights[i]); } } vertexStream.Dispose(); // Write all indices var indices = assimpMesh.GetIntIndices(); indexBuffer.Count = indices.Length; meshPart.IndexBufferRange.Count = indices.Length; if (meshPart.VertexBufferRange.Count < 65536) { // Write only short indices if count is less than the size of a short indexBuffer.Buffer = new byte[indices.Length * 2]; using (var indexStream = DataStream.Create(indexBuffer.Buffer, true, true)) foreach (int index in indices) indexStream.Write((ushort)index); } else { // Otherwise, use full 32-bit precision to store indices indexBuffer.Buffer = new byte[indices.Length * 4]; using (var indexStream = DataStream.Create(indexBuffer.Buffer, true, true)) indexStream.WriteRange(indices); } // Update the MaximumBufferSizeInBytes needed to load this model if (indexBuffer.Buffer.Length > model.MaximumBufferSizeInBytes) { model.MaximumBufferSizeInBytes = indexBuffer.Buffer.Length; } return meshPart; }
//determine the number of elements in the vertex private int GetNoofInputElements(Assimp.Mesh mesh) { bool hasTexCoords = mesh.HasTextureCoords(0); bool hasColors = mesh.HasVertexColors(0); bool hasNormals = mesh.HasNormals; bool hasTangents = mesh.Tangents != null; bool hasBitangents = mesh.BiTangents != null; int noofElements = 1; if (hasColors) noofElements++; if (hasNormals) noofElements++; if (hasTangents) noofElements++; if (hasBitangents) noofElements++; if (hasTexCoords) noofElements++; return noofElements; }
public Hatzap.Models.Mesh FromAssimp(Assimp.Mesh amesh) { var mesh = new Hatzap.Models.Mesh(); var v = amesh.Vertices; var n = amesh.Normals; var t = amesh.Tangents; var b = amesh.BiTangents; var tc = amesh.TextureCoordinateChannels; var c = amesh.VertexColorChannels; var verts = new Vector3[v.Count]; Vector3[] norms; Vector3[] tangents; Vector3[] binormals; Vector3[][] uv; Vector4[][] colors; if (amesh.HasNormals) norms = new Vector3[v.Count]; else norms = null; if (amesh.HasTangentBasis) tangents = new Vector3[v.Count]; else tangents = null; if (amesh.HasTangentBasis) binormals = new Vector3[v.Count]; else binormals = null; if (amesh.HasTextureCoords(0)) { uv = new Vector3[amesh.TextureCoordinateChannelCount][]; for(int i = 0; i < amesh.TextureCoordinateChannelCount; i++) { uv[i] = new Vector3[v.Count]; } } else { uv = null; } if (amesh.HasVertexColors(0)) { colors = new Vector4[amesh.VertexColorChannelCount][]; for (int i = 0; i < amesh.VertexColorChannelCount; i++) { colors[i] = new Vector4[v.Count]; } } else { colors = new Vector4[1][]; colors[0] = new Vector4[v.Count]; } for (int i = 0; i < v.Count; i++) { verts[i] = new Vector3(v[i].X, v[i].Y, v[i].Z); if (norms != null) norms[i] = new Vector3(n[i].X, n[i].Y, n[i].Z); if (tangents != null) tangents[i] = new Vector3(t[i].X, t[i].Y, t[i].Z); if (binormals != null) binormals[i] = new Vector3(b[i].X, b[i].Y, b[i].Z); if (uv != null) { for(int j = 0; j < amesh.TextureCoordinateChannelCount; j++) { uv[j][i] = new Vector3(tc[j][i].X, tc[j][i].Y, tc[j][i].Z); } } if (colors != null) { if (amesh.HasVertexColors(0)) { for (int j = 0; j < amesh.VertexColorChannelCount; j++) { colors[j][i] = new Vector4(c[j][i].R, c[j][i].G, c[j][i].B, c[j][i].A); } } else { colors[0][i] = new Vector4(1, 1, 1, 1); } } } mesh.Vertices = verts; mesh.Normals = norms; mesh.Tangents = tangents; mesh.Binormals = binormals; mesh.UV = uv; mesh.Colors = colors; var aindices = amesh.GetIndices(); var indices = new uint[aindices.Length]; for (int i = 0; i < aindices.Length; i++) { indices[i] = (uint)aindices[i]; } mesh.Indices = indices; return mesh; }