Exemplo n.º 1
0
        static int FindDuplicate(List <int> hashes, List <VertexPositionNormalDiffuseTextureTwo> buf, int startIndex,
                                 ref VertexPositionNormalDiffuseTextureTwo search, int hash)
        {
            for (int i = startIndex; i < buf.Count; i++)
            {
                if (hashes[i] != hash)
                {
                    continue;
                }
                if (buf[i].Position != search.Position)
                {
                    continue;
                }
                if (buf[i].Normal != search.Normal)
                {
                    continue;
                }
                if (buf[i].TextureCoordinate != search.TextureCoordinate)
                {
                    continue;
                }
                if (buf[i].Diffuse != search.Diffuse)
                {
                    continue;
                }
                if (buf[i].TextureCoordinateTwo != search.TextureCoordinateTwo)
                {
                    continue;
                }
                return(i);
            }

            return(-1);
        }
Exemplo n.º 2
0
 public static int HashVert(ref VertexPositionNormalDiffuseTextureTwo vert)
 {
     unchecked {
         int hash = (int)2166136261;
         hash = hash * 16777619 ^ vert.Position.GetHashCode();
         hash = hash * 16777619 ^ vert.Normal.GetHashCode();
         hash = hash * 16777619 ^ vert.TextureCoordinate.GetHashCode();
         hash = hash * 16777619 ^ vert.TextureCoordinateTwo.GetHashCode();
         hash = hash * 16777619 ^ vert.Diffuse.GetHashCode();
         return(hash);
     }
 }
Exemplo n.º 3
0
        static VMeshDump ProcessRef(VMeshRef vms, ResourceManager resources)
        {
            var d = new VMeshDump();
            List <VertexPositionNormalDiffuseTextureTwo> verts = new List <VertexPositionNormalDiffuseTextureTwo>();
            List <int> hashes = new List <int>();

            for (int meshi = vms.StartMesh; meshi < vms.StartMesh + vms.MeshCount; meshi++)
            {
                var m  = vms.Mesh.Meshes[meshi];
                var dc = new VmsDrawcall();
                LibreLancer.Utf.Mat.Material mat;
                if ((mat = resources.FindMaterial(m.MaterialCrc)) != null)
                {
                    dc.Material = new ExportMaterial()
                    {
                        Name = mat.Name,
                        Dc   = mat.Dc
                    };
                }
                else
                {
                    dc.Material = new ExportMaterial()
                    {
                        Name = string.Format("material_0x{0:X8}", m.MaterialCrc),
                        Dc   = Color4.White
                    };
                }

                List <int> indices = new List <int>(m.NumRefVertices);
                for (int i = m.TriangleStart; i < m.TriangleStart + m.NumRefVertices; i++)
                {
                    int idx = vms.Mesh.Indices[i] + m.StartVertex + vms.StartVertex;
                    VertexPositionNormalDiffuseTextureTwo vert;
                    if (vms.Mesh.verticesVertexPosition != null)
                    {
                        vert = new VertexPositionNormalDiffuseTextureTwo()
                        {
                            Position = vms.Mesh.verticesVertexPosition[idx].Position
                        }
                    }
                    ;
                    else if (vms.Mesh.verticesVertexPositionNormal != null)
                    {
                        vert = new VertexPositionNormalDiffuseTextureTwo()
                        {
                            Position = vms.Mesh.verticesVertexPositionNormal[idx].Position,
                            Normal   = vms.Mesh.verticesVertexPositionNormal[idx].Normal
                        };
                    }
                    else if (vms.Mesh.verticesVertexPositionTexture != null)
                    {
                        vert = new VertexPositionNormalDiffuseTextureTwo()
                        {
                            Position          = vms.Mesh.verticesVertexPositionTexture[idx].Position,
                            TextureCoordinate = vms.Mesh.verticesVertexPositionTexture[idx].TextureCoordinate
                        };
                    }
                    else if (vms.Mesh.verticesVertexPositionNormalTexture != null)
                    {
                        vert = new VertexPositionNormalDiffuseTextureTwo()
                        {
                            Position          = vms.Mesh.verticesVertexPositionNormalTexture[idx].Position,
                            Normal            = vms.Mesh.verticesVertexPositionNormalTexture[idx].Normal,
                            TextureCoordinate = vms.Mesh.verticesVertexPositionNormalTexture[idx].TextureCoordinate
                        };
                    }
                    else if (vms.Mesh.verticesVertexPositionNormalTextureTwo != null)
                    {
                        vert = new VertexPositionNormalDiffuseTextureTwo()
                        {
                            Position             = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx].Position,
                            Normal               = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx].Normal,
                            TextureCoordinate    = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx].TextureCoordinate,
                            TextureCoordinateTwo = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx]
                                                   .TextureCoordinateTwo
                        };
                    }
                    else if (vms.Mesh.verticesVertexPositionNormalDiffuseTexture != null)
                    {
                        vert = new VertexPositionNormalDiffuseTextureTwo()
                        {
                            Position          = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx].Position,
                            Normal            = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx].Normal,
                            Diffuse           = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx].Diffuse,
                            TextureCoordinate = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx]
                                                .TextureCoordinate
                        };
                    }
                    else if (vms.Mesh.verticesVertexPositionNormalDiffuseTextureTwo != null)
                    {
                        vert = vms.Mesh.verticesVertexPositionNormalDiffuseTextureTwo[idx];
                    }
                    else
                    {
                        throw new Exception("something in state is real bad"); //Never called
                    }
                    var hash     = HashVert(ref vert);
                    int newIndex = FindDuplicate(hashes, verts, 0, ref vert, hash);
                    if (newIndex == -1)
                    {
                        newIndex = verts.Count;
                        verts.Add(vert);
                        hashes.Add(hash);
                    }

                    indices.Add(newIndex);
                }

                dc.Indices = indices.ToArray();
                d.Drawcalls.Add(dc);
            }

            d.Vertices = verts.ToArray();
            d.FVF      = vms.Mesh.OriginalFVF;
            return(d);
        }
