HasVertexColors() public method

Checks if the mesh has vertex colors for the specified channel. This returns false if the list is null or empty. The channel, if it exists, should contain the same number of entries as VertexCount.
public HasVertexColors ( int channelIndex ) : bool
channelIndex int Channel index
return bool
        /// <summary>
        /// Gets vertex data from a given <see cref="AssimpMesh"/>.
        /// </summary>
        /// <param name="sceneMesh">The <see cref="AssimpMesh"/> to get vertex information from.</param>
        /// <param name="boneIndexByName">A lookup of bone index by name information.</param>
        /// <returns>An output list of vertices.</returns>
        private Vertex[] GetMeshVertices(AssimpMesh sceneMesh, Dictionary <string, uint> boneIndexByName)
        {
            var positions                = sceneMesh.Vertices;
            var normals                  = sceneMesh.Normals;
            var tangents                 = sceneMesh.Tangents;
            var colors                   = sceneMesh.HasVertexColors(0) ? sceneMesh.VertexColorChannels[0] : null;
            var textureCoordinates       = sceneMesh.HasTextureCoords(0) ? sceneMesh.TextureCoordinateChannels[0] : null;
            var boneWeightsByVertexIndex = GetBoneWeightsByVertexIndex(boneIndexByName, sceneMesh);

            var vertices = new List <Vertex>();

            for (var i = 0; i < positions.Count; i++)
            {
                var position          = positions[i];
                var normal            = normals[i];
                var tangent           = tangents[i];
                var color             = colors?[i];
                var textureCoordinate = textureCoordinates?[i];
                TryGetBoneIndicesAndWeights(boneWeightsByVertexIndex, i, out var boneIndices, out var boneWeights);

                vertices.Add(new Vertex(new Vector3(position.X, position.Y, position.Z),
                                        new Vector3(normal.X, normal.Y, normal.Z),
                                        new Vector3(tangent.X, tangent.Y, tangent.Z),
                                        color != null ? new Color(color.Value.R, color.Value.G, color.Value.B, color.Value.A) : new Color(1.0f, 1.0f, 1.0f, 1.0f),
                                        textureCoordinate != null ? new Vector2(textureCoordinate.Value.X, textureCoordinate.Value.Y) : Vector2.Zero,
                                        new ReadOnlyCollection <uint>(boneIndices),
                                        new ReadOnlyCollection <float>(boneWeights)));
            }

            return(vertices.ToArray());
        }
Beispiel #2
0
 IEnumerable <AssimpVertex> GetVertex(Assimp.Mesh m)
 {
     for (int i = 0; i < m.VertexCount; ++i)
     {
         Vector3 cc = m.Vertices[i].ToVector3();
         var     bw = GetWAndB(m, i);
         yield return(new AssimpVertex()
         {
             position = cc,
             uv = m.HasTextureCoords(0) ? m.TextureCoordinateChannels[0][i].ToVector3() : new Vector3(),
             tangent = m.HasTangentBasis ? m.Tangents[i].ToVector3() : new Vector3(),
             biTangent = m.HasTangentBasis ? m.BiTangents[i].ToVector3() : new Vector3(),
             normal = m.HasNormals ? m.Normals[i].ToVector3() : new Vector3(),
             BoneID = HasAnimation && m.HasBones ? GetBoneID(bw) : new Vector4(),
             BoneWheight = HasAnimation && m.HasBones ? GetWheight(bw) : new Vector4(),
             Color = m.HasVertexColors(0) ? m.VertexColorChannels[0][i].ToColor4() : new Color4(0.5f, 0.5f, 0.5f, 1)
         });
     }
     yield break;
 }
Beispiel #3
0
        //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 && mesh.Tangents.Count > 0;
            bool hasBitangents = mesh.BiTangents != null && mesh.BiTangents.Count > 0;

            int noofElements = 1;

            if (hasColors)
            {
                noofElements++;
            }

            if (hasNormals)
            {
                noofElements++;
            }

            if (hasTangents)
            {
                noofElements++;
            }

            if (hasBitangents)
            {
                noofElements++;
            }

            if (hasTexCoords)
            {
                noofElements++;
            }

            return(noofElements);
        }
        public void SetMesh(MainWindow host, Mesh mesh, string meshName) 
        {
            Debug.Assert(mesh != null);
            Debug.Assert(host != null);
            Debug.Assert(meshName != null);

            _mesh = mesh;
            _host = host;

            labelVertexCount.Text = mesh.VertexCount + " Vertices";
            labelFaceCount.Text = mesh.FaceCount + " Faces";
            Text = meshName + " - Details";

            checkedListBoxPerFace.CheckOnClick = false;
            checkedListBoxPerFace.SetItemCheckState(0,
                mesh.PrimitiveType.HasFlag(PrimitiveType.Triangle)
                ? CheckState.Checked
                : CheckState.Unchecked);

            checkedListBoxPerFace.SetItemCheckState(1,
                mesh.PrimitiveType.HasFlag(PrimitiveType.Line)
                ? CheckState.Checked
                : CheckState.Unchecked);

            checkedListBoxPerFace.SetItemCheckState(2,
                mesh.PrimitiveType.HasFlag(PrimitiveType.Point)
                ? CheckState.Checked
                : CheckState.Unchecked);

            checkedListBoxPerVertex.CheckOnClick = false;
            checkedListBoxPerVertex.SetItemCheckState(0, CheckState.Checked);
            checkedListBoxPerVertex.SetItemCheckState(1, mesh.HasNormals
                ? CheckState.Checked
                : CheckState.Unchecked);
            checkedListBoxPerVertex.SetItemCheckState(2, mesh.HasTangentBasis
                ? CheckState.Checked
                : CheckState.Unchecked);

            Debug.Assert(mesh.TextureCoordinateChannels.Length >= 4);
            for (var i = 0; i < 4; ++i)
            {
                checkedListBoxPerVertex.SetItemCheckState(3 + i, mesh.HasTextureCoords(i)
                    ? CheckState.Checked
                    : CheckState.Unchecked);
            }

            Debug.Assert(mesh.VertexColorChannels.Length >= 4);
            for (var i = 0; i < 4; ++i)
            {
                checkedListBoxPerVertex.SetItemCheckState(7 + i, mesh.HasVertexColors(i)
                    ? CheckState.Checked
                    : CheckState.Unchecked);
            }

            checkedListBoxPerVertex.SetItemCheckState(11, mesh.HasBones
                ? CheckState.Checked
                : CheckState.Unchecked);
        }
