예제 #1
0
        private static Node ConvertNode(Assimp.Node aiNode, List <Assimp.Mesh> aiMeshes, List <MaterialBuildInfo> materialBuildInfos)
        {
            Node ConvertHierarchyNodeRecursively(Assimp.Node curAiNode, ref Node previousSibling, Node parent, ref Assimp.Matrix4x4 parentNodeWorldTransform)
            {
                var nodeWorldTransform        = curAiNode.Transform * parentNodeWorldTransform;
                var nodeInverseWorldTransform = nodeWorldTransform;

                nodeInverseWorldTransform.Inverse();

                curAiNode.Transform.Decompose(out var scale, out var rotation, out var translation);

                // Create node
                var node = new Node(AssimpHelper.FromAssimp(translation), AngleVector.FromQuaternion(AssimpHelper.FromAssimp(rotation)),
                                    AssimpHelper.FromAssimp(scale), parent);

                if (curAiNode.HasMeshes)
                {
                    var geometry = new Geometry();

                    // Convert meshes
                    var vertexPositions = new List <Assimp.Vector3D>();
                    var vertexNormals   = new List <Assimp.Vector3D>();
                    var vertexUVs       = new List <Assimp.Vector3D>();
                    var vertexColors    = new List <Assimp.Color4D>();
                    var lastRenderState = new MeshRenderState();

                    foreach (var aiMeshIndex in curAiNode.MeshIndices)
                    {
                        var aiMesh      = aiMeshes[aiMeshIndex];
                        var material    = materialBuildInfos[aiMesh.MaterialIndex];
                        var mesh        = new Mesh();
                        var renderState = new MeshRenderState();

                        renderState.IndexFlags = IndexAttributeFlags.HasPosition | IndexAttributeFlags.Position16BitIndex;
                        var useColors  = false;
                        var hasColors  = aiMesh.HasVertexColors(0);
                        var hasUVs     = aiMesh.HasTextureCoords(0);
                        var hasNormals = aiMesh.HasNormals;

                        if (hasColors || !hasNormals)
                        {
                            renderState.IndexFlags |= IndexAttributeFlags.HasColor | IndexAttributeFlags.Color16BitIndex;
                            useColors = true;
                        }
                        else
                        {
                            renderState.IndexFlags |= IndexAttributeFlags.HasNormal | IndexAttributeFlags.Normal16BitIndex;
                        }

                        if (hasUVs)
                        {
                            renderState.IndexFlags |= IndexAttributeFlags.HasUV | IndexAttributeFlags.UV16BitIndex;
                        }

                        // Convert faces
                        var triangleIndices = new Index[aiMesh.FaceCount * 3];
                        for (var i = 0; i < aiMesh.Faces.Count; i++)
                        {
                            var aiFace = aiMesh.Faces[i];
                            Debug.Assert(aiFace.IndexCount == 3);

                            for (var j = 0; j < aiFace.Indices.Count; j++)
                            {
                                int aiFaceIndex = aiFace.Indices[j];

                                var position      = aiMesh.Vertices[aiFaceIndex];
                                var positionIndex = vertexPositions.IndexOf(position);
                                if (positionIndex == -1)
                                {
                                    positionIndex = vertexPositions.Count;
                                    vertexPositions.Add(position);
                                }

                                var normalIndex = 0;
                                var colorIndex  = 0;
                                var uvIndex     = 0;

                                if (useColors)
                                {
                                    var color = hasColors ? aiMesh.VertexColorChannels[0][aiFaceIndex] : new Assimp.Color4D();
                                    colorIndex = vertexColors.IndexOf(color);
                                    if (colorIndex == -1)
                                    {
                                        colorIndex = vertexColors.Count;
                                        vertexColors.Add(color);
                                    }
                                }
                                else
                                {
                                    var normal = aiMesh.Normals[aiFaceIndex];
                                    normalIndex = vertexNormals.IndexOf(normal);
                                    if (normalIndex == -1)
                                    {
                                        normalIndex = vertexNormals.Count;
                                        vertexNormals.Add(normal);
                                    }
                                }

                                if (hasUVs)
                                {
                                    var uv = aiMesh.TextureCoordinateChannels[0][aiFaceIndex];
                                    uvIndex = vertexUVs.IndexOf(uv);
                                    if (uvIndex == -1)
                                    {
                                        uvIndex = vertexUVs.Count;
                                        vertexUVs.Add(uv);
                                    }
                                }

                                triangleIndices[(i * 3) + j] = new Index
                                {
                                    PositionIndex = ( ushort )positionIndex,
                                    NormalIndex   = ( ushort )normalIndex,
                                    ColorIndex    = ( ushort )colorIndex,
                                    UVIndex       = ( ushort )uvIndex
                                };
                            }
                        }

                        // Build display list
                        var displayList = new GXDisplayList(GXPrimitive.Triangles, triangleIndices);
                        mesh.DisplayLists.Add(displayList);

                        // Set up render params
                        var indexFlagsParam = new IndexAttributeFlagsParam(renderState.IndexFlags);
                        mesh.Parameters.Add(indexFlagsParam);

                        if (useColors)
                        {
                            mesh.Parameters.Add(new LightingParams(LightingParams.Preset.Colors));
                        }
                        else
                        {
                            mesh.Parameters.Add(new LightingParams(LightingParams.Preset.Normals));
                        }

                        mesh.Parameters.Add(new TextureParams(( ushort )(material.TextureId)));
                        mesh.Parameters.Add(new MipMapParams());
                        geometry.OpaqueMeshes.Add(mesh);
                    }

                    // Build vertex buffers
                    if (vertexPositions.Count > 0)
                    {
                        geometry.VertexBuffers.Add(new VertexPositionBuffer(vertexPositions.Select(x =>
                        {
                            Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeInverseWorldTransform);
                            return(AssimpHelper.FromAssimp(x));
                        }).ToArray()));
                    }

                    if (vertexNormals.Count > 0)
                    {
                        nodeInverseWorldTransform.Transpose();

                        geometry.VertexBuffers.Add(new VertexNormalBuffer(vertexNormals.Select(x =>
                        {
                            Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeInverseWorldTransform);
                            return(AssimpHelper.FromAssimp(x));
                        }).ToArray()));
                    }

                    if (vertexColors.Count > 0)
                    {
                        geometry.VertexBuffers.Add(new VertexColorBuffer(vertexColors.Select(AssimpHelper.FromAssimp).ToArray()));
                    }

                    if (vertexUVs.Count > 0)
                    {
                        geometry.VertexBuffers.Add(new VertexUVBuffer(vertexUVs.Select(x =>
                                                                                       UVCodec.Encode1023(AssimpHelper
                                                                                                          .FromAssimpAsVector2(x)))
                                                                      .ToArray()));
                    }
                }

                // Set sibling (next) reference of previous
                if (previousSibling != null)
                {
                    previousSibling.Sibling = node;
                }

                previousSibling = node;

                if (curAiNode.HasChildren)
                {
                    Node childPreviousSibling = null;
                    foreach (var aiChildNode in curAiNode.Children)
                    {
                        var childNode = ConvertHierarchyNodeRecursively(aiChildNode, ref childPreviousSibling, node, ref nodeWorldTransform);

                        // Make sure to set the 'first child' reference if we haven't already
                        if (node.Child == null)
                        {
                            node.Child = childNode;
                        }
                    }
                }

                return(node);
            }

            // Dummy!
            Node dummy    = null;
            var  identity = Assimp.Matrix4x4.Identity;

            return(ConvertHierarchyNodeRecursively(aiNode, ref dummy, null, ref identity));
        }