Exemplo n.º 4
0
        static ColladaGeometry GetGeometry(CL.UpAxisType up, CL.geometry geo, CL.library_materials matlib, CL.library_effects fxlib)
        {
            var conv = new ColladaGeometry()
            {
                FVF = D3DFVF.XYZ
            };

            conv.Name = string.IsNullOrEmpty(geo.name) ? geo.id : geo.name;
            var msh = geo.Item as CL.mesh;

            if (msh == null)
            {
                return(null);
            }
            List <VertexPositionNormalDiffuseTextureTwo> vertices = new List <VertexPositionNormalDiffuseTextureTwo>();
            List <int>             hashes                    = new List <int>();
            List <ushort>          indices                   = new List <ushort>();
            List <ColladaDrawcall> drawcalls                 = new List <ColladaDrawcall>();
            Dictionary <string, GeometrySource> sources      = new Dictionary <string, GeometrySource>();
            Dictionary <string, float[]>        arrays       = new Dictionary <string, float[]>();
            Dictionary <string, GeometrySource> verticesRefs = new Dictionary <string, GeometrySource>();
            int placeHolderIdx = 0;

            //Get arrays
            foreach (var acc in msh.source)
            {
                var arr = acc.Item as CL.float_array;
                arrays.Add(arr.id, FloatArray(arr.Text));
            }
            //Accessors
            foreach (var acc in msh.source)
            {
                sources.Add(acc.id, new GeometrySource(acc, arrays));
            }
            //Process geometry
            foreach (var item in msh.Items)
            {
                if (!(item is CL.triangles || item is CL.polylist || item is CL.polygons))
                {
                    FLLog.Warning("Collada", "Ignoring " + item.GetType().Name + " element.");
                }
            }
            int totalTriangles = 0;

            foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist || x is CL.polygons))
            {
                if (item is CL.triangles)
                {
                    totalTriangles += (int)((CL.triangles)item).count;
                }
                else if (item is CL.polylist plist)
                {
                    totalTriangles += (int)plist.count;
                }
                else
                {
                    totalTriangles += (int)((CL.polygons)item).count;
                }
            }
            if (totalTriangles > 21845)
            {
                throw new Exception(string.Format(
                                        "Overflow!\nCollada geometry {0} has {1} triangles\nVMeshData has limit of 21845",
                                        string.IsNullOrEmpty(geo.name) ? geo.id : geo.name,
                                        totalTriangles));
            }
            foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist || x is CL.polygons))
            {
                CL.InputLocalOffset[] inputs;
                int[]           pRefs;
                int             indexCount;
                string          materialRef;
                ColladaMaterial material;
                if (item is CL.triangles)
                {
                    var triangles = (CL.triangles)item;
                    indexCount  = (int)(triangles.count * 3);
                    pRefs       = IntArray(triangles.p);
                    inputs      = triangles.input;
                    materialRef = triangles.material;
                }
                else if (item is CL.polygons polygons)
                {
                    indexCount = (int)(polygons.count * 3);
                    int j = 0;
                    pRefs = new int[indexCount];
                    foreach (var arr in polygons.Items)
                    {
                        if (!(arr is string))
                        {
                            throw new Exception("Polygons: ph element unsupported");
                        }
                        var ints = IntArray((string)arr);
                        if (ints.Length != 3)
                        {
                            throw new Exception("Polygons: non-triangle geometry not supported");
                        }
                        pRefs[j]     = ints[0];
                        pRefs[j + 1] = ints[1];
                        pRefs[j + 2] = ints[2];
                        j           += 3;
                    }
                    inputs      = polygons.input;
                    materialRef = polygons.material;
                }
                else
                {
                    var plist = (CL.polylist)item;
                    pRefs = IntArray(plist.p);
                    foreach (var c in IntArray(plist.vcount))
                    {
                        if (c != 3)
                        {
                            throw new Exception("Polylist: non-triangle geometry");
                        }
                    }
                    materialRef = plist.material;
                    inputs      = plist.input;
                    indexCount  = (int)(plist.count * 3);
                }
                if (indexCount == 0)
                {
                    continue;                  //Skip empty
                }
                material = ParseMaterial(materialRef, matlib, fxlib);
                int pStride = 0;
                foreach (var input in inputs)
                {
                    pStride = Math.Max((int)input.offset, pStride);
                }
                pStride++;
                GeometrySource sourceXYZ = null; int offXYZ = int.MinValue;
                GeometrySource sourceNORMAL = null; int offNORMAL = int.MinValue;
                GeometrySource sourceCOLOR = null; int offCOLOR = int.MinValue;
                GeometrySource sourceUV1 = null; int offUV1 = int.MinValue;
                GeometrySource sourceUV2 = null; int offUV2 = int.MinValue;
                int            texCount = 0;
                int            startIdx = indices.Count;
                foreach (var input in inputs)
                {
                    switch (input.semantic)
                    {
                    case SEM_VERTEX:
                        if (CheckURI(input.source) != msh.vertices.id)
                        {
                            throw new Exception("VERTEX doesn't match mesh vertices");
                        }
                        foreach (var ip2 in msh.vertices.input)
                        {
                            switch (ip2.semantic)
                            {
                            case SEM_POSITION:
                                offXYZ    = (int)input.offset;
                                sourceXYZ = sources[CheckURI(ip2.source)];
                                break;

                            case SEM_NORMAL:
                                offNORMAL    = (int)input.offset;
                                sourceNORMAL = sources[CheckURI(ip2.source)];
                                conv.FVF    |= D3DFVF.NORMAL;
                                break;

                            case SEM_COLOR:
                                offCOLOR    = (int)input.offset;
                                sourceCOLOR = sources[CheckURI(ip2.source)];
                                conv.FVF   |= D3DFVF.DIFFUSE;
                                break;

                            case SEM_TEXCOORD:
                                if (texCount == 2)
                                {
                                    throw new Exception("Too many texcoords!");
                                }
                                if (texCount == 1)
                                {
                                    offUV2    = (int)input.offset;
                                    sourceUV2 = sources[CheckURI(ip2.source)];
                                    conv.FVF &= ~D3DFVF.TEX1;
                                    conv.FVF |= D3DFVF.TEX2;
                                }
                                else
                                {
                                    offUV1    = (int)input.offset;
                                    sourceUV1 = sources[CheckURI(ip2.source)];
                                    if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2)
                                    {
                                        conv.FVF |= D3DFVF.TEX1;
                                    }
                                }
                                texCount++;
                                break;
                            }
                        }
                        break;

                    case SEM_POSITION:
                        offXYZ    = (int)input.offset;
                        sourceXYZ = sources[CheckURI(input.source)];
                        break;

                    case SEM_NORMAL:
                        offNORMAL    = (int)input.offset;
                        sourceNORMAL = sources[CheckURI(input.source)];
                        conv.FVF    |= D3DFVF.NORMAL;
                        break;

                    case SEM_COLOR:
                        offCOLOR    = (int)input.offset;
                        sourceCOLOR = sources[CheckURI(input.source)];
                        conv.FVF   |= D3DFVF.DIFFUSE;
                        break;

                    case SEM_TEXCOORD:
                        if (texCount == 2)
                        {
                            throw new Exception("Too many texcoords!");
                        }
                        if (texCount == 1)
                        {
                            offUV2    = (int)input.offset;
                            sourceUV2 = sources[CheckURI(input.source)];
                            conv.FVF &= ~D3DFVF.TEX1;
                            conv.FVF |= D3DFVF.TEX2;
                        }
                        else
                        {
                            offUV1    = (int)input.offset;
                            sourceUV1 = sources[CheckURI(input.source)];
                            if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2)
                            {
                                conv.FVF |= D3DFVF.TEX1;
                            }
                        }
                        texCount++;
                        break;
                    }
                }
                int vertexOffset = vertices.Count;
                for (int i = 0; i < indexCount; i++)
                {
                    int idx  = i * pStride;
                    var vert = new VertexPositionNormalDiffuseTextureTwo(
                        VecAxis(up, sourceXYZ.GetXYZ(pRefs[idx + offXYZ])),
                        offNORMAL == int.MinValue ? Vector3.Zero : VecAxis(up, sourceNORMAL.GetXYZ(pRefs[idx + offNORMAL])),
                        offCOLOR == int.MinValue ? (uint)Color4.White.ToRgba() : (uint)sourceCOLOR.GetColor(pRefs[idx + offCOLOR]).ToRgba(),
                        offUV1 == int.MinValue ? Vector2.Zero : sourceUV1.GetUV(pRefs[idx + offUV1]),
                        offUV2 == int.MinValue ? Vector2.Zero : sourceUV2.GetUV(pRefs[idx + offUV2])
                        );
                    var hash    = HashVert(ref vert);
                    var vertIdx = FindDuplicate(hashes, vertices, vertexOffset, ref vert, hash);
                    if (indices.Count >= ushort.MaxValue)
                    {
                        throw new Exception("Too many indices");
                    }
                    if (vertIdx == -1)
                    {
                        if (vertices.Count + 1 >= ushort.MaxValue)
                        {
                            throw new Exception("Too many vertices");
                        }
                        indices.Add((ushort)(vertices.Count - vertexOffset));
                        vertices.Add(vert);
                        hashes.Add(hash);
                    }
                    else
                    {
                        indices.Add((ushort)(vertIdx - vertexOffset));
                    }
                }
                drawcalls.Add(new ColladaDrawcall()
                {
                    StartIndex  = startIdx,
                    StartVertex = vertexOffset,
                    EndVertex   = vertices.Count - 1,
                    TriCount    = (indices.Count - startIdx) / 3,
                    Material    = material
                });
            }
            conv.Indices   = indices.ToArray();
            conv.Vertices  = vertices.ToArray();
            conv.Drawcalls = drawcalls.ToArray();
            conv.CalculateDimensions();
            return(conv);
        }