Beispiel #5
0
        //Create meshes and add vertex and index buffers
        private void AddVertexData(Model model, Scene scene, Node node, Device device, ref Matrix transform)
        {
            Matrix previousTransform = transform;

            transform = Matrix.Multiply(previousTransform, FromMatrix(node.Transform));

            //also calculate inverse transpose matrix for normal/tangent/bitagent transformation
            Matrix invTranspose = transform;

            invTranspose.Invert();
            invTranspose.Transpose();

            if (node.HasMeshes)
            {
                foreach (int index in node.MeshIndices)
                {
                    //get a mesh from the scene
                    Assimp.Mesh mesh = scene.Meshes[index];

                    //create new mesh to add to model
                    ModelMesh modelMesh = new ModelMesh();
                    model.AddMesh(ref modelMesh);

                    //if mesh has a material extract the diffuse texture, if present
                    Material material = scene.Materials[mesh.MaterialIndex];
                    if (material != null && material.GetMaterialTextureCount(TextureType.Diffuse) > 0)
                    {
                        material.GetMaterialTexture(TextureType.Diffuse, 0, out TextureSlot texture);
                        //create new texture for mesh
                        modelMesh.AddTextureDiffuse(device, m_modelPath + "\\" + texture.FilePath);
                    }

                    //determine the elements in the vertex
                    bool hasTexCoords  = mesh.HasTextureCoords(0);
                    bool hasColors     = mesh.HasVertexColors(0);
                    bool hasNormals    = mesh.HasNormals;
                    bool hasTangents   = mesh.Tangents != null && mesh.Tangents.Count > 0;
                    bool hasBitangents = mesh.BiTangents != null && mesh.BiTangents.Count > 0;

                    //create vertex element list
                    InputElement[] vertexElements = new InputElement[GetNoofInputElements(mesh)];
                    uint           elementIndex   = 0;
                    vertexElements[elementIndex++] = new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0);
                    short vertexSize = (short)Utilities.SizeOf <Vector3>();

                    if (hasColors)
                    {
                        vertexElements[elementIndex++] = new InputElement("COLOR", 0, Format.R8G8B8A8_UInt, vertexSize, 0);
                        vertexSize += (short)Utilities.SizeOf <Color>();
                    }
                    if (hasNormals)
                    {
                        vertexElements[elementIndex++] = new InputElement("NORMAL", 0, Format.R32G32B32_Float, vertexSize, 0);
                        vertexSize += (short)Utilities.SizeOf <Vector3>();
                    }
                    if (hasTangents)
                    {
                        vertexElements[elementIndex++] = new InputElement("TANGENT", 0, Format.R32G32B32_Float, vertexSize, 0);
                        vertexSize += (short)Utilities.SizeOf <Vector3>();
                    }
                    if (hasBitangents)
                    {
                        vertexElements[elementIndex++] = new InputElement("BITANGENT", 0, Format.R32G32B32_Float, vertexSize, 0);
                        vertexSize += (short)Utilities.SizeOf <Vector3>();
                    }
                    if (hasTexCoords)
                    {
                        vertexElements[elementIndex++] = new InputElement("TEXCOORD", 0, Format.R32G32_Float, vertexSize, 0);
                        vertexSize += (short)Utilities.SizeOf <Vector2>();
                    }

                    //set the vertex elements and size
                    modelMesh.InputElements = vertexElements;
                    modelMesh.VertexSize    = vertexSize;

                    //get pointers to vertex data
                    var positions  = mesh.Vertices;
                    var texCoords  = mesh.TextureCoordinateChannels[0];
                    var normals    = mesh.Normals;
                    var tangents   = mesh.Tangents;
                    var biTangents = mesh.BiTangents;
                    var colours    = mesh.VertexColorChannels[0];

                    //also determine primitive type
                    switch (mesh.PrimitiveType)
                    {
                    case PrimitiveType.Point:
                        modelMesh.PrimitiveTopology = PrimitiveTopology.PointList;
                        break;

                    case PrimitiveType.Line:
                        modelMesh.PrimitiveTopology = PrimitiveTopology.LineList;
                        break;

                    case PrimitiveType.Triangle:
                        modelMesh.PrimitiveTopology = PrimitiveTopology.TriangleList;
                        break;

                    default:
                        throw new Exception("ModelLoader::AddVertexData(): Unknown primitive type");
                    }

                    //create data stream for vertices
                    DataStream vertexStream = new DataStream(mesh.VertexCount * vertexSize, true, true);

                    for (int i = 0; i < mesh.VertexCount; i++)
                    {
                        //add position, after transforming it with accumulated node transform
                        {
                            Vector4 result;
                            Vector3 pos = FromVector(positions[i]);
                            Vector3.Transform(ref pos, ref transform, out result);
                            vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z));
                        }

                        if (hasColors)
                        {
                            Color vertColor = FromColor(mesh.VertexColorChannels[0][i]);
                            vertexStream.Write <Color>(vertColor);
                        }
                        if (hasNormals)
                        {
                            Vector4 result;
                            Vector3 normal = FromVector(normals[i]);
                            Vector3.Transform(ref normal, ref invTranspose, out result);
                            vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z));
                        }
                        if (hasTangents)
                        {
                            Vector4 result;
                            Vector3 tangent = FromVector(tangents[i]);
                            Vector3.Transform(ref tangent, ref invTranspose, out result);
                            vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z));
                        }
                        if (hasBitangents)
                        {
                            Vector4 result;
                            Vector3 biTangent = FromVector(biTangents[i]);
                            Vector3.Transform(ref biTangent, ref invTranspose, out result);
                            vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z));
                        }
                        if (hasTexCoords)
                        {
                            vertexStream.Write <Vector2>(new Vector2(texCoords[i].X, 1 - texCoords[i].Y));
                        }
                    }

                    vertexStream.Position = 0;

                    //create new vertex buffer
                    var vertexBuffer = new Buffer(device,
                                                  vertexStream,
                                                  new BufferDescription()
                    {
                        BindFlags      = BindFlags.VertexBuffer,
                        CpuAccessFlags = CpuAccessFlags.None,
                        OptionFlags    = ResourceOptionFlags.None,
                        SizeInBytes    = mesh.VertexCount * vertexSize,
                        Usage          = ResourceUsage.Default
                    }
                                                  );

                    //add it to the mesh
                    modelMesh.VertexBuffer   = vertexBuffer;
                    modelMesh.VertexCount    = mesh.VertexCount;
                    modelMesh.PrimitiveCount = mesh.FaceCount;

                    //get pointer to indices data
                    uint[] indices = mesh.GetIndices().Select(i => (uint)i).ToArray();

                    //create data stream for indices
                    DataStream indexStream = new DataStream(indices.GetLength(0) * sizeof(uint), true, true);

                    for (int i = 0; i < indices.GetLength(0); i++)
                    {
                        indexStream.Write <uint>(indices[i]);
                    }

                    indexStream.Position = 0;

                    //create new index buffer
                    var indexBuffer = new Buffer(device,
                                                 indexStream,
                                                 new BufferDescription()
                    {
                        BindFlags      = BindFlags.IndexBuffer,
                        CpuAccessFlags = CpuAccessFlags.None,
                        OptionFlags    = ResourceOptionFlags.None,
                        SizeInBytes    = indices.GetLength(0) * sizeof(uint),
                        Usage          = ResourceUsage.Default
                    }
                                                 );

                    //add it to the mesh
                    modelMesh.IndexBuffer = indexBuffer;
                    modelMesh.IndexCount  = indices.GetLength(0);
                }
            }

            //if node has more children process them as well
            for (int i = 0; i < node.ChildCount; i++)
            {
                AddVertexData(model, scene, node.Children[i], device, ref transform);
            }

            transform = previousTransform;
        }
        /// <summary>
        /// Draw a mesh using either its given material or a transparent "ghost" material.
        /// </summary>
        /// <param name="node">Current node</param>
        /// <param name="animated">Specifies whether animations should be played</param>
        /// <param name="showGhost">Indicates whether to substitute the mesh' material with a
        /// "ghost" surrogate material that allows looking through the geometry.</param>
        /// <param name="index">Mesh index in the scene</param>
        /// <param name="mesh">Mesh instance</param>
        /// <param name="flags"> </param>
        /// <returns></returns>
        protected override bool InternDrawMesh(Node node, bool animated, bool showGhost, int index, Mesh mesh, RenderFlags flags)
        {
            if (showGhost)
            {
                Owner.MaterialMapper.ApplyGhostMaterial(mesh, Owner.Raw.Materials[mesh.MaterialIndex], 
                    flags.HasFlag(RenderFlags.Shaded));
            }
            else
            {
                Owner.MaterialMapper.ApplyMaterial(mesh, Owner.Raw.Materials[mesh.MaterialIndex], 
                    flags.HasFlag(RenderFlags.Textured), 
                    flags.HasFlag(RenderFlags.Shaded));
            }

            if (GraphicsSettings.Default.BackFaceCulling)
            {
                GL.FrontFace(FrontFaceDirection.Ccw);
                GL.CullFace(CullFaceMode.Back);
                GL.Enable(EnableCap.CullFace);
            }
            else
            {
                GL.Disable(EnableCap.CullFace);
            }

            var hasColors = mesh.HasVertexColors(0);
            var hasTexCoords = mesh.HasTextureCoords(0);

            var skinning = mesh.HasBones && animated;

            foreach (var face in mesh.Faces)
            {
                BeginMode faceMode;
                switch (face.IndexCount)
                {
                    case 1:
                        faceMode = BeginMode.Points;
                        break;
                    case 2:
                        faceMode = BeginMode.Lines;
                        break;
                    case 3:
                        faceMode = BeginMode.Triangles;
                        break;
                    default:
                        faceMode = BeginMode.Polygon;
                        break;
                }

                GL.Begin(faceMode);
                for (var i = 0; i < face.IndexCount; i++)
                {
                    var indice = face.Indices[i];
                    if (hasColors)
                    {
                        var vertColor = AssimpToOpenTk.FromColor(mesh.VertexColorChannels[0][indice]);
                        GL.Color4(vertColor);
                    }
                    if (mesh.HasNormals)
                    {
                        Vector3 normal;
                        if (skinning)
                        {
                            Skinner.GetTransformedVertexNormal(node, mesh, (uint)indice, out normal);
                        }
                        else
                        {
                            normal = AssimpToOpenTk.FromVector(mesh.Normals[indice]);
                        }

                        GL.Normal3(normal);
                    }
                    if (hasTexCoords)
                    {
                        var uvw = AssimpToOpenTk.FromVector(mesh.TextureCoordinateChannels[0][indice]);
                        GL.TexCoord2(uvw.X, 1 - uvw.Y);
                    }

                    Vector3 pos;
                    if (skinning)
                    {
                        Skinner.GetTransformedVertexPosition(node, mesh, (uint)indice, out pos);
                    }
                    else
                    {
                        pos = AssimpToOpenTk.FromVector(mesh.Vertices[indice]);
                    }
                    GL.Vertex3(pos);
                }
                GL.End();
            }
            GL.Disable(EnableCap.CullFace);
            return skinning;
        }
Beispiel #7
0
        /// <summary>
        /// Determine the number of elements in the vertex.
        /// </summary>
        private static int GetNumberOfInputElements(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;
        }
Beispiel #8
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);
        }