예제 #2
0
        private static void ProcessMeshParameters(List <Param> parameters, ref MeshRenderState state)
        {
            foreach (var param in parameters)
            {
                switch (param.Type)
                {
                case 0:
                {
                    var param0 = ( UnknownParam )param;
                    state.Param0Value1 = param0.Value1;
                    state.Param0Value2 = param0.Value2;
                }
                break;

                case MeshStateParamType.IndexAttributeFlags:
                    state.IndexFlags = ((GC.IndexAttributeFlagsParam)param).Flags;
                    break;

                case MeshStateParamType.Lighting:
                {
                    var lightingParams = ( LightingParams )param;
                    state.LightingParam1 = lightingParams.Value1;
                    state.LightingParam2 = lightingParams.Value2;
                }
                break;

                case ( MeshStateParamType )3:
                {
                    var param3 = ( UnknownParam )param;
                    state.Param3Value1 = param3.Value1;
                    state.Param3Value2 = param3.Value2;
                }
                break;


                case  MeshStateParamType.BlendAlpha:
                {
                    var blendAlphaParam = ( BlendAlphaParam )param;
                    state.BlendAlphaFlags = blendAlphaParam.Flags;
                }
                break;

                case MeshStateParamType.AmbientColor:
                {
                    var ambientColorParam = ( AmbientColorParam )param;
                    state.AmbientColor = ambientColorParam.Color;
                }
                break;

                case ( MeshStateParamType )6:
                {
                    var param6 = ( UnknownParam )param;
                    state.Param6Value1 = param6.Value1;
                    state.Param6Value2 = param6.Value2;
                }
                break;

                case ( MeshStateParamType )7:
                {
                    var param7 = ( UnknownParam )param;
                    state.Param7Value1 = param7.Value1;
                    state.Param7Value2 = param7.Value2;
                }
                break;

                case MeshStateParamType.Texture:
                {
                    var textureParams = ( TextureParams )param;
                    state.TextureId = textureParams.TextureId;
                    state.TileMode  = textureParams.TileMode;
                }
                break;

                case ( MeshStateParamType )9:
                {
                    var param9 = ( UnknownParam )param;
                    state.Param9Value1 = param9.Value1;
                    state.Param9Value2 = param9.Value2;
                }
                break;

                case MeshStateParamType.MipMap:
                {
                    var mipMapParams = ( MipMapParams )param;
                    state.MipMapParam1 = mipMapParams.Value1;
                    state.MipMapParam2 = mipMapParams.Value2;
                }
                break;

                default:
                    Debugger.Break();
                    break;
                }
            }
        }
