예제 #1
0
        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);
                }
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
                }
            }
        }
예제 #4
0
        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);
                }
            }
        }
예제 #5
0
        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);
                }
            }
        }