Beispiel #9
0
        private void LoadFromNode(Assimp.Scene _scene, Assimp.Node _node, GraphicsDevice _device, SharpDX.Toolkit.Content.ContentManager _content, Matrix _transform)
        {
            // Sum up transformations recursively
            _transform = FromMatrix(_node.Transform) * _transform;
            Matrix transformInvTr = Helpers.CreateInverseTranspose(ref _transform);

            // Recursive load from scene
            if (_node.HasChildren)
            {
                foreach (Assimp.Node node in _node.Children)
                {
                    LoadFromNode(_scene, node, _device, _content, _transform);
                }
            }

            if (_node.HasMeshes)
            {
                foreach (int meshIndex in _node.MeshIndices)
                {
                    Assimp.Mesh mesh      = _scene.Meshes[meshIndex];
                    ModelMesh   modelMesh = new ModelMesh();

                    // if mesh has a diffuse texture extract it
                    Assimp.Material material = _scene.Materials[mesh.MaterialIndex];
                    if (material != null && material.GetTextureCount(TextureType.Diffuse) > 0)
                    {
                        TextureSlot texture = material.GetTexture(TextureType.Diffuse, 0);
                        // Create new texture for mesh
                        var dxtexture = _content.Load <Texture2D>(texture.FilePath);
                        modelMesh.DiffuseTexture = dxtexture;
                    }

                    // Position is mandarory
                    if (!mesh.HasVertices)
                    {
                        throw new Exception("Model::Model(): Model has no vertices.");
                    }

                    // Determine the elements in the vertex
                    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  numElements   = 1 + (hasTexCoords ? 1 : 0) + (hasColors ? 1 : 0) + (hasNormals ? 1 : 0) + (hasTangents ? 1 : 0) + (hasBitangents ? 1 : 0);

                    // Create vertex element list: Here starts the section of creating SharpDX stuff
                    VertexElement[] vertexElements = new VertexElement[numElements];
                    uint            elementIndex   = 0;
                    vertexElements[elementIndex++] = new VertexElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0);
                    int vertexSize = Utilities.SizeOf <Vector3>();

                    if (hasColors)
                    {
                        vertexElements[elementIndex++] = new VertexElement("COLOR", 0, SharpDX.DXGI.Format.R8G8B8A8_UInt, vertexSize);
                        vertexSize += Utilities.SizeOf <Color>();
                    }
                    if (hasNormals)
                    {
                        vertexElements[elementIndex++] = new VertexElement("NORMAL", 0, SharpDX.DXGI.Format.R32G32B32_Float, vertexSize);
                        vertexSize += Utilities.SizeOf <Vector3>();
                    }
                    if (hasTangents)
                    {
                        vertexElements[elementIndex++] = new VertexElement("TANGENT", 0, SharpDX.DXGI.Format.R32G32B32_Float, vertexSize);
                        vertexSize += Utilities.SizeOf <Vector3>();
                    }
                    if (hasBitangents)
                    {
                        vertexElements[elementIndex++] = new VertexElement("BITANGENT", 0, SharpDX.DXGI.Format.R32G32B32_Float, vertexSize);
                        vertexSize += Utilities.SizeOf <Vector3>();
                    }
                    if (hasTexCoords)
                    {
                        vertexElements[elementIndex++] = new VertexElement("TEXCOORD", 0, SharpDX.DXGI.Format.R32G32_Float, vertexSize);
                        vertexSize += Utilities.SizeOf <Vector2>();
                    }

                    // Set the vertex elements and size
                    modelMesh.InputLayout = VertexInputLayout.New(VertexBufferLayout.New(0, vertexElements));
                    modelMesh.VertexSize  = vertexSize;

                    // Determine primitive type
                    switch (mesh.PrimitiveType)
                    {
                    case Assimp.PrimitiveType.Point:    modelMesh.PrimitiveTopology = SharpDX.Toolkit.Graphics.PrimitiveType.PointList;    break;

                    case Assimp.PrimitiveType.Line:     modelMesh.PrimitiveTopology = SharpDX.Toolkit.Graphics.PrimitiveType.LineList;     break;

                    case Assimp.PrimitiveType.Triangle: modelMesh.PrimitiveTopology = SharpDX.Toolkit.Graphics.PrimitiveType.TriangleList; break;

                    default:                            throw new Exception("Model::Model(): Unknown primitive type");
                    }

                    // Create data stream for vertices
                    //System.IO.MemoryStream vertexStream = new System.IO.MemoryStream(mesh.VertexCount * vertexSize);
                    DataStream vertexStream = new DataStream(mesh.VertexCount * vertexSize, true, true);

                    for (int i = 0; i < mesh.VertexCount; i++)
                    {
                        vertexStream.Write <Vector3>(Helpers.Transform(FromVector(mesh.Vertices[i]), ref _transform));
                        if (hasColors)
                        {
                            vertexStream.Write <Color>(FromColor(mesh.GetVertexColors(0)[i]));
                        }
                        if (hasNormals)
                        {
                            vertexStream.Write <Vector3>(Helpers.Transform(FromVector(mesh.Normals[i]), ref transformInvTr));
                        }
                        if (hasTangents)
                        {
                            vertexStream.Write <Vector3>(Helpers.Transform(FromVector(mesh.Tangents[i]), ref transformInvTr));
                        }
                        if (hasBitangents)
                        {
                            vertexStream.Write <Vector3>(Helpers.Transform(FromVector(mesh.BiTangents[i]), ref transformInvTr));
                        }
                        if (hasTexCoords)
                        {
                            vertexStream.Write <Vector2>(new Vector2(mesh.GetTextureCoords(0)[i].X, mesh.GetTextureCoords(0)[i].Y));
                        }
                    }

                    vertexStream.Position = 0;

                    // Create new vertex buffer
                    var vertexBuffer = SharpDX.Toolkit.Graphics.Buffer.Vertex.New(_device, vertexStream);

                    // Add it to the mesh
                    modelMesh.VertexBuffer   = vertexBuffer;
                    modelMesh.VertexCount    = mesh.VertexCount;
                    modelMesh.PrimitiveCount = mesh.FaceCount;

                    // Create new index buffer
                    var indexBuffer = SharpDX.Toolkit.Graphics.Buffer.Index.New(_device, mesh.GetIndices());

                    // Add it to the mesh
                    modelMesh.IndexBuffer = indexBuffer;
                    modelMesh.IndexCount  = mesh.GetIndices().GetLength(0);

                    m_meshes.Add(modelMesh);
                }
            }
        }
Beispiel #10
0
        private ModelData.MeshPart Process(ModelData.Mesh mesh, Mesh assimpMesh)
        {
            var meshPart = new ModelData.MeshPart
            {
                PrimitiveTopology = PrimitiveTopology.TriangleList,
                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 += SharpDX.Utilities.SizeOf <Vector3>();

            // Add normals
            if (assimpMesh.HasNormals)
            {
                layout.Add(VertexElement.Normal(0, Format.R32G32B32_Float, vertexBufferElementSize));
                vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector3>();
            }

            // Add colors
            if (assimpMesh.VertexColorChannelCount > 0)
            {
                for (int localIndex = 0, i = 0; i < assimpMesh.VertexColorChannelCount; i++)
                {
                    if (assimpMesh.HasVertexColors(i))
                    {
                        layout.Add(VertexElement.Normal(localIndex, Format.R32G32B32A32_Float, vertexBufferElementSize));
                        vertexBufferElementSize += SharpDX.Utilities.SizeOf <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 += SharpDX.Utilities.SizeOf <Vector2>();
                        }
                        else if (uvCount == 3)
                        {
                            layout.Add(VertexElement.TextureCoordinate(localIndex, Format.R32G32B32_Float, vertexBufferElementSize));
                            vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector3>();
                        }
                        else
                        {
                            throw new InvalidOperationException("Unexpected uv count");
                        }

                        localIndex++;
                    }
                }
            }

            if (options.ModelOperations.HasFlag(ModelOperation.CalculateBarycentricCoordinates))
            {
                layout.Add(new VertexElement("BARYCENTRIC", 0, Format.R32G32B32_Float, vertexBufferElementSize));
                vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector3>();
            }
            else
            // Add tangent / bitangent
            if (assimpMesh.HasTangentBasis)
            {
                if (!options.ExcludeElements.Contains("Tangent"))
                {
                    layout.Add(VertexElement.Tangent(Format.R32G32B32A32_Float, vertexBufferElementSize));
                    vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector4>();
                }

                if (!options.ExcludeElements.Contains("BiTangent"))
                {
                    layout.Add(VertexElement.BiTangent(Format.R32G32B32_Float, vertexBufferElementSize));
                    vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector3>();
                }
            }

            if (options.ModelOperations.HasFlag(ModelOperation.CalculateBarycentricCoordinates))
            {
                WriteBarycentricVertices(assimpMesh, meshPart, vertexBuffer, vertexBufferElementSize);
            }
            else
            {
                WriteVertices(assimpMesh, meshPart, vertexBuffer, vertexBufferElementSize);
            }
            WriteIndices(assimpMesh, meshPart, indexBuffer);
            return(meshPart);
        }