Exemplo n.º 5
0
        public VMeshData(byte[] data, ILibFile materialLibrary, string name)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (materialLibrary == null)
            {
                throw new ArgumentNullException("materialLibrary");
            }
            vmsname = name;
            ready   = false;

            using (BinaryReader reader = new BinaryReader(new MemoryStream(data)))
            {
                // Read the data header.
                MeshType             = reader.ReadUInt32();
                SurfaceType          = reader.ReadUInt32();
                MeshCount            = reader.ReadUInt16();
                IndexCount           = reader.ReadUInt16();
                FlexibleVertexFormat = (D3DFVF)reader.ReadUInt16();
                VertexCount          = reader.ReadUInt16();

                // Read the mesh headers.
                Meshes = new List <TMeshHeader>();
                int triangleStartOffset = 0;
                for (int count = 0; count < MeshCount; count++)
                {
                    TMeshHeader item = new TMeshHeader(reader, triangleStartOffset, materialLibrary);
                    triangleStartOffset += item.NumRefVertices;
                    Meshes.Add(item);
                }

                // Read the triangle data
                Indices = new ushort[IndexCount];
                for (int i = 0; i < IndexCount; i++)
                {
                    Indices[i] = reader.ReadUInt16();
                }

                // Read the vertex data.
                // The FVF defines what fields are included for each vertex.
                switch (FlexibleVertexFormat)
                {
                case D3DFVF.XYZ:     //(D3DFVF)0x0002:
                    verticesVertexPosition = new VertexPosition[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        verticesVertexPosition[i] = new VertexPosition(reader);
                    }
                    break;

                case D3DFVF.XYZ | D3DFVF.NORMAL:     //(D3DFVF)0x0012:
                    verticesVertexPositionNormal = new VertexPositionNormal[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        verticesVertexPositionNormal[i] = new VertexPositionNormal(reader);
                    }
                    break;

                case D3DFVF.XYZ | D3DFVF.TEX1:     //(D3DFVF)0x0102:
                    verticesVertexPositionNormalTexture = new VertexPositionNormalTexture[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        Vector3 position          = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle());
                        verticesVertexPositionNormalTexture[i] = new VertexPositionNormalTexture(position, Vector3.Zero, textureCoordinate);
                    }
                    CalculateNormals(verticesVertexPositionNormalTexture);
                    FlexibleVertexFormat |= D3DFVF.NORMAL;
                    break;

                case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX1:     //(D3DFVF)0x0112:
                    verticesVertexPositionNormalTexture = new VertexPositionNormalTexture[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        Vector3 position          = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        Vector3 normal            = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle());
                        verticesVertexPositionNormalTexture[i] = new VertexPositionNormalTexture(position, normal, textureCoordinate);
                    }
                    break;

                case D3DFVF.XYZ | D3DFVF.DIFFUSE | D3DFVF.TEX1:     //(D3DFVF)0x0142:
                    verticesVertexPositionNormalColorTexture = new VertexPositionNormalColorTexture[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        Vector3 position          = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        int     r                 = reader.ReadByte();
                        int     g                 = reader.ReadByte();
                        int     b                 = reader.ReadByte();
                        int     a                 = reader.ReadByte();
                        Color4  diffuse           = new Color4(r / 255f, g / 255f, b / 255f, a / 255f);
                        Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle());
                        verticesVertexPositionNormalColorTexture[i] = new VertexPositionNormalColorTexture(position, Vector3.Zero, diffuse, textureCoordinate);
                    }
                    FlexibleVertexFormat |= D3DFVF.NORMAL;
                    CalculateNormals(verticesVertexPositionNormalColorTexture);
                    break;

                case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.DIFFUSE | D3DFVF.TEX1:     //(D3DFVF)0x0152:
                    verticesVertexPositionNormalColorTexture = new VertexPositionNormalColorTexture[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        //verticesVertexPositionNormalDiffuseTexture[i] = new VertexPositionNormalDiffuseTexture(reader);
                        var     position          = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        var     normal            = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        int     r                 = reader.ReadByte();
                        int     g                 = reader.ReadByte();
                        int     b                 = reader.ReadByte();
                        int     a                 = reader.ReadByte();
                        Color4  diffuse           = new Color4(r / 255f, g / 255f, b / 255f, a / 255f);
                        Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle());
                        verticesVertexPositionNormalColorTexture[i] = new VertexPositionNormalColorTexture(position, normal, diffuse, textureCoordinate);
                    }
                    break;

                case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX2:     //(D3DFVF)0x0212:
                    verticesVertexPositionNormalTextureTwo = new VertexPositionNormalTextureTwo[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        verticesVertexPositionNormalTextureTwo[i] = new VertexPositionNormalTextureTwo(reader);
                    }
                    break;

                case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.DIFFUSE | D3DFVF.TEX2:     //(D3DFVF)0x0252:
                    verticesVertexPositionNormalDiffuseTextureTwo = new VertexPositionNormalDiffuseTextureTwo[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        verticesVertexPositionNormalDiffuseTextureTwo[i] = new VertexPositionNormalDiffuseTextureTwo(reader);
                    }
                    break;

                /*case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX4: //(D3DFVF)0x0412:
                 *  for (int i = 0; i < VertexCount; i++) vertices[i] = new VertexPositionNormalTextureTangentBinormal(reader);
                 *  break;*/
                default:
                    throw new FileContentException("UTF:VMeshData", "FVF 0x" + FlexibleVertexFormat + " not supported.");
                }
            }
        }