예제 #3
0
        private void ConvertMeshes(List <Mesh> meshes, VertexPositionBuffer positionBuffer, VertexNormalBuffer normalBuffer, VertexColorBuffer colorBuffer, VertexUVBuffer uvBuffer)
        {
            var state = new MeshRenderState();

            for (var i = 0; i < meshes.Count; i++)
            {
                var mesh = meshes[i];

                if (mesh.Parameters != null && mesh.Parameters.Count > 0)
                {
                    ProcessMeshParameters(mesh.Parameters, ref state);
                }

                var stateCopy = state;
                stateCopy.TextureId = 0;
                stateCopy.TileMode  = 0;
                //stateCopy.IndexFlags = 0;
                stateCopy.AmbientColor = new Color();
                sUniqueStates.Add(stateCopy);

                var aiMesh      = new Assimp.Mesh();
                var vertexCache = new List <Vertex>();

                Debug.Assert(state.IndexFlags.HasFlag(IndexAttributeFlags.HasPosition) ? positionBuffer != null : true);
                Debug.Assert(state.IndexFlags.HasFlag(IndexAttributeFlags.HasNormal) ? normalBuffer != null : true);
                Debug.Assert(state.IndexFlags.HasFlag(IndexAttributeFlags.HasColor) ? colorBuffer != null : true);
                Debug.Assert(state.IndexFlags.HasFlag(IndexAttributeFlags.HasUV) ? uvBuffer != null : true);

                // Extract all vertices used by the triangles, and build a new vertex list
                // with each vertex attribute clumped together
                var aiFace = new Assimp.Face();
                foreach (var index in mesh.DisplayLists.SelectMany(x => x.ToTriangles()))
                {
                    var vertex = new Vertex();

                    if (state.IndexFlags.HasFlag(IndexAttributeFlags.HasPosition))
                    {
                        vertex.Position = positionBuffer.Elements[index.PositionIndex];
                    }

                    if (state.IndexFlags.HasFlag(IndexAttributeFlags.HasNormal))
                    {
                        vertex.Normal = normalBuffer.Elements[index.NormalIndex];
                    }

                    if (state.IndexFlags.HasFlag(IndexAttributeFlags.HasColor))
                    {
                        vertex.Color = colorBuffer.Elements[index.ColorIndex];
                    }

                    if (state.IndexFlags.HasFlag(IndexAttributeFlags.HasUV))
                    {
                        vertex.UV = uvBuffer.Elements[index.UVIndex];
                    }

                    // Find index of this vertex in the list in case it already exists
                    var vertexIndex = vertexCache.IndexOf(vertex);
                    if (vertexIndex == -1)
                    {
                        vertexIndex = vertexCache.Count;
                        vertexCache.Add(vertex);
                    }

                    aiFace.Indices.Add(vertexIndex);

                    if (aiFace.IndexCount == 3)
                    {
                        // Done with this face, move on to the next one
                        aiMesh.Faces.Add(aiFace);
                        aiFace = new Assimp.Face();
                    }
                }

                // Convert vertices
                aiMesh.Vertices.AddRange(vertexCache.Select(x => ToAssimp(x.Position)));

                if (state.IndexFlags.HasFlag(IndexAttributeFlags.HasNormal))
                {
                    aiMesh.Normals.AddRange(vertexCache.Select(x => ToAssimp(x.Normal)));
                }

                if (state.IndexFlags.HasFlag(IndexAttributeFlags.HasUV))
                {
                    aiMesh.TextureCoordinateChannels[0].AddRange(vertexCache.Select(x => ToAssimp(UVCodec.Decode1023(x.UV))));
                }

                if (state.IndexFlags.HasFlag(IndexAttributeFlags.HasColor))
                {
                    aiMesh.VertexColorChannels[0].AddRange(vertexCache.Select(x => ToAssimp(x.Color)));
                }

                // Convert material
                if (!mConvertedMaterialCache.TryGetValue(state, out var aiMaterialIndex))
                {
                    // Not in cache, so create a new one and add it
                    aiMaterialIndex = Scene.MaterialCount;
                    Scene.Materials.Add(CreateMaterial(Color.Gray, Color.Gray, Color.Gray, FormatTextureName(state.TextureId), false, false,
                                                       state.TileMode.HasFlag(TileMode.MirrorU),
                                                       state.TileMode.HasFlag(TileMode.MirrorV),
                                                       state.BlendAlphaFlags.HasFlag(BlendAlphaFlags.UseAlpha)));

                    mConvertedMaterialCache[state] = aiMaterialIndex;
                }

                aiMesh.MaterialIndex = aiMaterialIndex;

                // Add mesh to scene.
                Scene.Meshes.Add(aiMesh);
            }
        }