Beispiel #11
0
        void WriteVertices(Mesh assimpMesh, ModelData.MeshPart meshPart, ModelData.VertexBuffer vertexBuffer, int vertexBufferElementSize)
        {
            // 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)
                {
                    if (!options.ExcludeElements.Contains("Tangent"))
                    {
                        double w = Vector3D.Dot(assimpMesh.Normals[i],
                                                Vector3D.Cross(assimpMesh.Tangents[i], assimpMesh.Tangents[i]));
                        Vector3D t   = assimpMesh.Tangents[i];
                        Vector4  t4D = new Vector4(t.X, t.Y, t.Z, (float)w);
                        vertexStream.Write(t4D);
                    }
                    if (!options.ExcludeElements.Contains("BiTangent"))
                    {
                        vertexStream.Write(assimpMesh.BiTangents[i]);
                    }
                }
            }
            vertexStream.Dispose();
        }
        private void ApplyFixedFunctionMaterial(Mesh mesh, Material mat, bool textured, bool shaded)
        {
            shaded = shaded && (mesh == null || mesh.HasNormals);
            if (shaded)
            {
                GL.Enable(EnableCap.Lighting);
            }
            else
            {
                GL.Disable(EnableCap.Lighting);
            }

            var hasColors = mesh != null && mesh.HasVertexColors(0);
            if (hasColors)
            {
                GL.Enable(EnableCap.ColorMaterial);
                GL.ColorMaterial(MaterialFace.FrontAndBack, ColorMaterialParameter.AmbientAndDiffuse);
            }
            else
            {
                GL.Disable(EnableCap.ColorMaterial);
            }

            // note: keep semantics of hasAlpha consistent with IsAlphaMaterial()
            var hasAlpha = false;
            var hasTexture = false;

            // note: keep this up-to-date with the code in UploadTextures()
            if (textured && mat.GetMaterialTextureCount(TextureType.Diffuse) > 0)
            {
                hasTexture = true;

                TextureSlot tex;
                mat.GetMaterialTexture(TextureType.Diffuse, 0, out tex);
                var gtex = _scene.TextureSet.GetOriginalOrReplacement(tex.FilePath);

                hasAlpha = hasAlpha || gtex.HasAlpha == Texture.AlphaState.HasAlpha;

                if(gtex.State == Texture.TextureState.GlTextureCreated)
                {
                    GL.ActiveTexture(TextureUnit.Texture0);
                    gtex.BindGlTexture();

                    GL.Enable(EnableCap.Texture2D);
                }
                else
                {
                    GL.Disable(EnableCap.Texture2D);
                }
            }
            else
            {
                GL.Disable(EnableCap.Texture2D);
            }

            GL.Enable(EnableCap.Normalize);

            var alpha = 1.0f;
            if (mat.HasOpacity)
            {
                alpha = mat.Opacity;
                if (alpha < AlphaSuppressionThreshold) // suppress zero opacity, this is likely wrong input data
                {
                    alpha = 1.0f;
                }
            }

            var color = new Color4(.8f, .8f, .8f, 1.0f);
            if (mat.HasColorDiffuse)
            {
                color = AssimpToOpenTk.FromColor(mat.ColorDiffuse);
                if (color.A < AlphaSuppressionThreshold) // s.a.
                {
                    color.A = 1.0f;
                }
            }
            color.A *= alpha;
            hasAlpha = hasAlpha || color.A < 1.0f;

            if (shaded)
            {
                // if the material has a texture but the diffuse color texture is all black,
                // then heuristically assume that this is an import/export flaw and substitute
                // white.
                if (hasTexture && color.R < 1e-3f && color.G < 1e-3f && color.B < 1e-3f)
                {
                    GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, Color4.White);
                }
                else
                {
                    GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, color);
                }

                color = new Color4(0, 0, 0, 1.0f);
                if (mat.HasColorSpecular)
                {
                    color = AssimpToOpenTk.FromColor(mat.ColorSpecular);
                }
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, color);

                color = new Color4(.2f, .2f, .2f, 1.0f);
                if (mat.HasColorAmbient)
                {
                    color = AssimpToOpenTk.FromColor(mat.ColorAmbient);
                }
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Ambient, color);

                color = new Color4(0, 0, 0, 1.0f);
                if (mat.HasColorEmissive)
                {
                    color = AssimpToOpenTk.FromColor(mat.ColorEmissive);
                }
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, color);

                float shininess = 1;
                float strength = 1;
                if (mat.HasShininess)
                {
                    shininess = mat.Shininess;

                }
                // todo: I don't even remember how shininess strength was supposed to be handled in assimp
                if (mat.HasShininessStrength)
                {
                    strength = mat.ShininessStrength;
                }

                var exp = shininess*strength;
                if (exp >= 128.0f) // 128 is the maximum exponent as per the Gl spec
                {
                    exp = 128.0f;
                }

                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, exp);
            }
            else if (!hasColors)
            {
                GL.Color3(color.R, color.G, color.B);
            }

            if (hasAlpha)
            {
                GL.Enable(EnableCap.Blend);
                GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
                GL.DepthMask(false);
            }
            else
            {
                GL.Disable(EnableCap.Blend);
                GL.DepthMask(true);
            }
        }
Beispiel #13
0
		void GetVertexFormat (Mesh mesh, int boneCount, out VertexFlags flags, out int stride) {
			stride = 3;
			flags = 0;
			if (mesh.HasNormals) {
				stride += 3;
				flags |= VertexFlags.Normal;
			}
			if (mesh.HasTextureCoords(0)) {
				stride += 2;
				flags |= VertexFlags.TexCoord0;
			}
			if (mesh.HasTextureCoords(1)) {
				stride += 2;
				flags |= VertexFlags.TexCoord0;
			}
			if (mesh.HasTextureCoords(2)) {
				stride += 2;
				flags |= VertexFlags.TexCoord0;
			}
			if (mesh.HasTextureCoords(3)) {
				stride += 2;
				flags |= VertexFlags.TexCoord0;
			}
			if (mesh.HasVertexColors(0)) {
				stride += 4;
				flags |= VertexFlags.Color0;
			}
			if (mesh.HasVertexColors(1)) {
				stride += 4;
				flags |= VertexFlags.Color1;
			}
			if (mesh.HasVertexColors(2)) {
				stride += 4;
				flags |= VertexFlags.Color2;
			}
			if (mesh.HasVertexColors(3)) {
				stride += 4;
				flags |= VertexFlags.Color3;
			}
			stride += boneCount * 2;
		}
Beispiel #14
0
		unsafe void WriteMesh (Mesh mesh, BinaryWriter writer) {
			var boneSlotCount = this.GetBoneSlotCount(mesh);

			VertexFlags flags;
			int stride;
			this.GetVertexFormat(mesh, boneSlotCount, out flags, out stride);
			var count = mesh.VertexCount;

			writer.Write(mesh.Name);
			writer.Write((uint)flags);
			writer.Write(boneSlotCount);
			writer.Write(mesh.MaterialIndex);
			var vertices = new float[stride * count];
			int idx = 0, offset = 0;
			foreach (var pos in mesh.Vertices) {
				vertices[idx] = pos.X;
				vertices[idx + 1] = pos.Y;
				vertices[idx + 2] = pos.Z;
				idx += stride;
			}
			offset = idx = 3;
			if (mesh.HasNormals) {
				foreach (var norm in mesh.Normals) {
					vertices[idx] = norm.X;
					vertices[idx + 1] = norm.Y;
					vertices[idx + 2] = norm.Z;
					idx += stride;
				}
				offset += 3;
				idx = offset;
			}
			for (var i = 0; i < 4; i++) {
				if (mesh.HasTextureCoords(i)) {
					if (mesh.UVComponentCount[i] != 2)
						Console.WriteLine("WARNING: texture coordinates should have 2 components, but this channel has " + mesh.UVComponentCount[i]);
					foreach (var uv in mesh.TextureCoordinateChannels[i]) {
						vertices[idx] = uv.X;
						vertices[idx + 1] = uv.Y;
						idx += stride;
					}
					offset += 2;
					idx = offset;
				}
			}
			for (var i = 0; i < 4; i++) {
				if (mesh.HasVertexColors(i)) {
					foreach (var c in mesh.VertexColorChannels[i]) {
						vertices[idx] = c.R;
						vertices[idx + 1] = c.G;
						vertices[idx + 2] = c.B;
						vertices[idx + 3] = c.A;
						idx += stride;
					}
					offset += 4;
					idx = offset;
				}
			}
			// add bone information to every vertex
			for(var i = 0; i < mesh.BoneCount; i++) {
				foreach (var weight in mesh.Bones[i].VertexWeights) {
					if (weight.Weight > 0f) {
						idx = (stride * weight.VertexID) + offset;
						while (vertices[idx] != 0f)
							idx++;
						vertices[idx] = weight.Weight;
						vertices[idx + boneSlotCount] = i;
					}
				}
			}
			writer.Write(vertices.Length);
			writer.Flush();
			fixed(float *fp = &vertices[0]) {
				byte* bp = (byte*)fp;
				using (var ms = new UnmanagedMemoryStream(bp, vertices.Length * sizeof(float))) {
					ms.CopyTo(writer.BaseStream);
				}
			}

			count = mesh.FaceCount;
			var indices = new int[count * 3];
			idx = 0;
			for (var i = 0; i < count; i++) {
				var face = mesh.Faces[i];
				var faceIndices = face.Indices;
				if (face.IndexCount != 3)
					throw new InvalidOperationException("Polygonal faces are not supported, faces must be triangles.");
				indices[idx++] = faceIndices[0];
				indices[idx++] = faceIndices[1];
				indices[idx++] = faceIndices[2];
			}
			writer.Write(indices.Length);
			writer.Flush();
			fixed(int *ip = &indices[0]) {
				byte* bp = (byte*)ip;
				using (var ms = new UnmanagedMemoryStream(bp, indices.Length * sizeof(float))) {
					ms.CopyTo(writer.BaseStream);
				}
			}

			count = mesh.BoneCount;
			writer.Write(count);
			for (var i = 0; i < count; i++) {
				var bone = mesh.Bones[i];
				writer.Write(bone.Name);
				writer.Write(bone.OffsetMatrix);
				var weightCount = bone.VertexWeightCount;
				writer.Write(weightCount);
				for (var j = 0; j < weightCount; j++) {
					var weight = bone.VertexWeights[i];
					writer.Write(weight.VertexID);
					writer.Write(weight.Weight);
				}
			}
		}