Exemplo n.º 6
0
        public VMeshData(ArraySegment <byte> data, ILibFile materialLibrary, string name)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (materialLibrary == null)
            {
                throw new ArgumentNullException("materialLibrary");
            }
            vmsname = name;
            ready   = false;

            using (BinaryReader reader = new BinaryReader(data.GetReadStream()))
            {
                // Read the data header.
                MeshType             = reader.ReadUInt32();
                SurfaceType          = reader.ReadUInt32();
                MeshCount            = reader.ReadUInt16();
                IndexCount           = reader.ReadUInt16();
                FlexibleVertexFormat = (D3DFVF)reader.ReadUInt16();
                OriginalFVF          = FlexibleVertexFormat;
                VertexCount          = reader.ReadUInt16();

                // Read the mesh headers.
                Meshes = new List <TMeshHeader>();
                int triangleStartOffset = 0;
                for (int count = 0; count < MeshCount; count++)
                {
                    TMeshHeader item = new TMeshHeader(reader, triangleStartOffset, materialLibrary);
                    if (item.NumRefVertices < 3)
                    {
                        FLLog.Warning("Vms", $"{name} mesh {count} references 0 triangles");
                    }
                    triangleStartOffset += item.NumRefVertices;
                    Meshes.Add(item);
                }

                // Read the triangle data
                Indices = new ushort[IndexCount];
                for (int i = 0; i < IndexCount; i++)
                {
                    Indices[i] = reader.ReadUInt16();
                }

                // Read the vertex data.
                // The FVF defines what fields are included for each vertex.
                switch (FlexibleVertexFormat)
                {
                case D3DFVF.XYZ:     //(D3DFVF)0x0002:
                    verticesVertexPosition = new VertexPosition[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        verticesVertexPosition[i] = new VertexPosition(reader);
                    }
                    break;

                case D3DFVF.XYZ | D3DFVF.NORMAL:     //(D3DFVF)0x0012:
                    verticesVertexPositionNormal = new VertexPositionNormal[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        verticesVertexPositionNormal[i] = new VertexPositionNormal(reader);
                    }
                    break;

                case D3DFVF.XYZ | D3DFVF.TEX1:     //(D3DFVF)0x0102:
                    verticesVertexPositionNormalTexture = new VertexPositionNormalTexture[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        Vector3 position          = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle());
                        verticesVertexPositionNormalTexture[i] = new VertexPositionNormalTexture(position, Vector3.One, textureCoordinate);
                    }
                    FlexibleVertexFormat |= D3DFVF.NORMAL;
                    break;

                case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX1:     //(D3DFVF)0x0112:
                    verticesVertexPositionNormalTexture = new VertexPositionNormalTexture[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        Vector3 position          = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        Vector3 normal            = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle());
                        verticesVertexPositionNormalTexture[i] = new VertexPositionNormalTexture(position, normal, textureCoordinate);
                    }
                    break;

                case D3DFVF.XYZ | D3DFVF.DIFFUSE | D3DFVF.TEX1:     //(D3DFVF)0x0142:
                    verticesVertexPositionNormalDiffuseTexture = new VertexPositionNormalDiffuseTexture[VertexCount];
                    Diffuse = new uint[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        Vector3 position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        Diffuse[i] = reader.ReadUInt32();
                        Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle());
                        verticesVertexPositionNormalDiffuseTexture[i] = new VertexPositionNormalDiffuseTexture(position, Vector3.One, Diffuse[i], textureCoordinate);
                    }
                    FlexibleVertexFormat |= D3DFVF.NORMAL;
                    break;

                case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.DIFFUSE | D3DFVF.TEX1:     //(D3DFVF)0x0152:
                    verticesVertexPositionNormalDiffuseTexture = new VertexPositionNormalDiffuseTexture[VertexCount];
                    Diffuse = new uint[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        var position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        var normal   = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        Diffuse[i] = reader.ReadUInt32();
                        Vector2 textureCoordinate = new Vector2(reader.ReadSingle(), 1 - reader.ReadSingle());
                        verticesVertexPositionNormalDiffuseTexture[i] = new VertexPositionNormalDiffuseTexture(position, normal, Diffuse[i], textureCoordinate);
                    }
                    break;

                case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX2:     //(D3DFVF)0x0212:
                    verticesVertexPositionNormalTextureTwo = new VertexPositionNormalTextureTwo[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        verticesVertexPositionNormalTextureTwo[i] = new VertexPositionNormalTextureTwo(reader);
                    }
                    break;

                case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.DIFFUSE | D3DFVF.TEX2:     //(D3DFVF)0x0252:
                    verticesVertexPositionNormalDiffuseTextureTwo = new VertexPositionNormalDiffuseTextureTwo[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        verticesVertexPositionNormalDiffuseTextureTwo[i] = new VertexPositionNormalDiffuseTextureTwo(reader);
                    }
                    break;

                /*case D3DFVF.XYZ | D3DFVF.NORMAL | D3DFVF.TEX4: //(D3DFVF)0x0412:
                 *  for (int i = 0; i < VertexCount; i++) vertices[i] = new VertexPositionNormalTextureTangentBinormal(reader);
                 *  break;*/
                default:
                    throw new FileContentException("UTF:VMeshData", "FVF 0x" + FlexibleVertexFormat + " not supported.");
                }
            }
        }
