private void CollectMeshes(Node node) { var boneIndex = skeletonNodes[node]; var bone = model.Bones[boneIndex]; if (node.HasMeshes) { var mesh = new ModelData.Mesh { Name = bone.Name, ParentBoneIndex = bone.Index, MeshParts = new List <ModelData.MeshPart>() }; model.Meshes.Add(mesh); // Precalculate the number of vertices for bounding sphere calculation boundingPointCount = 0; for (int i = 0; i < node.MeshCount; i++) { var meshIndex = node.MeshIndices[i]; var meshPart = scene.Meshes[meshIndex]; boundingPointCount += meshPart.VertexCount; } // Reallocate the buffer if needed if (boundingPoints == null || boundingPoints.Length < boundingPointCount) { boundingPoints = new Vector3[boundingPointCount]; } currentBoundingPointIndex = 0; for (int i = 0; i < node.MeshCount; i++) { var meshIndex = node.MeshIndices[i]; var meshPart = Process(mesh, scene.Meshes[meshIndex], node); var meshToPartList = registeredMeshParts[meshIndex]; if (meshToPartList == null) { meshToPartList = new List <ModelData.MeshPart>(); registeredMeshParts[meshIndex] = meshToPartList; } meshToPartList.Add(meshPart); mesh.MeshParts.Add(meshPart); } // Calculate the bounding sphere. BoundingSphere.FromPoints(boundingPoints, 0, boundingPointCount, out mesh.BoundingSphere); } // continue for all child nodes if (node.HasChildren) { foreach (var subNode in node.Children) { CollectMeshes(subNode); } } }
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 void CollectNodes(Node node, ModelData.Bone targetParent) { bool isModelNode = IsModelNode(node); if (!isModelNode) { return; } var parent = new ModelData.Bone { Index = model.Bones.Count, Name = node.Name, ParentIndex = targetParent == null ? -1 : targetParent.Index, Transform = ConvertMatrix(node.Transform), Children = new List <int>() }; if (targetParent != null && targetParent.Children != null) { targetParent.Children.Add(parent.Index); } // Associate created bones with local index meshNodes[node] = model.Bones.Count; model.Bones.Add(parent); // if node has meshes, create a new scene object for it if (node.MeshCount > 0) { var mesh = new ModelData.Mesh { Name = parent.Name, ParentBoneIndex = parent.Index, MeshParts = new List <ModelData.MeshPart>() }; model.Meshes.Add(mesh); // Precalculate the number of vertices for bounding sphere calculation boundingPointCount = 0; for (int i = 0; i < node.MeshCount; i++) { var meshIndex = node.MeshIndices[i]; var meshPart = scene.Meshes[meshIndex]; boundingPointCount += meshPart.VertexCount; } // Reallocate the buffer if needed if (boundingPoints == null || boundingPoints.Length < boundingPointCount) { boundingPoints = new Vector3[boundingPointCount]; } currentBoundingPointIndex = 0; for (int i = 0; i < node.MeshCount; i++) { var meshIndex = node.MeshIndices[i]; var meshPart = Process(mesh, scene.Meshes[meshIndex]); var meshToPartList = registeredMeshParts[meshIndex]; if (meshToPartList == null) { meshToPartList = new List <ModelData.MeshPart>(); registeredMeshParts[meshIndex] = meshToPartList; } meshToPartList.Add(meshPart); mesh.MeshParts.Add(meshPart); } // Calculate the bounding sphere. BoundingSphere.FromPoints(boundingPoints, 0, boundingPointCount, out mesh.BoundingSphere); } // continue for all child nodes if (node.HasChildren) { foreach (var subNode in node.Children) { CollectNodes(subNode, parent); } } }
private void CollectNodes(Node node, ModelData.Bone targetParent) { bool isModelNode = IsModelNode(node); if (!isModelNode) { return; } var parent = new ModelData.Bone { Index = model.Bones.Count, Name = node.Name, ParentIndex = targetParent == null ? -1 : targetParent.Index, Transform = ConvertMatrix(node.Transform), Children = new List<int>() }; if (targetParent!= null && targetParent.Children != null) { targetParent.Children.Add(parent.Index); } // Associate created bones with local index meshNodes[node] = model.Bones.Count; model.Bones.Add(parent); // if node has meshes, create a new scene object for it if( node.MeshCount > 0) { var mesh = new ModelData.Mesh { Name = parent.Name, ParentBoneIndex = parent.Index, MeshParts = new List<ModelData.MeshPart>() }; model.Meshes.Add(mesh); // Precalculate the number of vertices for bounding sphere calculation boundingPointCount = 0; for (int i = 0; i < node.MeshCount; i++) { var meshIndex = node.MeshIndices[i]; var meshPart = scene.Meshes[meshIndex]; boundingPointCount += meshPart.VertexCount; } // Reallocate the buffer if needed if (boundingPoints == null || boundingPoints.Length < boundingPointCount) { boundingPoints = new Vector3[boundingPointCount]; } currentBoundingPointIndex = 0; for (int i = 0; i < node.MeshCount; i++) { var meshIndex = node.MeshIndices[i]; var meshPart = Process(mesh, scene.Meshes[meshIndex]); var meshToPartList = registeredMeshParts[meshIndex]; if (meshToPartList == null) { meshToPartList = new List<ModelData.MeshPart>(); registeredMeshParts[meshIndex] = meshToPartList; } meshToPartList.Add(meshPart); mesh.MeshParts.Add(meshPart); } // Calculate the bounding sphere. BoundingSphere.FromPoints(boundingPoints, 0, boundingPointCount, out mesh.BoundingSphere); } // continue for all child nodes if (node.HasChildren) { foreach (var subNode in node.Children) { CollectNodes(subNode, parent); } } }
private void CollectMeshes(Node node) { var boneIndex = skeletonNodes[node]; var bone = model.Bones[boneIndex]; if (node.HasMeshes) { var mesh = new ModelData.Mesh { Name = bone.Name, ParentBoneIndex = bone.Index, MeshParts = new List<ModelData.MeshPart>() }; model.Meshes.Add(mesh); // Precalculate the number of vertices for bounding sphere calculation boundingPointCount = 0; for (int i = 0; i < node.MeshCount; i++) { var meshIndex = node.MeshIndices[i]; var meshPart = scene.Meshes[meshIndex]; boundingPointCount += meshPart.VertexCount; } // Reallocate the buffer if needed if (boundingPoints == null || boundingPoints.Length < boundingPointCount) { boundingPoints = new Vector3[boundingPointCount]; } currentBoundingPointIndex = 0; for (int i = 0; i < node.MeshCount; i++) { var meshIndex = node.MeshIndices[i]; var meshPart = Process(mesh, scene.Meshes[meshIndex], node); var meshToPartList = registeredMeshParts[meshIndex]; if (meshToPartList == null) { meshToPartList = new List<ModelData.MeshPart>(); registeredMeshParts[meshIndex] = meshToPartList; } meshToPartList.Add(meshPart); mesh.MeshParts.Add(meshPart); } // Calculate the bounding sphere. BoundingSphere.FromPoints(boundingPoints, 0, boundingPointCount, out mesh.BoundingSphere); } // continue for all child nodes if (node.HasChildren) { foreach (var subNode in node.Children) { CollectMeshes(subNode); } } }