Beispiel #15
0
        private static Mesh ConvertAssimpMeshToGeometry(Ai.Mesh aiMesh, Ai.Material material, Dictionary <string, NodeInfo> nodeLookup, ref int nextBoneIndex, Dictionary <int, List <int> > nodeToBoneIndices, List <Matrix4x4> boneInverseBindMatrices, ref Matrix4x4 nodeWorldTransform, ref Matrix4x4 nodeInverseWorldTransform, List <Vector3> transformedVertices, ModelConverterOptions options)
        {
            if (!aiMesh.HasVertices)
            {
                throw new Exception("Assimp mesh has no vertices");
            }

            var geometry = new Mesh();
            var geometryTransformedVertices = new Vector3[aiMesh.VertexCount];

            geometry.Vertices = aiMesh.Vertices
                                .Select(x => new Vector3(x.X, x.Y, x.Z))
                                .ToArray();

            for (int i = 0; i < geometry.Vertices.Length; i++)
            {
                geometryTransformedVertices[i] = Vector3.Transform(geometry.Vertices[i], nodeWorldTransform);
            }

            transformedVertices.AddRange(geometryTransformedVertices);

            if (aiMesh.HasNormals)
            {
                geometry.Normals = aiMesh.Normals
                                   .Select(x => new Vector3(x.X, x.Y, x.Z))
                                   .ToArray();
            }

            if (aiMesh.HasTextureCoords(0))
            {
                geometry.TexCoordsChannel0 = aiMesh.TextureCoordinateChannels[0]
                                             .Select(x => new Vector2(x.X, x.Y))
                                             .ToArray();
            }

            if (aiMesh.HasTextureCoords(1))
            {
                geometry.TexCoordsChannel1 = aiMesh.TextureCoordinateChannels[1]
                                             .Select(x => new Vector2(x.X, x.Y))
                                             .ToArray();
            }

            if (aiMesh.HasTextureCoords(2))
            {
                geometry.TexCoordsChannel2 = aiMesh.TextureCoordinateChannels[2]
                                             .Select(x => new Vector2(x.X, x.Y))
                                             .ToArray();
            }

            if (aiMesh.HasVertexColors(0))
            {
                geometry.ColorChannel0 = aiMesh.VertexColorChannels[0]
                                         .Select(x => ( uint )(( byte )(x.B * 255f) | ( byte )(x.G * 255f) << 8 | ( byte )(x.R * 255f) << 16 | ( byte )(x.A * 255f) << 24))
                                         .ToArray();
            }
            else if (options.GenerateVertexColors)
            {
                geometry.ColorChannel0 = new uint[geometry.VertexCount];
                for (int i = 0; i < geometry.ColorChannel0.Length; i++)
                {
                    geometry.ColorChannel0[i] = 0xFFFFFFFF;
                }
            }

            if (aiMesh.HasVertexColors(1))
            {
                geometry.ColorChannel1 = aiMesh.VertexColorChannels[1]
                                         .Select(x => ( uint )(( byte )(x.B * 255f) | ( byte )(x.G * 255f) << 8 | ( byte )(x.R * 255f) << 16 | ( byte )(x.A * 255f) << 24))
                                         .ToArray();
            }

            if (aiMesh.HasFaces)
            {
                geometry.TriangleIndexFormat = aiMesh.VertexCount <= ushort.MaxValue ? TriangleIndexFormat.UInt16 : TriangleIndexFormat.UInt32;
                geometry.Triangles           = aiMesh.Faces
                                               .Select(x => new Triangle(( uint )x.Indices[0], ( uint )x.Indices[1], ( uint )x.Indices[2]))
                                               .ToArray();
            }

            if (aiMesh.HasBones)
            {
                geometry.VertexWeights = new VertexWeight[geometry.VertexCount];
                for (int i = 0; i < geometry.VertexWeights.Length; i++)
                {
                    geometry.VertexWeights[i].Indices = new byte[4];
                    geometry.VertexWeights[i].Weights = new float[4];
                }

                var vertexWeightCounts = new int[geometry.VertexCount];

                for (var i = 0; i < aiMesh.Bones.Count; i++)
                {
                    var aiMeshBone = aiMesh.Bones[i];

                    // Find node index for the bone
                    var boneLookupData = nodeLookup[AssimpConverterCommon.UnescapeName(aiMeshBone.Name)];
                    int nodeIndex      = boneLookupData.Index;

                    // Calculate inverse bind matrix
                    var boneNode   = boneLookupData.Node;
                    var bindMatrix = boneNode.WorldTransform * nodeInverseWorldTransform;

                    if (options.ConvertSkinToZUp)
                    {
                        bindMatrix *= YToZUpMatrix;
                    }

                    Matrix4x4.Invert(bindMatrix, out var inverseBindMatrix);

                    // Get bone index
                    int boneIndex;
                    if (!nodeToBoneIndices.TryGetValue(nodeIndex, out var boneIndices))
                    {
                        // No entry for the node was found, so we add a new one
                        boneIndex = nextBoneIndex++;
                        nodeToBoneIndices.Add(nodeIndex, new List <int>()
                        {
                            boneIndex
                        });
                        boneInverseBindMatrices.Add(inverseBindMatrix);
                    }
                    else
                    {
                        // Entry for the node was found
                        // Try to find the bone index based on whether the inverse bind matrix matches
                        boneIndex = -1;
                        foreach (int index in boneIndices)
                        {
                            if (boneInverseBindMatrices[index].Equals(inverseBindMatrix))
                            {
                                boneIndex = index;
                            }
                        }

                        if (boneIndex == -1)
                        {
                            // None matching inverse bind matrix was found, so we add a new entry
                            boneIndex = nextBoneIndex++;
                            nodeToBoneIndices[nodeIndex].Add(boneIndex);
                            boneInverseBindMatrices.Add(inverseBindMatrix);
                        }
                    }

                    foreach (var aiVertexWeight in aiMeshBone.VertexWeights)
                    {
                        int vertexWeightCount = vertexWeightCounts[aiVertexWeight.VertexID]++;

                        geometry.VertexWeights[aiVertexWeight.VertexID].Indices[vertexWeightCount] = ( byte )boneIndex;
                        geometry.VertexWeights[aiVertexWeight.VertexID].Weights[vertexWeightCount] = aiVertexWeight.Weight;
                    }
                }
            }

            geometry.MaterialName   = AssimpConverterCommon.UnescapeName(material.Name);
            geometry.BoundingBox    = BoundingBox.Calculate(geometry.Vertices);
            geometry.BoundingSphere = BoundingSphere.Calculate(geometry.BoundingBox.Value, geometry.Vertices);
            geometry.Flags         |= GeometryFlags.Flag80000000;

            return(geometry);
        }
Beispiel #16
0
        // Load a model from file using the ASSIMP model loader and generate all resources required to render the model
        void loadModel(string filename)
        {
            // Load the model from file using ASSIMP

            // Flags for loading the mesh
            PostProcessSteps assimpFlags = PostProcessSteps.FlipWindingOrder | PostProcessSteps.Triangulate | PostProcessSteps.PreTransformVertices;

            var scene = new AssimpContext().ImportFile(filename, assimpFlags);

            // Generate vertex buffer from ASSIMP scene data
            float scale        = 1.0f;
            var   vertexBuffer = new List <Vertex>();

            // Iterate through all meshes in the file and extract the vertex components
            for (int m = 0; m < scene.MeshCount; m++)
            {
                for (int v = 0; v < scene.Meshes[(int)m].VertexCount; v++)
                {
                    Vertex      vertex;
                    Assimp.Mesh mesh = scene.Meshes[m];

                    // Use glm make_* functions to convert ASSIMP vectors to glm vectors
                    vertex.pos    = new Vector3(mesh.Vertices[v].X, mesh.Vertices[v].Y, mesh.Vertices[v].Z) * scale;
                    vertex.normal = new Vector3(mesh.Normals[v].X, mesh.Normals[v].Y, mesh.Normals[v].Z);
                    // Texture coordinates and colors may have multiple channels, we only use the first [0] one
                    vertex.uv = new Vector2(mesh.TextureCoordinateChannels[0][v].X, mesh.TextureCoordinateChannels[0][v].Y);
                    // Mesh may not have vertex colors
                    if (mesh.HasVertexColors(0))
                    {
                        vertex.color = new Vector3(mesh.VertexColorChannels[0][v].R, mesh.VertexColorChannels[0][v].G, mesh.VertexColorChannels[0][v].B);
                    }
                    else
                    {
                        vertex.color = new Vector3(1f);
                    }

                    // Vulkan uses a right-handed NDC (contrary to OpenGL), so simply flip Y-Axis
                    vertex.pos.Y *= -1.0f;

                    vertexBuffer.Add(vertex);
                }
            }
            ulong vertexBufferSize = (ulong)(vertexBuffer.Count * sizeof(Vertex));

            // Generate index buffer from ASSIMP scene data
            var indexBuffer = new List <uint>();

            for (int m = 0; m < scene.MeshCount; m++)
            {
                uint indexBase = (uint)indexBuffer.Count;
                for (int f = 0; f < scene.Meshes[m].FaceCount; f++)
                {
                    // We assume that all faces are triangulated
                    for (int i = 0; i < 3; i++)
                    {
                        indexBuffer.Add((uint)scene.Meshes[m].Faces[f].Indices[i] + indexBase);
                    }
                }
            }
            ulong indexBufferSize = (ulong)(indexBuffer.Count * sizeof(uint));

            model_indices_count = (int)indexBuffer.Count;

            // Static mesh should always be Device local

            bool useStaging = true;

            if (useStaging)
            {
                VkBuffer       vertexStaging_buffer;
                VkDeviceMemory vertexStaging_memory;
                VkBuffer       indexStaging_buffer;
                VkDeviceMemory indexStaging_memory;

                // Create staging buffers
                // Vertex data
                fixed(Vertex *pointer = vertexBuffer.ToArray())
                {
                    vulkanDevice.createBuffer(
                        VkBufferUsageFlagBits.TransferSrc,
                        VkMemoryPropertyFlagBits.HostVisible | VkMemoryPropertyFlagBits.HostCoherent,
                        vertexBufferSize,
                        &vertexStaging_buffer,
                        &vertexStaging_memory,
                        pointer);
                }

                // Index data
                fixed(uint *pointer = indexBuffer.ToArray())
                {
                    vulkanDevice.createBuffer(
                        VkBufferUsageFlagBits.TransferSrc,
                        VkMemoryPropertyFlagBits.HostVisible | VkMemoryPropertyFlagBits.HostCoherent,
                        indexBufferSize,
                        &indexStaging_buffer,
                        &indexStaging_memory,
                        pointer);
                }

                // Create Device local buffers
                // Vertex buffer
                vulkanDevice.createBuffer(
                    VkBufferUsageFlagBits.VertexBuffer | VkBufferUsageFlagBits.TransferDst,
                    VkMemoryPropertyFlagBits.DeviceLocal,
                    vertexBufferSize,
                    out model_vertices_buffer,
                    out model_vertices_memory);
                // Index buffer
                vulkanDevice.createBuffer(
                    VkBufferUsageFlagBits.IndexBuffer | VkBufferUsageFlagBits.TransferDst,
                    VkMemoryPropertyFlagBits.DeviceLocal,
                    indexBufferSize,
                    out model_indices_buffer,
                    out model_indices_memory);

                // Copy from staging buffers
                VkCommandBuffer copyCmd = createCommandBuffer(VkCommandBufferLevel.Primary, true);

                VkBufferCopy copyRegion = new VkBufferCopy();

                copyRegion.size = vertexBufferSize;

                vkCmdCopyBuffer(
                    copyCmd,
                    vertexStaging_buffer,
                    model_vertices_buffer,
                    1,
                    &copyRegion);

                copyRegion.size = indexBufferSize;

                vkCmdCopyBuffer(
                    copyCmd,
                    indexStaging_buffer,
                    model_indices_buffer,
                    1,
                    &copyRegion);

                flushCommandBuffer(copyCmd, queue, true);


                vkDestroyBuffer(device, vertexStaging_buffer, null);

                vkFreeMemory(device, vertexStaging_memory, null);

                vkDestroyBuffer(device, indexStaging_buffer, null);

                vkFreeMemory(device, indexStaging_memory, null);
            }
            else
            {
                // Vertex buffer
                fixed(Vertex *pointer = vertexBuffer.ToArray())
                {
                    vulkanDevice.createBuffer(
                        VkBufferUsageFlagBits.VertexBuffer,
                        VkMemoryPropertyFlagBits.HostVisible,
                        vertexBufferSize,
                        out model_vertices_buffer,
                        out model_vertices_memory,
                        pointer);
                }

                // Index buffer
                fixed(uint *pointer = indexBuffer.ToArray())
                {
                    vulkanDevice.createBuffer(
                        VkBufferUsageFlagBits.IndexBuffer,
                        VkMemoryPropertyFlagBits.HostVisible,
                        indexBufferSize,
                        out model_indices_buffer,
                        out model_indices_memory,
                        pointer);
                }
            }
        }