Exemplo n.º 7
0
        static ColladaGeometry GetGeometry(CL.UpAxisType up, CL.geometry geo)
        {
            var conv = new ColladaGeometry()
            {
                FVF = D3DFVF.XYZ
            };
            var msh = geo.Item as CL.mesh;

            if (msh == null)
            {
                return(null);
            }
            List <VertexPositionNormalDiffuseTextureTwo> vertices = new List <VertexPositionNormalDiffuseTextureTwo>();
            List <ushort>          indices                   = new List <ushort>();
            List <ColladaDrawcall> drawcalls                 = new List <ColladaDrawcall>();
            Dictionary <string, GeometrySource> sources      = new Dictionary <string, GeometrySource>();
            Dictionary <string, float[]>        arrays       = new Dictionary <string, float[]>();
            Dictionary <string, GeometrySource> verticesRefs = new Dictionary <string, GeometrySource>();

            //Get arrays
            foreach (var acc in msh.source)
            {
                var arr = acc.Item as CL.float_array;
                arrays.Add(arr.id, FloatArray(arr.Text));
            }
            //Accessors
            foreach (var acc in msh.source)
            {
                sources.Add(acc.id, new GeometrySource(acc, arrays));
            }
            //Process geometry
            if (msh.Items.Where(x => x is CL.triangles || x is CL.polylist).Count() != msh.Items.Length)
            {
                throw new Exception("Non-triangle geometry");
            }
            foreach (var item in msh.Items.Where(x => x is CL.triangles || x is CL.polylist))
            {
                CL.InputLocalOffset[] inputs;
                int[]  pRefs;
                int    triangleCount;
                string material;
                if (item is CL.triangles)
                {
                    var triangles = (CL.triangles)item;
                    pRefs         = IntArray(triangles.p);
                    inputs        = triangles.input;
                    triangleCount = (int)(triangles.count * 3);
                    material      = triangles.material;
                }
                else
                {
                    var plist = (CL.polylist)item;
                    pRefs = IntArray(plist.p);
                    foreach (var c in IntArray(plist.vcount))
                    {
                        if (c != 3)
                        {
                            throw new Exception("Polylist: non-triangle geometry");
                        }
                    }
                    material      = plist.material;
                    inputs        = plist.input;
                    triangleCount = (int)(plist.count * 3);
                }
                int pStride = 0;
                foreach (var input in inputs)
                {
                    pStride = Math.Max((int)input.offset, pStride);
                }
                pStride++;
                GeometrySource sourceXYZ = null; int offXYZ = int.MinValue;
                GeometrySource sourceNORMAL = null; int offNORMAL = int.MinValue;
                GeometrySource sourceCOLOR = null; int offCOLOR = int.MinValue;
                GeometrySource sourceUV1 = null; int offUV1 = int.MinValue;
                GeometrySource sourceUV2 = null; int offUV2 = int.MinValue;
                int            texCount = 0;
                int            startIdx = indices.Count;
                foreach (var input in inputs)
                {
                    switch (input.semantic)
                    {
                    case SEM_VERTEX:
                        if (CheckURI(input.source) != msh.vertices.id)
                        {
                            throw new Exception("VERTEX doesn't match mesh vertices");
                        }
                        foreach (var ip2 in msh.vertices.input)
                        {
                            switch (ip2.semantic)
                            {
                            case SEM_POSITION:
                                offXYZ    = (int)input.offset;
                                sourceXYZ = sources[CheckURI(ip2.source)];
                                break;

                            case SEM_NORMAL:
                                offNORMAL    = (int)input.offset;
                                sourceNORMAL = sources[CheckURI(ip2.source)];
                                conv.FVF    |= D3DFVF.NORMAL;
                                break;

                            case SEM_COLOR:
                                offCOLOR    = (int)input.offset;
                                sourceCOLOR = sources[CheckURI(ip2.source)];
                                conv.FVF   |= D3DFVF.DIFFUSE;
                                break;

                            case SEM_TEXCOORD:
                                if (texCount == 2)
                                {
                                    throw new Exception("Too many texcoords!");
                                }
                                if (texCount == 1)
                                {
                                    offUV2    = (int)input.offset;
                                    sourceUV2 = sources[CheckURI(ip2.source)];
                                    conv.FVF &= ~D3DFVF.TEX1;
                                    conv.FVF |= D3DFVF.TEX2;
                                }
                                else
                                {
                                    offUV1    = (int)input.offset;
                                    sourceUV1 = sources[CheckURI(ip2.source)];
                                    if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2)
                                    {
                                        conv.FVF |= D3DFVF.TEX1;
                                    }
                                }
                                texCount++;
                                break;
                            }
                        }
                        break;

                    case SEM_POSITION:
                        offXYZ    = (int)input.offset;
                        sourceXYZ = sources[CheckURI(input.source)];
                        break;

                    case SEM_NORMAL:
                        offNORMAL    = (int)input.offset;
                        sourceNORMAL = sources[CheckURI(input.source)];
                        conv.FVF    |= D3DFVF.NORMAL;
                        break;

                    case SEM_COLOR:
                        offCOLOR    = (int)input.offset;
                        sourceCOLOR = sources[CheckURI(input.source)];
                        conv.FVF   |= D3DFVF.DIFFUSE;
                        break;

                    case SEM_TEXCOORD:
                        if (texCount == 2)
                        {
                            throw new Exception("Too many texcoords!");
                        }
                        if (texCount == 1)
                        {
                            offUV2    = (int)input.offset;
                            sourceUV2 = sources[CheckURI(input.source)];
                            conv.FVF &= ~D3DFVF.TEX1;
                            conv.FVF |= D3DFVF.TEX2;
                        }
                        else
                        {
                            offUV1    = (int)input.offset;
                            sourceUV1 = sources[CheckURI(input.source)];
                            if ((conv.FVF & D3DFVF.TEX2) != D3DFVF.TEX2)
                            {
                                conv.FVF |= D3DFVF.TEX1;
                            }
                        }
                        texCount++;
                        break;
                    }
                }
                for (int i = 0; i < triangleCount; i++)
                {
                    int idx  = i * pStride;
                    var vert = new VertexPositionNormalDiffuseTextureTwo(
                        VecAxis(up, sourceXYZ.GetXYZ(pRefs[idx + offXYZ])),
                        offNORMAL == int.MinValue ? Vector3.Zero : VecAxis(up, sourceNORMAL.GetXYZ(pRefs[idx + offNORMAL])),
                        offCOLOR == int.MinValue ? Color4.White : sourceCOLOR.GetColor(pRefs[idx + offCOLOR]),
                        offUV1 == int.MinValue ? Vector2.Zero : sourceUV1.GetUV(pRefs[idx + offUV1]),
                        offUV2 == int.MinValue ? Vector2.Zero : sourceUV2.GetUV(pRefs[idx + offUV2])
                        );
                    var vertIdx = vertices.IndexOf(vert);
                    if (indices.Count >= ushort.MaxValue)
                    {
                        throw new Exception("Too many indices");
                    }
                    if (vertIdx == -1)
                    {
                        if (vertices.Count + 1 >= ushort.MaxValue)
                        {
                            throw new Exception("Overflow");
                        }
                        indices.Add((ushort)vertices.Count);
                        vertices.Add(vert);
                    }
                    else
                    {
                        indices.Add((ushort)vertIdx);
                    }
                }
                drawcalls.Add(new ColladaDrawcall()
                {
                    Start    = startIdx,
                    TriCount = (indices.Count - startIdx) / 3,
                    Material = string.IsNullOrEmpty(material) ? "NullMaterial" : material
                });
            }
            conv.Indices   = indices.ToArray();
            conv.Vertices  = vertices.ToArray();
            conv.Drawcalls = drawcalls.ToArray();
            conv.CalculateDimensions();
            return(conv);
        }