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); }
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; }