Beispiel #17
0
        //private const PostProcessSteps DefaultPostProcessSteps
        //    = PostProcessSteps.None;

        //TODO: add support for VertexPosition Type
        public static byte[] GenerateVertexBytesArrayFromAssimp(VertexRuntimeTypes henzaiVertexType, Assimp.Mesh aiMesh, int index)
        {
            Vector3D pPos       = aiMesh.Vertices[index];
            Vector3D pNormal    = aiMesh.Normals[index];
            Vector3D pTexCoord  = aiMesh.HasTextureCoords(0) ? aiMesh.TextureCoordinateChannels[0][index] : Zero3D;
            Color4D  pColor     = aiMesh.HasVertexColors(0) ? aiMesh.VertexColorChannels[0][index] : Nocolor;
            Vector3D pTangent   = aiMesh.HasTangentBasis ? aiMesh.Tangents[index] : Zero3D;
            Vector3D pBiTangent = aiMesh.HasTangentBasis ? aiMesh.BiTangents[index] : Zero3D;

            byte[] bytes;
            byte[] posAsBytes       = ByteMarshal.StructToBytes(pPos);
            byte[] colorAsBytes     = ByteMarshal.StructToBytes(pColor);
            byte[] normalAsBytes    = ByteMarshal.StructToBytes(pNormal);
            byte[] texCoordAsBytes  = ByteMarshal.StructToBytes(pTexCoord.ToVector2());
            byte[] tangentAsBytes   = ByteMarshal.StructToBytes(pTangent);
            byte[] bitangentAsBytes = ByteMarshal.StructToBytes(pBiTangent);

            switch (henzaiVertexType)
            {
            case VertexRuntimeTypes.VertexPosition:
                bytes = new byte[VertexPosition.SizeInBytes];
                Array.Copy(posAsBytes, 0, bytes, VertexPosition.PositionOffset, posAsBytes.Length);
                break;

            case VertexRuntimeTypes.VertexPositionColor:
                bytes = new byte[VertexPositionColor.SizeInBytes];
                Array.Copy(posAsBytes, 0, bytes, VertexPositionColor.PositionOffset, posAsBytes.Length);
                Array.Copy(colorAsBytes, 0, bytes, VertexPositionColor.ColorOffset, colorAsBytes.Length);
                break;

            case VertexRuntimeTypes.VertexPositionTexture:
                bytes = new byte[VertexPositionTexture.SizeInBytes];
                Array.Copy(posAsBytes, 0, bytes, VertexPositionTexture.PositionOffset, posAsBytes.Length);
                Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionTexture.TextureCoordinatesOffset, texCoordAsBytes.Length);
                break;

            case VertexRuntimeTypes.VertexPositionNormalTexture:
                bytes = new byte[VertexPositionNormalTexture.SizeInBytes];
                Array.Copy(posAsBytes, 0, bytes, VertexPositionNormalTexture.PositionOffset, posAsBytes.Length);
                Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormalTexture.NormalOffset, normalAsBytes.Length);
                Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionNormalTexture.TextureCoordinatesOffset, texCoordAsBytes.Length);
                break;

            case VertexRuntimeTypes.VertexPositionNormal:
                bytes = new byte[VertexPositionNormal.SizeInBytes];
                Array.Copy(posAsBytes, 0, bytes, VertexPositionNormal.PositionOffset, posAsBytes.Length);
                Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormal.NormalOffset, normalAsBytes.Length);
                break;

            case VertexRuntimeTypes.VertexPositionNormalTextureTangent:
                bytes = new byte[VertexPositionNormalTextureTangent.SizeInBytes];
                Array.Copy(posAsBytes, 0, bytes, VertexPositionNormalTextureTangent.PositionOffset, posAsBytes.Length);
                Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormalTextureTangent.NormalOffset, normalAsBytes.Length);
                Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionNormalTextureTangent.TextureCoordinatesOffset, texCoordAsBytes.Length);
                Array.Copy(tangentAsBytes, 0, bytes, VertexPositionNormalTextureTangent.TangentOffset, tangentAsBytes.Length);
                break;

            case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent:
                bytes = new byte[VertexPositionNormalTextureTangentBitangent.SizeInBytes];
                Array.Copy(posAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.PositionOffset, posAsBytes.Length);
                Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.NormalOffset, normalAsBytes.Length);
                Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.TextureCoordinatesOffset, texCoordAsBytes.Length);
                Array.Copy(tangentAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.TangentOffset, tangentAsBytes.Length);
                Array.Copy(bitangentAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.BitangentOffset, bitangentAsBytes.Length);
                break;

            default:
                throw new NotImplementedException($"{henzaiVertexType.ToString("g")} not implemented");
            }

            return(bytes);
        }
