コード例 #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 GC.Geometry ConvertBasicToGCGeometry(Basic.Geometry basicGeometry)
        {
            var geometry = new GC.Geometry();

            geometry.VertexBuffers.Add(new GC.VertexPositionBuffer(basicGeometry.VertexPositions));

            var positionFlags = GC.IndexAttributeFlags.HasPosition;

            if (basicGeometry.VertexCount > byte.MaxValue)
            {
                positionFlags |= GC.IndexAttributeFlags.Position16BitIndex;
            }

            var indexFlagsParams = new List <GC.IndexAttributeFlagsParam>();
            var normals          = new List <Vector3>();
            var uvs    = new List <Vector2 <short> >();
            var colors = new List <Color>();

            foreach (var basicMesh in basicGeometry.Meshes)
            {
                var basicMaterial = basicGeometry.Materials[basicMesh.MaterialId];
                var mesh          = new GC.Mesh();

                var indexFlags       = positionFlags;
                var useColors        = false;
                var hasColors        = basicMesh.Colors != null;
                var hasUVs           = basicMesh.UVs != null;
                var hasVertexNormals = basicGeometry.VertexNormals != null;
                var hasNormals       = hasVertexNormals || basicMesh.Normals != null;

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

                if (hasUVs)
                {
                    indexFlags |= GC.IndexAttributeFlags.HasUV;
                }

                //Debug.Assert( indexFlags == ( GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.HasNormal ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.Position16BitIndex | GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.Normal16BitIndex | GC.IndexAttributeFlags.HasNormal ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.HasColor ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.Position16BitIndex | GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.Color16BitIndex | GC.IndexAttributeFlags.HasColor ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.HasNormal | GC.IndexAttributeFlags.HasUV ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.Position16BitIndex | GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.Normal16BitIndex | GC.IndexAttributeFlags.HasNormal | GC.IndexAttributeFlags.HasUV ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.HasColor | GC.IndexAttributeFlags.HasUV ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.Position16BitIndex | GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.Color16BitIndex | GC.IndexAttributeFlags.HasColor | GC.IndexAttributeFlags.HasUV ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.HasNormal | GC.IndexAttributeFlags.UV16BitIndex | GC.IndexAttributeFlags.HasUV ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.Position16BitIndex | GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.Normal16BitIndex | GC.IndexAttributeFlags.HasNormal | GC.IndexAttributeFlags.UV16BitIndex | GC.IndexAttributeFlags.HasUV ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.HasColor | GC.IndexAttributeFlags.UV16BitIndex | GC.IndexAttributeFlags.HasUV ) ||
                //              indexFlags == ( GC.IndexAttributeFlags.Position16BitIndex | GC.IndexAttributeFlags.HasPosition | GC.IndexAttributeFlags.Color16BitIndex | GC.IndexAttributeFlags.HasColor | GC.IndexAttributeFlags.UV16BitIndex | GC.IndexAttributeFlags.HasUV ) );

                // Set up parameters
                var indexFlagsParam = new GC.IndexAttributeFlagsParam(indexFlags);
                mesh.Parameters.Add(indexFlagsParam);
                indexFlagsParams.Add(indexFlagsParam);

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

                mesh.Parameters.Add(new GC.TextureParams(( ushort )(basicMaterial.TextureId)));
                mesh.Parameters.Add(new GC.MipMapParams());

                // Build display list
                var basicTriangles = basicMesh.ToTriangles();
                for (int i = 0; i < basicTriangles.Length; i += 3)
                {
                    var temp = basicTriangles[i];
                    basicTriangles[i]     = basicTriangles[i + 2];
                    basicTriangles[i + 2] = temp;
                }

                var displayListIndices = new GC.Index[basicTriangles.Length];
                for (int i = 0; i < basicTriangles.Length; i++)
                {
                    var index      = new GC.Index();
                    var basicIndex = basicTriangles[i];
                    index.PositionIndex = basicIndex.VertexIndex;

                    if (useColors)
                    {
                        var color      = hasColors ? basicIndex.Color : Color.White;
                        var colorIndex = colors.IndexOf(color);
                        if (colorIndex == -1)
                        {
                            colorIndex = colors.Count;
                            colors.Add(color);
                        }

                        index.ColorIndex = ( ushort )colorIndex;
                    }
                    else
                    {
                        var normal      = hasVertexNormals ? basicGeometry.VertexNormals[basicIndex.VertexIndex] : basicIndex.Normal;
                        var normalIndex = normals.IndexOf(normal);
                        if (normalIndex == -1)
                        {
                            normalIndex = normals.Count;
                            normals.Add(normal);
                        }

                        index.NormalIndex = ( ushort )normalIndex;
                    }

                    if (hasUVs)
                    {
                        var uv      = basicIndex.UV;
                        var uvIndex = uvs.IndexOf(uv);
                        if (uvIndex == -1)
                        {
                            uvIndex = uvs.Count;
                            uvs.Add(uv);
                        }

                        index.UVIndex = ( ushort )uvIndex;
                    }

                    displayListIndices[i] = index;
                }

                var displayList = new GC.GXDisplayList(GC.GXPrimitive.Triangles, displayListIndices);
                mesh.DisplayLists.Add(displayList);
                geometry.OpaqueMeshes.Add(mesh);
            }

            if (normals.Count > 0)
            {
                if (normals.Count > byte.MaxValue)
                {
                    foreach (var param in indexFlagsParams)
                    {
                        if (param.Flags.HasFlag(GC.IndexAttributeFlags.HasNormal))
                        {
                            param.Flags |= GC.IndexAttributeFlags.Normal16BitIndex;
                        }
                    }
                }

                geometry.VertexBuffers.Add(new GC.VertexNormalBuffer(normals.ToArray()));
            }

            if (colors.Count > 0)
            {
                if (colors.Count > byte.MaxValue)
                {
                    foreach (var param in indexFlagsParams)
                    {
                        if (param.Flags.HasFlag(GC.IndexAttributeFlags.HasColor))
                        {
                            param.Flags |= GC.IndexAttributeFlags.Color16BitIndex;
                        }
                    }
                }

                geometry.VertexBuffers.Add(new GC.VertexColorBuffer(colors.ToArray()));
            }

            if (uvs.Count > 0)
            {
                if (uvs.Count > byte.MaxValue)
                {
                    foreach (var param in indexFlagsParams)
                    {
                        if (param.Flags.HasFlag(GC.IndexAttributeFlags.HasUV))
                        {
                            param.Flags |= GC.IndexAttributeFlags.UV16BitIndex;
                        }
                    }
                }

                geometry.VertexBuffers.Add(new GC.VertexUVBuffer(uvs.ToArray()));
            }

            geometry.Bounds = basicGeometry.Bounds;
            return(geometry);
        }