예제 #4
0
        private static IGeometry ConvertDisplayGeometry(Assimp.Node curAiNode, Assimp.Matrix4x4 nodeWorldTransform, List <Assimp.Mesh> aiMeshes, List <MaterialBuildInfo> materialBuildInfos)
        {
            var nodeInverseWorldTransform = nodeWorldTransform;

            nodeInverseWorldTransform.Inverse();
            var nodeInverseTransposeWorldTransform = nodeInverseWorldTransform;

            nodeInverseTransposeWorldTransform.Transpose();

            var geometry = new Geometry();

            // Convert meshes
            var vertexPositions = new List <Assimp.Vector3D>();
            var vertexNormals   = new List <Assimp.Vector3D>();
            var vertexUVs       = new List <Assimp.Vector3D>();
            var vertexColors    = new List <Assimp.Color4D>();
            var lastRenderState = new MeshRenderState();

            foreach (var aiMeshIndex in curAiNode.MeshIndices)
            {
                var aiMesh      = aiMeshes[aiMeshIndex];
                var material    = materialBuildInfos[aiMesh.MaterialIndex];
                var mesh        = new Mesh();
                var renderState = new MeshRenderState();

                renderState.IndexFlags = IndexAttributeFlags.HasPosition;
                var useColors  = false;
                var hasColors  = aiMesh.HasVertexColors(0);
                var hasUVs     = aiMesh.HasTextureCoords(0);
                var hasNormals = aiMesh.HasNormals;

                if (hasColors || !hasNormals)
                {
                    renderState.IndexFlags |= IndexAttributeFlags.HasColor;
                    useColors = true;
                }
                else
                {
                    renderState.IndexFlags |= IndexAttributeFlags.HasNormal;
                }

                if (hasUVs)
                {
                    renderState.IndexFlags |= IndexAttributeFlags.HasUV;
                }

                // Convert faces
                var triangleIndices = new Index[aiMesh.FaceCount * 3];
                for (var i = 0; i < aiMesh.Faces.Count; i++)
                {
                    var aiFace = aiMesh.Faces[i];

                    for (var j = 0; j < 3; j++)
                    {
                        var triangleIndicesIndex = (i * 3) + 2 - j;

                        if (j >= aiFace.IndexCount)
                        {
                            triangleIndices[triangleIndicesIndex] = triangleIndices[triangleIndicesIndex + 1];
                            continue;
                        }

                        int aiFaceIndex = aiFace.Indices[j];

                        var position      = aiMesh.Vertices[aiFaceIndex];
                        var positionIndex = vertexPositions.AddUnique(position);
                        if (positionIndex > byte.MaxValue)
                        {
                            renderState.IndexFlags |= IndexAttributeFlags.Position16BitIndex;
                        }

                        var normalIndex = 0;
                        var colorIndex  = 0;
                        var uvIndex     = 0;

                        if (useColors)
                        {
                            var color = hasColors ? aiMesh.VertexColorChannels[0][aiFaceIndex] : new Assimp.Color4D();
                            colorIndex = vertexColors.AddUnique(color);

                            if (colorIndex > byte.MaxValue)
                            {
                                renderState.IndexFlags |= IndexAttributeFlags.Color16BitIndex;
                            }
                        }
                        else
                        {
                            var normal = aiMesh.Normals[aiFaceIndex];
                            normalIndex = vertexNormals.AddUnique(normal);

                            if (normalIndex > byte.MaxValue)
                            {
                                renderState.IndexFlags |= IndexAttributeFlags.Normal16BitIndex;
                            }
                        }

                        if (hasUVs)
                        {
                            var uv = aiMesh.TextureCoordinateChannels[0][aiFaceIndex];
                            uvIndex = vertexUVs.AddUnique(uv);

                            if (uvIndex > byte.MaxValue)
                            {
                                renderState.IndexFlags |= IndexAttributeFlags.UV16BitIndex;
                            }
                        }

                        triangleIndices[triangleIndicesIndex] = new Index
                        {
                            PositionIndex = ( ushort )positionIndex,
                            NormalIndex   = ( ushort )normalIndex,
                            ColorIndex    = ( ushort )colorIndex,
                            UVIndex       = ( ushort )uvIndex
                        };
                    }
                }

                // Build display list
                var displayList = new GXDisplayList(GXPrimitive.Triangles, triangleIndices);
                mesh.DisplayLists.Add(displayList);

                // Set up render params
                if (renderState.IndexFlags != lastRenderState.IndexFlags)
                {
                    mesh.Parameters.Add(new IndexAttributeFlagsParam(renderState.IndexFlags));
                }

                // Set up render lighting params
                {
                    if (useColors)
                    {
                        renderState.LightingValue1 = 0x0b11;
                    }
                    else
                    {
                        renderState.LightingValue2 = 0x0011;
                    }

                    renderState.LightingValue2 = 1;

                    if (renderState.LightingValue1 != lastRenderState.LightingValue1 ||
                        renderState.LightingValue2 != lastRenderState.LightingValue2)
                    {
                        mesh.Parameters.Add(new LightingParams()
                        {
                            Value1 = renderState.LightingValue1,
                            Value2 = renderState.LightingValue2
                        });
                    }
                }

                // Set up render texture params
                {
                    renderState.TextureId = ( ushort )material.TextureId;
                    renderState.TileMode  = TileMode.WrapU | TileMode.WrapV;

                    if (renderState.TextureId != lastRenderState.TextureId ||
                        renderState.TileMode != lastRenderState.TileMode)
                    {
                        mesh.Parameters.Add(new TextureParams(renderState.TextureId, renderState.TileMode));
                    }
                }

                // Set up render mipmap params
                {
                    renderState.MipMapValue1 = 0x104a;
                    renderState.MipMapValue2 = 0;

                    if (renderState.MipMapValue1 != lastRenderState.MipMapValue1 ||
                        renderState.MipMapValue2 != lastRenderState.MipMapValue2)
                    {
                        mesh.Parameters.Add(new MipMapParams {
                            Value1 = renderState.MipMapValue1, Value2 = renderState.MipMapValue2
                        });
                    }
                }

                //if ( material.UseAlpha )
                //{
                //    mesh.Parameters.Add( new BlendAlphaParam() { Flags = BlendAlphaFlags.UseAlpha } );
                //    geometry.TranslucentMeshes.Add( mesh );
                //}
                //else
                //{
                //    geometry.OpaqueMeshes.Add( mesh );
                //}

                geometry.OpaqueMeshes.Add(mesh);
                lastRenderState = renderState;
            }

            // Build vertex buffers
            if (vertexPositions.Count > 0)
            {
                Debug.Assert(vertexPositions.Count <= ushort.MaxValue);
                var localVertexPositions = vertexPositions.Select(x =>
                {
                    Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeWorldTransform);
                    return(AssimpHelper.FromAssimp(x));
                }).ToArray();
                geometry.VertexBuffers.Add(new VertexPositionBuffer(localVertexPositions));
                geometry.Bounds = BoundingSphere.Calculate(localVertexPositions);
            }

            if (vertexNormals.Count > 0)
            {
                Debug.Assert(vertexNormals.Count <= ushort.MaxValue);
                geometry.VertexBuffers.Add(new VertexNormalBuffer(vertexNormals.Select(x =>
                {
                    Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref x, ref nodeInverseTransposeWorldTransform);
                    return(AssimpHelper.FromAssimp(x));
                }).ToArray()));
            }

            if (vertexColors.Count > 0)
            {
                Debug.Assert(vertexColors.Count <= ushort.MaxValue);
                geometry.VertexBuffers.Add(new VertexColorBuffer(vertexColors.Select(AssimpHelper.FromAssimp).ToArray()));
            }

            if (vertexUVs.Count > 0)
            {
                Debug.Assert(vertexUVs.Count <= ushort.MaxValue);
                geometry.VertexBuffers.Add(new VertexUVBuffer(vertexUVs.Select(x =>
                                                                               UVCodec.Encode255(AssimpHelper
                                                                                                 .FromAssimpAsVector2(x)))
                                                              .ToArray()));
            }

            return(geometry);
        }