Beispiel #18
0
        private void AddVertexData(CModel model, Assimp.Scene scene, Node node, Device device, ref Matrix transform, string modelPath, CShaderResource shaderResource)
        {
            // TODO henning With this we don't preserve hiearchy in the models meshes, for now this is the wanted behavior but maybe we want to think about this in the future
            Matrix previousTransform = transform;

            transform = Matrix.Multiply(previousTransform, FromAssimpMatrix(node.Transform));

            if (node.HasMeshes)
            {
                foreach (int index in node.MeshIndices)
                {
                    // Get the mesh from the scene
                    Assimp.Mesh assimpMesh = scene.Meshes[index];

                    // Create a mesh in our engine format
                    CMesh mesh = new CMesh();
                    mesh.Transform.SetFromMatrix(in transform);
                    model.AddMesh(ref mesh);

                    //Extract diffuse texture from Assimp Material
                    // TODO henning extract other textures if we want
                    Material material = scene.Materials[assimpMesh.MaterialIndex];
                    if (material != null && material.GetMaterialTextureCount(TextureType.Diffuse) > 0)
                    {
                        TextureSlot texture;
                        if (material.GetMaterialTexture(TextureType.Diffuse, 0, out texture))
                        {
                            // Create texture asset
                            mesh.Material = CMaterial.CreateDefaultMaterial();
                            CTextureSampler textureSampler = new CTextureSampler(device, device.ImmediateContext, modelPath + "\\" + texture.FilePath);
                            mesh.Material.SetTextureParameter(new SHashedName("DiffuseTexture"), textureSampler);
                            mesh.Material.FinishLoading();
                        }
                        else
                        {
                            mesh.Material = CRenderer.Instance.ResourceManager.DefaultTextureMaterial;
                        }
                    }
                    else
                    {
                        mesh.Material = CRenderer.Instance.ResourceManager.DefaultTextureMaterial;
                    }
                    mesh.Material.SetColorParameter(new SHashedName("tintColor"), new Vector4(1, 1, 1, 1));


                    int numInputElements = 6;                     // We always provide all data to the vertex buffer so shaders can rely on them being available if it is not in the asset we will add a default value

                    bool hasTexCoords  = assimpMesh.HasTextureCoords(0);
                    bool hasColors     = assimpMesh.HasVertexColors(0);
                    bool hasNormals    = assimpMesh.HasNormals;
                    bool hasTangents   = assimpMesh.Tangents != null && assimpMesh.Tangents.Count > 0;
                    bool hasBiTangents = assimpMesh.BiTangents != null && assimpMesh.BiTangents.Count > 0;

                    // Create InputElement list
                    InputElement[] vertexElements = new InputElement[numInputElements];
                    uint           elementIndex   = 0;
                    vertexElements[elementIndex] = new InputElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0);
                    elementIndex++;
                    int vertexSize = Utilities.SizeOf <Vector3>();

                    // TODO henning evaluate if we need 32bit vertex color range
                    vertexElements[elementIndex] = new InputElement("COLOR", 0, SharpDX.DXGI.Format.R32G32B32A32_Float, 0);
                    elementIndex++;
                    vertexSize += Utilities.SizeOf <Vector4>();
                    vertexElements[elementIndex] = new InputElement("NORMAL", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0);
                    elementIndex++;
                    vertexSize += Utilities.SizeOf <Vector3>();
                    vertexElements[elementIndex] = new InputElement("TANGENT", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0);
                    elementIndex++;
                    vertexSize += Utilities.SizeOf <Vector3>();
                    vertexElements[elementIndex] = new InputElement("BITANGENT", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0);
                    elementIndex++;
                    vertexSize += Utilities.SizeOf <Vector3>();
                    vertexElements[elementIndex] = new InputElement("TEXCOORD", 0, SharpDX.DXGI.Format.R32G32_Float, 0);
                    elementIndex++;
                    vertexSize += Utilities.SizeOf <Vector2>();

                    // Set InputElements and Vertex Size on mesh
                    mesh.m_sizePerVertex = vertexSize;

                    List <Vector3D> positions  = assimpMesh.Vertices;
                    List <Vector3D> texCoords  = assimpMesh.TextureCoordinateChannels[0];                   // TODO henning support multiple UV channels if wanted
                    List <Vector3D> normals    = assimpMesh.Normals;
                    List <Vector3D> tangents   = assimpMesh.Tangents;
                    List <Vector3D> biTangents = assimpMesh.BiTangents;
                    List <Color4D>  colors     = assimpMesh.VertexColorChannels[0];

                    switch (assimpMesh.PrimitiveType)
                    {
                    case PrimitiveType.Point:
                        mesh.m_primitiveTopology = SharpDX.Direct3D.PrimitiveTopology.PointList;
                        break;

                    case PrimitiveType.Line:
                        mesh.m_primitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList;
                        break;

                    case PrimitiveType.Triangle:
                        mesh.m_primitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList;
                        break;

                    default:
                        throw new NotImplementedException("Primitive Type not supported: " + assimpMesh.PrimitiveType.ToString());
                    }

                    DataStream vertexStream = new DataStream(assimpMesh.VertexCount * vertexSize, true, true);

                    for (int i = 0; i < assimpMesh.VertexCount; i++)
                    {
                        //add position, after transforming it with accumulated node transform
                        {
                            Vector3 pos = FromAssimpVector(positions[i]);
                            vertexStream.Write(pos);
                        }

                        if (hasColors)
                        {
                            Vector4 vertColor = FromAssimpColor(colors[i]);
                            vertexStream.Write(vertColor);
                        }
                        else
                        {
                            vertexStream.Write(new Vector4(1, 1, 1, 1));
                        }
                        if (hasNormals)
                        {
                            Vector3 normal = FromAssimpVector(normals[i]);
                            vertexStream.Write(normal);
                        }
                        else
                        {
                            vertexStream.Write(new Vector3(0, 0, 0));
                        }
                        if (hasTangents)
                        {
                            Vector3 tangent = FromAssimpVector(tangents[i]);
                            vertexStream.Write(tangent);
                        }
                        else
                        {
                            vertexStream.Write(new Vector3(0, 0, 0));
                        }
                        if (hasBiTangents)
                        {
                            Vector3 biTangent = FromAssimpVector(biTangents[i]);
                            vertexStream.Write(biTangent);
                        }
                        else
                        {
                            vertexStream.Write(new Vector3(0, 0, 0));
                        }
                        if (hasTexCoords)
                        {
                            vertexStream.Write(new Vector2(texCoords[i].X, texCoords[i].Y));
                        }
                        else
                        {
                            vertexStream.Write(new Vector2(0, 0));
                        }
                    }

                    vertexStream.Position = 0;
                    BufferDescription vertexDescription = new BufferDescription
                    {
                        BindFlags      = BindFlags.VertexBuffer,
                        Usage          = ResourceUsage.Default,
                        CpuAccessFlags = CpuAccessFlags.None,
                        SizeInBytes    = assimpMesh.VertexCount * vertexSize,
                        OptionFlags    = ResourceOptionFlags.None
                    };

                    mesh.m_vertexBuffer = new Buffer(device, vertexStream, vertexDescription);
                    vertexStream.Dispose();

                    mesh.m_vertexCount    = assimpMesh.VertexCount;
                    mesh.m_primitiveCount = assimpMesh.FaceCount;


                    int[] indices = assimpMesh.GetIndices();
                    mesh.m_indexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, indices);
                    mesh.m_indexCount  = indices.Length;
                }
            }

            for (int i = 0; i < node.ChildCount; i++)
            {
                AddVertexData(model, scene, node.Children[i], device, ref transform, modelPath, shaderResource);
            }

            transform = previousTransform;
        }