コード例 #3
0
        public void Read(EndianBinaryReader reader, MeshContext context)
        {
            var meshParamListOffset = reader.ReadInt32();
            var meshParamCount      = reader.ReadInt32();
            var displayListOffset   = reader.ReadInt32();
            var displayListSize     = reader.ReadInt32();

            reader.ReadAtOffset(meshParamListOffset, () =>
            {
                Parameters = new List <Param>();
                for (int i = 0; i < meshParamCount; i++)
                {
                    var type = ( MeshStateParamType )reader.ReadInt32();
                    Param param;

                    switch (type)
                    {
                    case MeshStateParamType.IndexAttributeFlags:
                        param = new IndexAttributeFlagsParam();
                        break;

                    case MeshStateParamType.Lighting:
                        param = new LightingParams();
                        break;

                    case MeshStateParamType.BlendAlpha:
                        param = new BlendAlphaParam();
                        break;

                    case MeshStateParamType.AmbientColor:
                        param = new AmbientColorParam();
                        break;

                    case MeshStateParamType.Texture:
                        param = new TextureParams();
                        break;

                    case MeshStateParamType.MipMap:
                        param = new MipMapParams();
                        break;

                    default:
                        param = new UnknownParam();
                        break;
                    }

                    param.ReadBody(type, reader);
                    Parameters.Add(param);
                }
            });

            // Hack(TGE): look up index attributes flag in params to parse display lists
            foreach (var param in Parameters)
            {
                if (param.Type == MeshStateParamType.IndexAttributeFlags)
                {
                    context.IndexAttributeFlags = (( IndexAttributeFlagsParam )param).Flags;
                }
            }

            reader.ReadAtOffset(displayListOffset, () =>
            {
                DisplayLists    = new List <GXDisplayList>();
                var endPosition = reader.Position + displayListSize;
                while (reader.ReadByte() != 0 && reader.Position < endPosition)
                {
                    reader.SeekCurrent(-1);
                    var displayList = reader.ReadObject <GXDisplayList>(context.IndexAttributeFlags);
                    DisplayLists.Add(displayList);
                }
            });
        }