Beispiel #19
0
            private void CreateBuffers(Node assimpnode, ModelNode parent_node, ref Matrix4x4 model_matrix)
            {
                // create new mesh
                ModelNode node = new ModelNode(_openGLFactory);

                if (parent_node != null)
                {
                    parent_node.AddChild(node);
                }
                else
                {
                    _model._root_node = node;
                }

                // set model matrix
                Matrix4x4 mm = assimpnode.Transform;

                node.ModelMatrix = new Matrix4(
                    mm.A1, mm.A2, mm.A3, mm.A4,
                    mm.B1, mm.B2, mm.B3, mm.B4,
                    mm.C1, mm.C2, mm.C3, mm.C4,
                    mm.D1, mm.D2, mm.D3, mm.D4);

                // combined model matrix
                Matrix4x4 prev_model    = model_matrix;
                Matrix4x4 new_transform = assimpnode.Transform;

                model_matrix = new_transform * model_matrix; // ? has this to be reversed link in OpneTK?

                if (assimpnode.HasMeshes)
                {
                    foreach (int index in assimpnode.MeshIndices)
                    {
                        Assimp.Mesh assimpmesh = _assimpmodel.Meshes[index];
                        AABB        mesh_box   = new AABB();

                        // extend bounding box by vertices
                        for (int i = 0; i < assimpmesh.VertexCount; i++)
                        {
                            Vector3D tmp = assimpmesh.Vertices[i];
                            mesh_box = mesh_box | new Vector3(tmp.X, tmp.Y, tmp.Z);

                            tmp = model_matrix * tmp;
                            _model._scene_box = _model._scene_box | new Vector3(tmp.X, tmp.Y, tmp.Z);
                        }

                        // create Mesh
                        uint tuple_index = 0;
                        List <TVertexFormat> formalist = new List <TVertexFormat>();

                        OpenTK_library.Scene.Mesh mesh = new OpenTK_library.Scene.Mesh();
                        mesh.Box = mesh_box;
                        node.Add(mesh);

                        // specify vertices
                        mesh.VertexAttribute = (tuple_index, 3);
                        formalist.Add(new TVertexFormat(0, vertex_index, 3, (int)tuple_index, false));
                        tuple_index += 3;

                        // specify normals
                        if (assimpmesh.HasNormals)
                        {
                            mesh.NormalAttribute = (tuple_index, 3);
                            formalist.Add(new TVertexFormat(0, normal_index, 3, (int)tuple_index, false));
                            tuple_index += 3;
                        }

                        // specify bi-normals and tangents
                        if (assimpmesh.HasTangentBasis)
                        {
                            mesh.BinormalAttribute = (tuple_index, 3);
                            formalist.Add(new TVertexFormat(0, binormal_index, 3, (int)tuple_index, false));
                            tuple_index += 3;

                            mesh.TangentAttribute = (tuple_index, 3);
                            formalist.Add(new TVertexFormat(0, tangent_index, 3, (int)tuple_index, false));
                            tuple_index += 3;
                        }

                        // specify texture channels
                        for (int textur_channel = 0; assimpmesh.HasTextureCoords(textur_channel); ++textur_channel)
                        {
                            mesh.AddTextureAttrib((tuple_index, 3));
                            int attr_i = textur_channel == 0 ? texture0_index : (textureN_index + textur_channel - 1);
                            formalist.Add(new TVertexFormat(0, attr_i, 3, (int)tuple_index, false));
                            tuple_index += 3;
                        }

                        // specify color channels
                        for (int color_channel = 0; assimpmesh.HasVertexColors(color_channel); ++color_channel)
                        {
                            mesh.AddColorAttrib((tuple_index, 4));
                            int attr_i = color_channel == 0 ? color0_index : (colorN_index + color_channel - 1);
                            formalist.Add(new TVertexFormat(0, attr_i, 4, (int)tuple_index, false));
                            tuple_index += 4;
                        }

                        // TODO $$$ bones
                        if (assimpmesh.HasBones)
                        {
                            // [...]
                            Console.WriteLine("bones not yet implemented");
                        }

                        // set tuple size
                        mesh.TupleSize = tuple_index;

                        // setup index buffer
                        List <float> attributes = new List <float>();
                        List <uint>  indices    = new List <uint>();
                        uint         elem_index = 0;
                        foreach (Face face in assimpmesh.Faces)
                        {
                            if (face.IndexCount < 3)
                            {
                                continue; // lines?
                            }
                            for (uint i = 2; i < (uint)face.IndexCount; i++)
                            {
                                indices.Add(elem_index);
                                indices.Add(elem_index + 1);
                                indices.Add(elem_index + i);
                            }
                            elem_index += (uint)face.IndexCount;

                            for (int i = 0; i < face.IndexCount; i++)
                            {
                                int ei = face.Indices[i];

                                // add vertex attribute
                                var vertex = assimpmesh.Vertices[ei];
                                attributes.Add(vertex.X);
                                attributes.Add(vertex.Y);
                                attributes.Add(vertex.Z);

                                // add normals
                                if (assimpmesh.HasNormals)
                                {
                                    var normal = assimpmesh.Normals[ei];
                                    attributes.Add(normal.X);
                                    attributes.Add(normal.Y);
                                    attributes.Add(normal.Z);
                                }

                                // add bi-normals and tangents
                                if (assimpmesh.HasTangentBasis)
                                {
                                    var binormal = assimpmesh.BiTangents[ei];
                                    attributes.Add(binormal.X);
                                    attributes.Add(binormal.Y);
                                    attributes.Add(binormal.Z);

                                    var tangent = assimpmesh.Tangents[ei];
                                    attributes.Add(tangent.X);
                                    attributes.Add(tangent.Y);
                                    attributes.Add(tangent.Z);
                                }

                                // add texture coordinates
                                for (int textur_channel = 0; assimpmesh.HasTextureCoords(textur_channel); ++textur_channel)
                                {
                                    var uvw = assimpmesh.TextureCoordinateChannels[textur_channel][ei];
                                    attributes.Add(uvw.X);
                                    attributes.Add(uvw.Y);
                                    attributes.Add(uvw.Z);
                                }

                                // add color attributes
                                for (int color_channel = 0; assimpmesh.HasVertexColors(color_channel); ++color_channel)
                                {
                                    var vertColor = assimpmesh.VertexColorChannels[color_channel][ei];
                                    attributes.Add(vertColor.R);
                                    attributes.Add(vertColor.G);
                                    attributes.Add(vertColor.B);
                                    attributes.Add(vertColor.A);
                                }
                            }
                        }

                        // setup vertex arrays and index array
                        TVertexFormat[] format = formalist.ToArray();
                        var             vao    = _openGLFactory.NewVertexArrayObject();
                        vao.AppendVertexBuffer(0, (int)tuple_index, attributes.ToArray());
                        vao.Create(format, indices.ToArray());

                        mesh.FaceSize    = 3;
                        mesh.VertexArray = vao;
                    }
                }

                for (int i = 0; i < assimpnode.ChildCount; i++)
                {
                    CreateBuffers(assimpnode.Children[i], node, ref model_matrix);
                }
                model_matrix = prev_model;
            }
Beispiel #20
0
        private void LoadMeshInternal(int meshIndex, CMeshAsset asset, CMeshLoadingJob loadingJob, string assetPath, string nameOverride = null, bool bAlwaysImport = false)
        {
            Assimp.Mesh assimpMesh = loadingJob.Scene.Meshes[meshIndex];

            // Load texture and material from the file if present
            //todo henning extract more textures
            Material material = loadingJob.Scene.Materials[assimpMesh.MaterialIndex];

            if (material != null && material.GetMaterialTextureCount(TextureType.Diffuse) > 0)
            {
                if (material.GetMaterialTexture(TextureType.Diffuse, 0, out TextureSlot texture))
                {
                    if (loadingJob.LoadedMaterials == null || !loadingJob.LoadedMaterials.TryGetValue(material.Name, out CMaterialAsset materialAsset))
                    {
                        materialAsset = new CMaterialAsset();
                        loadingJob.LoadedMaterials?.Add(material.Name, materialAsset);
                        // Make sure we only load each referenced texture once
                        if (loadingJob.LoadedTextures == null || !loadingJob.LoadedTextures.TryGetValue(texture.FilePath, out CTextureAsset textureAsset))
                        {
                            textureAsset = CImportManager.Instance.TextureImporter.ImportTextureAsync(loadingJob.BasePath + "\\" + texture.FilePath, assetPath + "Textures/");
                            loadingJob.LoadedTextures?.Add(texture.FilePath, textureAsset);
                        }

                        SShaderParameter textureParameter = new SShaderParameter()
                        {
                            parameterData = new CAssetReference <CTextureAsset>(textureAsset),
                            parameterType = EShaderParameterType.Texture
                        };
                        materialAsset.MaterialParameters.Add(new SMaterialParameterEntry(new SHashedName("DiffuseTexture"), textureParameter));

                        materialAsset.Name = material.Name;
                        if (CAssetRegistry.Instance.RequestRegisterAsset(materialAsset, assetPath + "Materials/", out CMaterialAsset existingMaterial))
                        {
                            existingMaterial.WaitUntilLoaded();
                            existingMaterial.CopyFrom(existingMaterial);
                        }
                        materialAsset.LoadFinished();
                    }
                    asset.MaterialAsset = materialAsset;
                }
            }

            bool hasTexCoords  = assimpMesh.HasTextureCoords(0);
            bool hasColors     = assimpMesh.HasVertexColors(0);
            bool hasNormals    = assimpMesh.HasNormals;
            bool hasTangents   = assimpMesh.Tangents != null && assimpMesh.Tangents.Count > 0;
            bool hasBiTangents = assimpMesh.BiTangents != null && assimpMesh.BiTangents.Count > 0;

            switch (assimpMesh.PrimitiveType)
            {
            case PrimitiveType.Point:
                asset.PrimitiveTopology = PrimitiveTopology.PointList;
                break;

            case PrimitiveType.Line:
                asset.PrimitiveTopology = PrimitiveTopology.LineList;
                break;

            case PrimitiveType.Triangle:
                asset.PrimitiveTopology = PrimitiveTopology.TriangleList;
                break;

            default:
                throw new ArgumentOutOfRangeException("Primtive Type not supported: " + assimpMesh.PrimitiveType.ToString());
            }

            asset.FaceCount  = assimpMesh.FaceCount;
            asset.VertexData = new SVertexInfo[assimpMesh.VertexCount];

            Vector3 boundingBoxMin = new Vector3(1e10f, 1e10f, 1e10f);
            Vector3 boundingBoxMax = new Vector3(-1e10f, -1e10f, -1e10f);

            for (int i = 0; i < assimpMesh.VertexCount; i++)
            {
                SVertexInfo vertexInfo = new SVertexInfo();
                vertexInfo.position = FromAssimpVector(assimpMesh.Vertices[i]);
                boundingBoxMin.X    = Math.Min(vertexInfo.position.X, boundingBoxMin.X);
                boundingBoxMin.Y    = Math.Min(vertexInfo.position.Y, boundingBoxMin.Y);
                boundingBoxMin.Z    = Math.Min(vertexInfo.position.Z, boundingBoxMin.Z);

                boundingBoxMax.X = Math.Max(vertexInfo.position.X, boundingBoxMax.X);
                boundingBoxMax.Y = Math.Max(vertexInfo.position.Y, boundingBoxMax.Y);
                boundingBoxMax.Z = Math.Max(vertexInfo.position.Z, boundingBoxMax.Z);

                if (hasColors)
                {
                    vertexInfo.color = FromAssimpColor(assimpMesh.VertexColorChannels[0][i]);
                }
                else
                {
                    vertexInfo.color = Vector4.One;
                }

                if (hasNormals)
                {
                    vertexInfo.normal = FromAssimpVector(assimpMesh.Normals[i]);
                }

                if (hasBiTangents)
                {
                    vertexInfo.biTangent = FromAssimpVector(assimpMesh.BiTangents[i]);
                }

                if (hasTangents)
                {
                    vertexInfo.tangent = FromAssimpVector(assimpMesh.Tangents[i]);
                }

                if (hasTexCoords)
                {
                    Vector3D assimpTexCoord = assimpMesh.TextureCoordinateChannels[0][i];
                    vertexInfo.texCoord = new Vector2(assimpTexCoord.X, assimpTexCoord.Y);
                }

                asset.VertexData[i] = vertexInfo;
            }

            asset.AABBMin   = boundingBoxMin;
            asset.AABBMax   = boundingBoxMax;
            asset.IndexData = assimpMesh.GetIndices();
            asset.Name      = nameOverride ?? assimpMesh.Name;
            if (CAssetRegistry.Instance.RequestRegisterAsset(asset, assetPath, out CMeshAsset existingAsset, true))
            {
                existingAsset.WaitUntilLoaded();
                asset.CopyFrom(existingAsset);
            }
        }