Example #1
0
 private void WriteGroup(int groupIndex, ref int baseIndex, ModelEntity model)
 {
     _streamWriter.WriteLine("g group" + groupIndex);
     _streamWriter.WriteLine("usemtl mtl{0}", model.TexturePage);
     for (var k = 0; k < model.Triangles.Length; k++)
     {
         _streamWriter.WriteLine("f {2}/{2}/{2} {1}/{1}/{1} {0}/{0}/{0}", baseIndex++, baseIndex++, baseIndex++);
     }
 }
Example #2
0
        private void WriteModel(ModelEntity model)
        {
            if (model.Texture != null)
            {
                if (_mtlExporter.AddMaterial((int)model.TexturePage))
                {
                    _pngExporter.Export(model.Texture, (int)model.TexturePage, _selectedPath);
                }
            }
            var worldMatrix = model.WorldMatrix;

            foreach (var triangle in model.Triangles)
            {
                var vertexColor0 = string.Empty;
                var vertexColor1 = string.Empty;
                var vertexColor2 = string.Empty;
                var c0           = triangle.Colors[0];
                var c1           = triangle.Colors[1];
                var c2           = triangle.Colors[2];
                if (_experimentalVertexColor)
                {
                    vertexColor0 = string.Format(" {0} {1} {2}", (c0.R).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c0.G).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c0.B).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture));
                    vertexColor1 = string.Format(" {0} {1} {2}", (c1.R).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c1.G).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c1.B).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture));
                    vertexColor2 = string.Format(" {0} {1} {2}", (c2.R).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c2.G).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c2.B).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture));
                }
                var v0 = Vector3.TransformPosition(triangle.Vertices[0], worldMatrix);
                var v1 = Vector3.TransformPosition(triangle.Vertices[1], worldMatrix);
                var v2 = Vector3.TransformPosition(triangle.Vertices[2], worldMatrix);
                _streamWriter.WriteLine("v {0} {1} {2} {3}", (v0.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v0.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v0.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), vertexColor0);
                _streamWriter.WriteLine("v {0} {1} {2} {3}", (v1.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v1.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v1.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), vertexColor1);
                _streamWriter.WriteLine("v {0} {1} {2} {3}", (v2.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v2.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v2.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), vertexColor2);
            }
            foreach (var triangle in model.Triangles)
            {
                var n0 = Vector3.TransformNormal(triangle.Normals[0], worldMatrix);
                var n1 = Vector3.TransformNormal(triangle.Normals[1], worldMatrix);
                var n2 = Vector3.TransformNormal(triangle.Normals[2], worldMatrix);
                _streamWriter.WriteLine("vn {0} {1} {2}", (n0.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n0.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n0.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture));
                _streamWriter.WriteLine("vn {0} {1} {2}", (n1.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n1.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n1.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture));
                _streamWriter.WriteLine("vn {0} {1} {2}", (n2.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n2.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n2.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture));
            }
            foreach (var triangle in model.Triangles)
            {
                var uv0 = triangle.Uv[0];
                var uv1 = triangle.Uv[1];
                var uv2 = triangle.Uv[2];
                _streamWriter.WriteLine("vt {0} {1}", uv0.X.ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (1f - uv0.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture));
                _streamWriter.WriteLine("vt {0} {1}", uv1.X.ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (1f - uv1.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture));
                _streamWriter.WriteLine("vt {0} {1}", uv2.X.ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (1f - uv2.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture));
            }
        }
Example #3
0
        private void ProccessPrimitive(BinaryReader reader, List <ModelEntity> modelEntities, List <Animation> animations, List <Texture> textures, uint primitiveIndex, uint primitiveSetTop, uint primitiveHeaderTop)
        {
            var groupedTriangles = new Dictionary <uint, List <Triangle> >();

            while (true)
            {
                reader.BaseStream.Seek(_offset + primitiveSetTop, SeekOrigin.Begin);
                var nextPrimitivePointer   = reader.ReadUInt32();
                var primitiveHeaderPointer = reader.ReadUInt32() * 4;
                ReadMappedValue(reader, out var typeCountMapped, out var typeCount);
                if (typeCount > Program.MaxHMDTypeCount)
                {
                    return;
                }
                for (var j = 0; j < typeCount; j++)
                {
                    //0: Polygon data 1: Shared polygon data 2: Image data 3: Animation data 4: MIMe data 5: Ground data

                    var type          = reader.ReadUInt32();
                    var developerId   = (type >> 27) & 0b00001111; //4
                    var category      = (type >> 24) & 0b00001111; //4
                    var driver        = (type >> 16) & 0b11111111; //8
                    var primitiveType = type & 0xFFFF;             //16

                    ReadMappedValue16(reader, out var dataCountMapped, out var dataCount);
                    ReadMappedValue16(reader, out var dataSizeMapped, out var dataSize);

                    if (dataCount > Program.MaxHMDDataSize)
                    {
                        return;
                    }
                    if (dataSize > Program.MaxHMDDataSize)
                    {
                        return;
                    }

                    if (category > 5)
                    {
                        return;
                    }

                    if (Program.Debug)
                    {
                        Program.Logger.WriteLine($"HMD Type: {type} of category {category} and primitive type {primitiveType}");
                    }

                    if (Program.Debug)
                    {
                        Program.Logger.WriteLine("Primitive type bits:" + new BitArray(BitConverter.GetBytes(primitiveType)).ToBitString());
                    }

                    if (category == 0)
                    {
                        if (Program.Debug)
                        {
                            Program.Logger.WriteLine($"HMD Non-Shared Vertices Geometry");
                        }

                        var polygonIndex = reader.ReadUInt32() * 4;
                        ProcessNonSharedGeometryData(groupedTriangles, reader, driver, primitiveType, primitiveHeaderPointer, nextPrimitivePointer, polygonIndex, dataSize);
                    }
                    else if (category == 1)
                    {
                        if (Program.Debug)
                        {
                            Program.Logger.WriteLine($"HMD Shared Vertices Geometry");
                        }
                    }
                    else if (category == 1)
                    {
                        if (Program.Debug)
                        {
                            Program.Logger.WriteLine($"HMD Image Data");
                        }
                        var hasClut = primitiveType == 1;
                        var texture = ProcessImageData(reader, driver, hasClut, primitiveHeaderPointer, nextPrimitivePointer);
                        if (texture != null)
                        {
                            textures.Add(texture);
                        }
                    }
                    else if (category == 3)
                    {
                        if (Program.Debug)
                        {
                            Program.Logger.WriteLine($"HMD Animation");
                        }
                    }
                    else if (category == 4)
                    {
                        var code1 = (primitiveType & 0b11100000) > 0;
                        var rst   = (primitiveType & 0b00010000) > 0;
                        var code0 = (primitiveType & 0b00001110) > 0;
                        if (Program.Debug)
                        {
                            Program.Logger.WriteLine($"HMD Mime Animation: {code1}|{rst}|{code0}");
                        }
                        //todo: docs are broken!
                        if (!code0)
                        {
                            var       diffTop   = reader.ReadUInt32() * 4;
                            Animation animation = null;
                            if (code1)
                            {
                                animation = ProcessMimeVertexData(groupedTriangles, reader, driver, primitiveType, primitiveHeaderPointer, nextPrimitivePointer, diffTop, dataSize, rst);
                            }
                            if (animation != null)
                            {
                                animations.Add(animation);
                            }
                        }
                    }
                    else if (category == 5)
                    {
                        if (Program.Debug)
                        {
                            Program.Logger.WriteLine($"HMD Grid");
                        }
                        var polygonIndex = reader.ReadUInt32() * 4;
                        var gridIndex    = reader.ReadUInt32() * 4;
                        var vertexIndex  = reader.ReadUInt32() * 4;
                        ProcessGroundData(groupedTriangles, reader, driver, primitiveType, primitiveHeaderPointer, nextPrimitivePointer, polygonIndex, dataCount / 4, gridIndex, vertexIndex);
                    }
                }
                if (nextPrimitivePointer != 0xFFFFFFFF)
                {
                    primitiveSetTop = nextPrimitivePointer * 4;
                    continue;
                }
                break;
            }
            foreach (var key in groupedTriangles.Keys)
            {
                var triangles = groupedTriangles[key];
                var model     = new ModelEntity
                {
                    Triangles   = triangles.ToArray(),
                    TexturePage = key,
                    TMDID       = primitiveIndex, //todo
                    //PrimitiveIndex = primitiveIndex
                };
                modelEntities.Add(model);
            }
        }
Example #4
0
        private RootEntity ParsePMD(BinaryReader reader)
        {
            var primPoint = reader.ReadUInt32();
            var vertPoint = reader.ReadUInt32();
            var nObj      = reader.ReadUInt32();

            if (nObj < 1 || nObj > 4000)
            {
                return(null);
            }
            var models = new List <ModelEntity>();

            for (var o = 0; o < nObj; o++)
            {
                var model     = new ModelEntity();
                var triangles = new List <Triangle>();
                var nPointers = reader.ReadUInt32();
                if (nPointers < 1 || nPointers > 4000)
                {
                    return(null);
                }
                for (var p = 0; p < nPointers; p++)
                {
                    var position = reader.BaseStream.Position;
                    var pointer  = reader.ReadUInt32();
                    reader.BaseStream.Seek(_offset + pointer, SeekOrigin.Begin);
                    var nPacket = reader.ReadUInt16();
                    if (nPacket > 4000)
                    {
                        return(null);
                    }
                    var primType = reader.ReadUInt16();
                    if (primType > 15)
                    {
                        return(null);
                    }
                    for (var pk = 0; pk < nPacket; pk++)
                    {
                        switch (primType)
                        {
                        case 0x00:
                            triangles.Add(ReadPolyFT3(reader));
                            break;

                        case 0x01:
                            triangles.AddRange(ReadPolyFT4(reader));
                            break;

                        case 0x02:
                            triangles.Add(ReadPolyGT3(reader));
                            break;

                        case 0x03:
                            triangles.AddRange(ReadPolyGT4(reader));
                            break;

                        case 0x04:
                            triangles.Add(ReadPolyF3(reader));
                            break;

                        case 0x05:
                            triangles.AddRange(ReadPolyF4(reader));
                            break;

                        case 0x06:
                            triangles.Add(ReadPolyG3(reader));
                            break;

                        case 0x07:
                            triangles.AddRange(ReadPolyG4(reader));
                            break;

                        case 0x08:
                            triangles.Add(ReadPolyFT3(reader, true, _offset + vertPoint));
                            break;

                        case 0x09:
                            triangles.AddRange(ReadPolyFT4(reader, true, _offset + vertPoint));
                            break;

                        case 0x0a:
                            triangles.Add(ReadPolyGT3(reader, true, _offset + vertPoint));
                            break;

                        case 0x0b:
                            triangles.AddRange(ReadPolyGT4(reader, true, _offset + vertPoint));
                            break;

                        case 0x0c:
                            triangles.Add(ReadPolyF3(reader, true, _offset + vertPoint));
                            break;

                        case 0x0d:
                            triangles.AddRange(ReadPolyF4(reader, true, _offset + vertPoint));
                            break;

                        case 0x0e:
                            triangles.Add(ReadPolyG3(reader, true, _offset + vertPoint));
                            break;

                        case 0x0f:
                            triangles.AddRange(ReadPolyG4(reader, true, _offset + vertPoint));
                            break;

                        default:
                            if (Program.Debug)
                            {
                                Program.Logger.WriteErrorLine("Unknown primitive:" + primType);
                            }
                            goto EndObject;
                        }
                    }
                    reader.BaseStream.Seek(position + 4, SeekOrigin.Begin);
                }
EndObject:
                model.Triangles = triangles.ToArray();
                models.Add(model);
            }

EndModel:
            if (models.Count > 0)
            {
                var entity = new RootEntity();
                foreach (var model in models)
                {
                    model.ParentEntity = entity;
                }
                entity.ChildEntities = models.ToArray();
                entity.ComputeBounds();
                return(entity);
            }
            return(null);
        }
Example #5
0
        private RootEntity ParseTmd(BinaryReader reader, string fileTitle)
        {
            var flags = reader.ReadUInt32();

            if (flags != 0 && flags != 1)
            {
                return(null);
            }

            var nObj = reader.ReadUInt32();

            if (nObj == 0 || nObj > Program.MaxTMDObjects)
            {
                return(null);
            }

            var models = new List <ModelEntity>();

            var objBlocks = new ObjBlock[nObj];

            var objOffset = reader.BaseStream.Position;

            for (var o = 0; o < nObj; o++)
            {
                var vertTop      = reader.ReadUInt32();
                var nVert        = reader.ReadUInt32();
                var normalTop    = reader.ReadUInt32();
                var nNormal      = reader.ReadUInt32();
                var primitiveTop = reader.ReadUInt32();
                var nPrimitive   = reader.ReadUInt32();
                var scale        = reader.ReadInt32();

                if (flags == 0)
                {
                    vertTop      += (uint)objOffset;
                    normalTop    += (uint)objOffset;
                    primitiveTop += (uint)objOffset;
                }

                if (nPrimitive > Program.MaxTMDPrimitives)
                {
                    return(null);
                }

                objBlocks[o] = new ObjBlock
                {
                    VertTop      = vertTop,
                    NVert        = nVert,
                    NormalTop    = normalTop,
                    NNormal      = nNormal,
                    PrimitiveTop = primitiveTop,
                    NPrimitive   = nPrimitive,
                    Scale        = scale
                };
            }

            for (uint o = 0; o < objBlocks.Length; o++)
            {
                var objBlock = objBlocks[o];

                var vertices = new Vector3[objBlock.NVert];
                if (Program.IgnoreTmdVersion && objBlock.VertTop < _offset)
                {
                    return(null);
                }
                reader.BaseStream.Seek(objBlock.VertTop, SeekOrigin.Begin);
                for (var v = 0; v < objBlock.NVert; v++)
                {
                    var vx  = reader.ReadInt16();
                    var vy  = reader.ReadInt16();
                    var vz  = reader.ReadInt16();
                    var pad = reader.ReadInt16();
                    if (pad != 0)
                    {
                        if (Program.Debug)
                        {
                            Program.Logger.WriteLine($"Found suspicious pad value of: {pad} at index:{v}");
                        }
                    }
                    var vertex = new Vector3
                    {
                        X = vx,
                        Y = vy,
                        Z = vz
                    };
                    vertices[v] = vertex;
                }

                var normals = new Vector3[objBlock.NNormal];
                if (Program.IgnoreTmdVersion && objBlock.NormalTop < _offset)
                {
                    return(null);
                }
                reader.BaseStream.Seek(objBlock.NormalTop, SeekOrigin.Begin);
                for (var n = 0; n < objBlock.NNormal; n++)
                {
                    var nx  = TMDHelper.ConvertNormal(reader.ReadInt16());
                    var ny  = TMDHelper.ConvertNormal(reader.ReadInt16());
                    var nz  = TMDHelper.ConvertNormal(reader.ReadInt16());
                    var pad = reader.ReadInt16();
                    if (pad != 0)
                    {
                        if (Program.Debug)
                        {
                            Program.Logger.WriteLine($"Found suspicious pad value of: {pad} at index:{n}");
                        }
                    }
                    var normal = new Vector3
                    {
                        X = nx,
                        Y = ny,
                        Z = nz
                    };
                    normals[n] = normal.Normalized();
                }

                var groupedTriangles = new Dictionary <uint, List <Triangle> >();

                reader.BaseStream.Seek(objBlock.PrimitiveTop, SeekOrigin.Begin);
                if (Program.IgnoreTmdVersion && objBlock.PrimitiveTop < _offset)
                {
                    return(null);
                }

                if (Program.Debug)
                {
                    Program.Logger.WriteLine($"Primitive count:{objBlock.NPrimitive} {fileTitle}");
                }
                for (var p = 0; p < objBlock.NPrimitive; p++)
                {
                    var olen            = reader.ReadByte();
                    var ilen            = reader.ReadByte();
                    var flag            = reader.ReadByte();
                    var mode            = reader.ReadByte();
                    var offset          = reader.BaseStream.Position;
                    var packetStructure = TMDHelper.CreateTMDPacketStructure(flag, mode, reader, p);
                    if (packetStructure != null)
                    {
                        TMDHelper.AddTrianglesToGroup(groupedTriangles, packetStructure, delegate(uint index)
                        {
                            if (index >= vertices.Length)
                            {
                                if (Program.IgnoreTmdVersion)
                                {
                                    return(new Vector3(index, 0, 0));
                                }
                                Program.Logger.WriteErrorLine("Vertex index error : " + fileTitle);
                                throw new Exception("Vertex index error: " + fileTitle);
                            }
                            return(vertices[index]);
                        }, delegate(uint index)
                        {
                            if (index >= normals.Length)
                            {
                                if (Program.IgnoreTmdVersion)
                                {
                                    return(new Vector3(index, 0, 0));
                                }
                                Program.Logger.WriteErrorLine("Vertex index error: " + fileTitle);
                                throw new Exception("Vertex index error: " + fileTitle);
                            }
                            return(normals[index]);
                        });
                    }
                    var newOffset = offset + ilen * 4;
                    if (Program.IgnoreTmdVersion && newOffset < _offset)
                    {
                        return(null);
                    }
                    reader.BaseStream.Seek(newOffset, SeekOrigin.Begin);
                }

                foreach (var kvp in groupedTriangles)
                {
                    var triangles = kvp.Value;
                    if (triangles.Count > 0)
                    {
                        var model = new ModelEntity
                        {
                            Triangles   = triangles.ToArray(),
                            TexturePage = kvp.Key,
                            TMDID       = o
                        };
                        models.Add(model);
                    }
                }
            }

            if (models.Count > 0)
            {
                var entity = new RootEntity();
                foreach (var model in models)
                {
                    model.ParentEntity = entity;
                }
                entity.ChildEntities = models.ToArray();
                entity.ComputeBounds();
                return(entity);
            }
            return(null);
        }
Example #6
0
        private static RootEntity ReadModels(BinaryReader reader)
        {
            var count = BRenderHelper.ReadU16BE(reader.BaseStream);

            if (count == 0 || count > 10000)
            {
                return(null);
            }
            var flags  = BRenderHelper.ReadU16BE(reader.BaseStream);
            var models = new List <ModelEntity>();

            for (var i = 0; i < count; i++)
            {
                var modelEntity = new ModelEntity();
                var radius      = (int)BRenderHelper.ReadU32BE(reader.BaseStream);
                for (var j = 0; j < 9; j++)
                {
                    for (var k = 0; k < 4; k++)
                    {
                        BRenderHelper.ReadU16BE(reader.BaseStream);
                    }
                }
                var countVerts = BRenderHelper.ReadU32BE(reader.BaseStream);
                if (countVerts == 0 || countVerts > 1000)
                {
                    return(null);
                }
                var vertices = new Vector3[countVerts];
                var normals  = new Vector3[countVerts];
                for (var j = 0; j < countVerts; j++)
                {
                    var x = (short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f;
                    var z = (short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f;
                    var y = -(short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f;
                    BRenderHelper.ReadU16BE(reader.BaseStream);
                    vertices[j] = new Vector3(x, y, z);
                }
                for (var j = 0; j < countVerts; j++)
                {
                    var x = (short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f;
                    var z = (short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f;
                    var y = -(short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f;
                    BRenderHelper.ReadU16BE(reader.BaseStream);
                    normals[j] = new Vector3(x, y, z);
                }
                var countFaces = BRenderHelper.ReadU32BE(reader.BaseStream);
                var triangles  = new List <Triangle>();
                //var header = Encoding.ASCII.GetString(reader.ReadBytes(64));
                for (var j = 0; j < countFaces; j++)
                {
                    var unk1 = reader.BaseStream.ReadByte();
                    var unk2 = reader.BaseStream.ReadByte();
                    var unk3 = reader.BaseStream.ReadByte();
                    var unk4 = reader.BaseStream.ReadByte();
                    var unk5 = reader.BaseStream.ReadByte();
                    var unk6 = reader.BaseStream.ReadByte();
                    var unk7 = reader.BaseStream.ReadByte();
                    var unk8 = reader.BaseStream.ReadByte();
                    var f0   = BRenderHelper.ReadU16BE(reader.BaseStream);
                    var f1   = BRenderHelper.ReadU16BE(reader.BaseStream);
                    var f2   = BRenderHelper.ReadU16BE(reader.BaseStream);
                    var f3   = BRenderHelper.ReadU16BE(reader.BaseStream);
                    if (f0 >= vertices.Length || f1 >= vertices.Length || f2 >= vertices.Length || f3 >= vertices.Length)
                    {
                        return(null);
                    }
                    var unk9      = BRenderHelper.ReadU16BE(reader.BaseStream);
                    var unk10     = reader.BaseStream.ReadByte();
                    var primFlags = reader.BaseStream.ReadByte();
                    var vertex0   = vertices[f0];
                    var vertex1   = vertices[f1];
                    var vertex2   = vertices[f2];
                    var normal0   = normals[f0];
                    var normal1   = normals[f1];
                    var normal2   = normals[f2];
                    //if (Math.Abs((normal0 + normal1 + normal2).Length) <= 0.0f)
                    //{
                    normal0 = Vector3.Cross(vertex1 - vertex0, vertex2 - vertex0).Normalized();
                    normal1 = normal0;
                    normal2 = normal0;
                    //}
                    triangles.Add(new Triangle
                    {
                        Vertices          = new[] { vertex0, vertex1, vertex2 },
                        Normals           = new[] { normal0, normal1, normal2 },
                        Colors            = new[] { Color.Grey, Color.Grey, Color.Grey },
                        Uv                = new[] { Vector3.Zero, Vector3.Zero, Vector3.Zero },
                        AttachableIndices = new [] { uint.MaxValue, uint.MaxValue, uint.MaxValue }
                    });
                    if ((primFlags & 0x8) != 0)
                    {
                        var vertex3 = vertices[f3];
                        var normal3 = normals[f3];
                        //if (Math.Abs((normal1 + normal3 + normal2).Length) <= 0.0f)
                        {
                            normal3 = Vector3.Cross(vertex3 - vertex1, vertex2 - vertex1).Normalized();
                            normal1 = normal3;
                            normal2 = normal3;
                        }
                        triangles.Add(new Triangle
                        {
                            Vertices          = new[] { vertex1, vertex3, vertex2 },
                            Normals           = new[] { normal1, normal3, normal2 },
                            Colors            = new[] { Color.Grey, Color.Grey, Color.Grey },
                            Uv                = new[] { Vector3.Zero, Vector3.Zero, Vector3.Zero },
                            AttachableIndices = new[] { uint.MaxValue, uint.MaxValue, uint.MaxValue }
                        });
                    }
                }
                modelEntity.Triangles = triangles.ToArray();
                models.Add(modelEntity);
            }
            if (models.Count > 0)
            {
                var entity = new RootEntity();
                foreach (var model in models)
                {
                    model.ParentEntity = entity;
                }
                entity.ChildEntities = models.ToArray();
                entity.ComputeBounds();
                return(entity);
            }
            return(null);
        }
Example #7
0
        private RootEntity ReadModels(BinaryReader reader, Dictionary <uint, List <Triangle> > groupedTriangles)
        {
            void AddTriangle(Triangle triangle, uint tPage)
            {
                List <Triangle> triangles;

                if (groupedTriangles.ContainsKey(tPage))
                {
                    triangles = groupedTriangles[tPage];
                }
                else
                {
                    triangles = new List <Triangle>();
                    groupedTriangles.Add(tPage, triangles);
                }
                triangles.Add(triangle);
            }

            //var id0 = reader.ReadByte();
            //var id1 = reader.ReadByte();
            //var id2 = reader.ReadByte();
            //var id3 = reader.ReadByte();
            //if ((char)id0 != 'P' || (char)id1 != 'S' || (char)id2 != 'I' || id3 != 1)
            //{
            //    return null;
            //}
            //
            //var version = reader.ReadUInt32();
            //var flags = reader.ReadUInt32();
            //var name = Encoding.ASCII.GetString(reader.ReadBytes(32));
            //var meshNum = reader.ReadUInt32();
            //var vertNum = reader.ReadUInt32();
            //var primNum = reader.ReadUInt32();
            //var primOffset = reader.ReadUInt32();
            //var animStart = reader.ReadUInt16();
            //var animEnd = reader.ReadUInt16();
            //var animNum = reader.ReadUInt32();
            //var animSegListOffset = reader.ReadUInt32();
            //var numTex = reader.ReadUInt32();
            //var texOff = reader.ReadUInt32();
            //var firstMeshOff = reader.ReadUInt32();
            //var radius = reader.ReadUInt32();
            //var pad = reader.ReadBytes(192 - 88);
            //
            //var models = new List<ModelEntity>();
            //var position = reader.BaseStream.Position;
            //{
            //    reader.BaseStream.Seek(_offset + firstMeshOff, SeekOrigin.Begin);
            //    var vertTop = reader.ReadUInt32();
            //    var vertCount = reader.ReadUInt32();
            //    var normTop = reader.ReadUInt32();
            //    var normCount = reader.ReadUInt32();
            //    var scale = reader.ReadUInt32();
            //
            //    var meshName = Encoding.ASCII.GetString(reader.ReadBytes(16));
            //    var childTop = reader.ReadUInt32();
            //    var nextTop = reader.ReadUInt32();
            //
            //    var numScaleKeys = reader.ReadUInt16();
            //    var numMoveKeys = reader.ReadUInt16();
            //    var numRotKeys = reader.ReadUInt16();
            //    var pad1 = reader.ReadUInt16();
            //
            //    var scaleKeysTop = reader.ReadUInt32();
            //    var moveKeysTop = reader.ReadUInt32();
            //    var rotateKeysTop = reader.ReadUInt32();
            //
            //    var sortListSize0 = reader.ReadUInt16();
            //    var sortListSize1 = reader.ReadUInt16();
            //    var sortListSize2 = reader.ReadUInt16();
            //    var sortListSize3 = reader.ReadUInt16();
            //    var sortListSize4 = reader.ReadUInt16();
            //    var sortListSize5 = reader.ReadUInt16();
            //    var sortListSize6 = reader.ReadUInt16();
            //    var sortListSize7 = reader.ReadUInt16();
            //
            //    var sortListSizeTop0 = reader.ReadUInt32();
            //    var sortListSizeTop1 = reader.ReadUInt32();
            //    var sortListSizeTop2 = reader.ReadUInt32();
            //    var sortListSizeTop3 = reader.ReadUInt32();
            //    var sortListSizeTop4 = reader.ReadUInt32();
            //    var sortListSizeTop5 = reader.ReadUInt32();
            //    var sortListSizeTop6 = reader.ReadUInt32();
            //    var sortListSizeTop7 = reader.ReadUInt32();
            //
            //    var lastScaleKey = reader.ReadUInt16();
            //    var lastMoveKey = reader.ReadUInt16();
            //    var lastRotKey = reader.ReadUInt16();
            //    var pad2 = reader.ReadUInt16();
            //}

#if SHORT_MAP_VERTNOS
            var BFF_FMA_MESH_ID  = 5;
            var BFF_FMA_MESH4_ID = 6;
#else
            var BFF_FMA_MESH_ID  = 1;
            var BFF_FMA_MESH4_ID = 4;
#endif

            var id0 = reader.ReadByte();
            var id1 = reader.ReadByte();
            var id2 = reader.ReadByte();
            var id3 = reader.ReadByte(); //4 or 1
            if ((char)id0 != 'F' || (char)id1 != 'M' || (char)id2 != 'M' || id3 != BFF_FMA_MESH_ID && id3 != BFF_FMA_MESH4_ID)
            {
                return(null);
            }

            var models = new List <ModelEntity>();

            //            // Version 1 mesh headers include flat-poly information. Like what skies used to.
            //#define BFF_FMA_MESH_ID (('F'<<0) | ('M'<<8) | ('M'<<16) | (1<<24))
            //            //#define BFF_FMA_SKYMESH_ID (('F'<<0) | ('M'<<8) | ('S'<<16) | (0<<24))
            //#define BFF_FMA_MESH4_ID (('F'<<0) | ('M'<<8) | ('M'<<16) | (4<<24))

            var length  = ReadInt(reader);
            var nameCrc = ReadLong(reader);

            var minX = ReadIntP(reader);
            var minY = ReadIntP(reader);
            var minZ = ReadIntP(reader);
            var maxX = ReadIntP(reader);
            var maxY = ReadIntP(reader);
            var maxZ = ReadIntP(reader);
            //
            //var offsetX = ReadIntP(reader);
            //var offsetY = ReadIntP(reader);
            //var offsetZ = ReadIntP(reader);
            //var rotX = ReadShort(reader);
            //var rotY = ReadShort(reader);
            //var rotZ = ReadShort(reader);
            //var rotW = ReadShort(reader);

            //var dummy1 = ReadShort(reader);
            //var dummy2 = ReadShort(reader);
            var polyListTop = ReadLong(reader);
            var dummy1      = ReadShort(reader);
            var dummy2      = ReadShort(reader);

            var radius = ReadInt(reader);

            var numVerts = ReadInt(reader);
            var vertsTop = ReadLong(reader);
            var position = reader.BaseStream.Position;
            //var offset = reader.BaseStream.Position - _offset;
            reader.BaseStream.Seek(_offset + vertsTop, SeekOrigin.Begin);
            // reader.BaseStream.Seek(288852, SeekOrigin.Begin);
            var vertices = new Vector3[numVerts];
            var uvs      = new Vector2[numVerts];
            for (var i = 0; i < numVerts; i++)
            {
                var x  = ReadShort(reader);
                var y  = ReadShort(reader);
                var z  = ReadShort(reader);
                var tu = reader.ReadByte();
                var tv = reader.ReadByte();
                vertices[i] = new Vector3(x, y, z);
                uvs[i]      = new Vector2(tu, tv);
            }

            using (var writer = File.CreateText("C:\\USERS\\RICKO\\DESKTOP\\TEST" + nameCrc + ".OBJ"))
            {
                foreach (var vertex in vertices)
                {
                    writer.WriteLine("v " + vertex.X + " " + vertex.Y + " " + vertex.Z);
                }
            }

            reader.BaseStream.Seek(position, SeekOrigin.Begin);

            var numGT3s  = ReadInt(reader);
            var primsTop = ReadInt(reader);
            position = reader.BaseStream.Position;
            reader.BaseStream.Seek(_offset + primsTop, SeekOrigin.Begin);
            if (id3 == BFF_FMA_MESH_ID)
            {
                for (var i = 0; i < numGT3s; i++) //FMA_GT3
                {
                    var r0   = reader.ReadByte();
                    var g0   = reader.ReadByte();
                    var b0   = reader.ReadByte();
                    var code = reader.ReadByte();
                    var u0   = reader.ReadByte();
                    var v0   = reader.ReadByte();
                    var clut = ReadPadData(reader);

                    var r1    = reader.ReadByte();
                    var g1    = reader.ReadByte();
                    var b1    = reader.ReadByte();
                    var pad1  = reader.ReadByte();
                    var u1    = reader.ReadByte();
                    var v1    = reader.ReadByte();
                    var tPage = ReadPadData(reader);

                    var r2   = reader.ReadByte();
                    var g2   = reader.ReadByte();
                    var b2   = reader.ReadByte();
                    var pad2 = reader.ReadByte();
                    var u2   = reader.ReadByte();
                    var v2   = reader.ReadByte();
                    var pad3 = ReadPadData(reader);

                    var vert0 = ReadIndex(reader);
                    var vert1 = ReadIndex(reader);
                    var vert2 = ReadIndex(reader);

                    var triangle = TriangleFromPrimitive(vertices,
                                                         vert0, vert1, vert2,
                                                         r0, g0, b0,
                                                         r1, g1, b1,
                                                         r2, g2, b2,
                                                         u0, v0,
                                                         u1, v1,
                                                         u2, v2);

                    AddTriangle(triangle, tPage);
                }
            }
            else
            {
                var vert0 = ReadIndex(reader);
                var vert1 = ReadIndex(reader);
                var vert2 = ReadIndex(reader);
                var vert3 = ReadIndex(reader);

                var triangle1 = ReadPolyGT3(reader, vertices, vert0, vert1, vert2, out var tPage1);
                //var triangle2 = ReadPolyGT3(reader, vertices, vert1, vert3, vert2, out var tPage2);
                AddTriangle(triangle1, tPage1);
                //AddTriangle(triangle2, 0);
            }

            reader.BaseStream.Seek(position, SeekOrigin.Begin);

            var numGT4s = ReadInt(reader);
            primsTop = ReadInt(reader);
            position = reader.BaseStream.Position;
            reader.BaseStream.Seek(_offset + primsTop, SeekOrigin.Begin);
            if (id3 == BFF_FMA_MESH_ID)
            {
                for (var i = 0; i < numGT4s; i++) //FMA_GT4
                {
                    var r0   = reader.ReadByte();
                    var g0   = reader.ReadByte();
                    var b0   = reader.ReadByte();
                    var code = reader.ReadByte();
                    var u0   = reader.ReadByte();
                    var v0   = reader.ReadByte();
                    var clut = ReadPadData(reader);

                    var r1    = reader.ReadByte();
                    var g1    = reader.ReadByte();
                    var b1    = reader.ReadByte();
                    var pad1  = reader.ReadByte();
                    var u1    = reader.ReadByte();
                    var v1    = reader.ReadByte();
                    var tPage = ReadPadData(reader);

                    var r2   = reader.ReadByte();
                    var g2   = reader.ReadByte();
                    var b2   = reader.ReadByte();
                    var pad2 = reader.ReadByte();
                    var u2   = reader.ReadByte();
                    var v2   = reader.ReadByte();
                    var pad3 = ReadPadData(reader);

                    var r3   = reader.ReadByte();
                    var g3   = reader.ReadByte();
                    var b3   = reader.ReadByte();
                    var pad4 = reader.ReadByte();
                    var u3   = reader.ReadByte();
                    var v3   = reader.ReadByte();
                    var pad5 = ReadPadData(reader);

                    var vert0 = ReadIndex(reader);
                    var vert1 = ReadIndex(reader);
                    var vert2 = ReadIndex(reader);
                    var vert3 = ReadIndex(reader);

                    var triangle1 = TriangleFromPrimitive(vertices,
                                                          vert0, vert1, vert2,
                                                          r0, g0, b0,
                                                          r1, g1, b1,
                                                          r2, g2, b2,
                                                          u0, v0,
                                                          u1, v1,
                                                          u2, v2);

                    var triangle2 = TriangleFromPrimitive(vertices,
                                                          vert1, vert3, vert2,
                                                          r1, g1, b1,
                                                          r3, g3, b3,
                                                          r2, g2, b2,
                                                          u1, v1,
                                                          u3, v3,
                                                          u2, v2);

                    AddTriangle(triangle1, tPage);
                    AddTriangle(triangle2, tPage);
                }
            }
            else
            {
                var vert0 = ReadIndex(reader);
                var vert1 = ReadIndex(reader);
                var vert2 = ReadIndex(reader);
                var vert3 = ReadIndex(reader);

                //two POLY_GT3
                var triangle1 = ReadPolyGT3(reader, vertices, vert0, vert1, vert2, out var tPage1);
                var triangle2 = ReadPolyGT3(reader, vertices, vert1, vert3, vert2, out var tPage2);
                AddTriangle(triangle1, tPage1);
                AddTriangle(triangle2, tPage2);
            }

            reader.BaseStream.Seek(position, SeekOrigin.Begin);

            var numTMaps = ReadInt(reader);
            var tMapsTop = ReadLong(reader);

            var numG3s = ReadInt(reader);
            primsTop = ReadInt(reader);
            position = reader.BaseStream.Position;
            reader.BaseStream.Seek(_offset + primsTop, SeekOrigin.Begin);
            for (var i = 0; i < numG3s; i++) //FMA_G3
            {
                var r0   = reader.ReadByte();
                var g0   = reader.ReadByte();
                var b0   = reader.ReadByte();
                var code = reader.ReadByte();

                var r1   = reader.ReadByte();
                var g1   = reader.ReadByte();
                var b1   = reader.ReadByte();
                var pad1 = reader.ReadByte();

                var r2   = reader.ReadByte();
                var g2   = reader.ReadByte();
                var b2   = reader.ReadByte();
                var pad2 = reader.ReadByte();

                var vert0 = ReadIndex(reader);
                var vert1 = ReadIndex(reader);
                var vert2 = ReadIndex(reader);

                var triangle = TriangleFromPrimitive(vertices,
                                                     vert0, vert1, vert2,
                                                     r0, g0, b0,
                                                     r1, g1, b1,
                                                     r2, g2, b2,
                                                     0, 0,
                                                     0, 0,
                                                     0, 0);

                AddTriangle(triangle, 0);
            }
            reader.BaseStream.Seek(position, SeekOrigin.Begin);

            var numG4s = ReadInt(reader);
            primsTop = ReadInt(reader);
            position = reader.BaseStream.Position;
            reader.BaseStream.Seek(_offset + primsTop, SeekOrigin.Begin);
            for (var i = 0; i < numG4s; i++) //FMA_G4
            {
                var r0   = reader.ReadByte();
                var g0   = reader.ReadByte();
                var b0   = reader.ReadByte();
                var code = reader.ReadByte();

                var r1   = reader.ReadByte();
                var g1   = reader.ReadByte();
                var b1   = reader.ReadByte();
                var pad1 = reader.ReadByte();

                var r2   = reader.ReadByte();
                var g2   = reader.ReadByte();
                var b2   = reader.ReadByte();
                var pad2 = reader.ReadByte();

                var r3   = reader.ReadByte();
                var g3   = reader.ReadByte();
                var b3   = reader.ReadByte();
                var pad3 = reader.ReadByte();

                var vert0 = ReadIndex(reader);
                var vert1 = ReadIndex(reader);
                var vert2 = ReadIndex(reader);
                var vert3 = ReadIndex(reader);

                var triangle1 = TriangleFromPrimitive(vertices,
                                                      vert0, vert1, vert2,
                                                      r0, g0, b0,
                                                      r1, g1, b1,
                                                      r2, g2, b2,
                                                      0, 0,
                                                      0, 0,
                                                      0, 0);

                var triangle2 = TriangleFromPrimitive(vertices,
                                                      vert1, vert3, vert2,
                                                      r1, g1, b1,
                                                      r3, g3, b3,
                                                      r2, g2, b2,
                                                      0, 0,
                                                      0, 0,
                                                      0, 0);


                AddTriangle(triangle1, 0);
                AddTriangle(triangle2, 0);
            }
            reader.BaseStream.Seek(position, SeekOrigin.Begin);

            foreach (var kvp in groupedTriangles)
            {
                var triangles = kvp.Value;
                if (triangles.Count > 0)
                {
                    var model = new ModelEntity
                    {
                        Triangles   = triangles.ToArray(),
                        TexturePage = kvp.Key,
                        TMDID       = 0
                    };
                    models.Add(model);
                }
            }

            if (models.Count > 0)
            {
                var entity = new RootEntity();
                foreach (var model in models)
                {
                    model.ParentEntity = entity;
                }
                entity.ChildEntities = models.ToArray();
                entity.ComputeBounds();
                return(entity);
            }

            return(null);
        }
Example #8
0
        private static RootEntity ReadModels(BinaryReader reader)
        {
            void AddTriangle(Dictionary <Tuple <uint, uint>, List <Triangle> > groupedTriangles, Triangle triangle, uint modelIndex, uint tPage)
            {
                var             tuple = new Tuple <uint, uint>(modelIndex, tPage);
                List <Triangle> triangles;

                if (groupedTriangles.ContainsKey(tuple))
                {
                    triangles = groupedTriangles[tuple];
                }
                else
                {
                    triangles = new List <Triangle>();
                    groupedTriangles.Add(tuple, triangles);
                }
                triangles.Add(triangle);
            }

            var version = reader.ReadByte();
            var magic2  = reader.ReadByte();
            var magic3  = reader.ReadByte();
            var magic4  = reader.ReadByte();

            if (version != 0x04 && version != 0x03 && version != 0x06)
            {
                return(null);
            }
            if (magic2 != 0x00 || magic3 != 0x02 || magic4 != 0x00)
            {
                return(null);
            }
            var metaPtr     = reader.ReadUInt32(); //todo: read meta
            var objectCount = reader.ReadUInt32();

            if (objectCount == 0 || objectCount > Program.MaxPSXObjectCount)
            {
                return(null);
            }
            var childEntities = new ModelEntity();
            var objectModels  = new PSXModel[objectCount];

            for (var i = 0; i < objectCount; i++)
            {
                var flags      = reader.ReadUInt32();
                var x          = (reader.ReadInt32() / 4096f) / 2.25f; // 4096f;
                var y          = (reader.ReadInt32() / 4096f) / 2.25f; // 4096f;
                var z          = (reader.ReadInt32() / 4096f) / 2.25f; // 4096f;
                var unk1       = reader.ReadUInt32();
                var unk2       = reader.ReadUInt16();
                var modelIndex = reader.ReadUInt16();
                var tx         = reader.ReadUInt16();
                var ty         = reader.ReadUInt16();
                var unk3       = reader.ReadUInt32();
                var palTop     = reader.ReadUInt32();
                objectModels[i] = new PSXModel(x, y, z, modelIndex);
            }
            var modelCount = reader.ReadUInt32();

            if (modelCount == 0 || modelCount > Program.MaxPSXObjectCount)
            {
                return(null);
            }
            var triangleGroups  = new Dictionary <Tuple <uint, uint>, List <Triangle> >();
            var modelEntities   = new List <ModelEntity>();
            var attachmentIndex = 0;

            for (uint i = 0; i < modelCount; i++)
            {
                var modelTop      = reader.ReadUInt32();
                var modelPosition = reader.BaseStream.Position;
                reader.BaseStream.Seek(modelTop, SeekOrigin.Begin);
                var flags       = version == 0x04 ? reader.ReadUInt16() : reader.ReadUInt32();
                var vertexCount = version == 0x04 ? reader.ReadUInt16() : reader.ReadUInt32();
                var planeCount  = version == 0x04 ? reader.ReadUInt16() : reader.ReadUInt32();
                var faceCount   = version == 0x04 ? reader.ReadUInt16() : reader.ReadUInt32();
                var radius      = reader.ReadUInt32();
                var xMax        = reader.ReadUInt16();
                var xMin        = reader.ReadUInt16();
                var yMax        = reader.ReadUInt16();
                var yMin        = reader.ReadUInt16();
                var zMax        = reader.ReadUInt16();
                var zMin        = reader.ReadUInt16();
                if (version == 0x04)
                {
                    var unk2 = reader.ReadUInt32();
                }

                var attachedIndices   = new Dictionary <uint, uint>();
                var attachableIndices = new Dictionary <uint, uint>();
                var vertices          = new Vector3[vertexCount];
                for (uint j = 0; j < vertexCount; j++)
                {
                    var x      = reader.ReadInt16(); //reader.ReadInt16() / 1f) / 2.25f;
                    var y      = reader.ReadInt16(); //reader.ReadInt16() / 1f) / 2.25f;
                    var z      = reader.ReadInt16(); //(reader.ReadInt16() / 1f) / 2.25f;
                    var pad    = reader.ReadInt16();
                    var vertex = new Vector3(
                        x / 1f / 2.25f,
                        y / 1f / 2.25f,
                        z / 1f / 2.25f
                        );
                    if (pad == 1)
                    {
                        attachableIndices.Add(j, (uint)attachmentIndex++);
                    }
                    else if (pad == 2)
                    {
                        attachedIndices.Add(j, (uint)y);
                    }

                    vertices[j] = vertex;
                }

                var normals = new Vector3[planeCount];
                for (uint j = 0; j < planeCount; j++)
                {
                    var x = reader.ReadInt16() / 4096f;
                    var y = reader.ReadInt16() / 4096f;
                    var z = reader.ReadInt16() / 4096f;
                    reader.ReadInt16();
                    normals[j] = new Vector3(
                        x, y, z
                        );
                }

                //uint faceFlags;
                //uint faceLength;
                //if (version == 0x03)
                //{
                //    faceFlags = reader.ReadUInt16();
                //    faceLength = reader.ReadUInt16();
                //}
                //else
                //{
                //    faceFlags = 0;
                //    faceLength = 0;
                //}
                for (uint j = 0; j < faceCount; j++)
                {
                    if (version == 0x04)
                    {
                        var   faceBegin  = reader.BaseStream.Position;
                        var   faceFlags  = reader.ReadUInt16();
                        var   faceLength = reader.ReadUInt16();
                        var   triangle   = (faceFlags & 0x0010) != 0;
                        var   gouraud    = (faceFlags & 0x0800) != 0;
                        var   textured   = (faceFlags & 0x0003) != 0;
                        var   invisible  = (faceFlags & 0x0080) != 0;
                        var   i0         = reader.ReadByte();
                        var   i1         = reader.ReadByte();
                        var   i2         = reader.ReadByte();
                        var   i3         = reader.ReadByte();
                        var   vertex0    = vertices[i0];
                        var   vertex1    = vertices[i1];
                        var   vertex2    = vertices[i2];
                        var   vertex3    = vertices[i3];
                        Color color0;
                        Color color1;
                        Color color2;
                        Color color3;
                        var   r0               = reader.ReadByte() / 255f;
                        var   g0               = reader.ReadByte() / 255f;
                        var   b0               = reader.ReadByte() / 255f;
                        var   command          = reader.ReadByte();
                        var   attachedIndex0   = attachedIndices.TryGetValue(i0, out var index0) ? index0 : uint.MaxValue;
                        var   attachedIndex1   = attachedIndices.TryGetValue(i1, out var index1) ? index1 : uint.MaxValue;
                        var   attachedIndex2   = attachedIndices.TryGetValue(i2, out var index2) ? index2 : uint.MaxValue;
                        var   attachedIndex3   = attachedIndices.TryGetValue(i3, out var index3) ? index3 : uint.MaxValue;
                        var   attachableIndex0 = attachableIndices.TryGetValue(i0, out var attIndex0) ? attIndex0 : uint.MaxValue;
                        var   attachableIndex1 = attachableIndices.TryGetValue(i1, out var attIndex1) ? attIndex1 : uint.MaxValue;
                        var   attachableIndex2 = attachableIndices.TryGetValue(i2, out var attIndex2) ? attIndex2 : uint.MaxValue;
                        var   attachableIndex3 = attachableIndices.TryGetValue(i3, out var attIndex3) ? attIndex3 : uint.MaxValue;
                        if (gouraud)
                        {
                            color0 = color1 = color2 = color3 = Color.Grey; //todo
                        }
                        else
                        {
                            color0 = color1 = color2 = color3 = new Color(r0, g0, b0);
                        }
                        //todo
                        var  planeIndex = reader.ReadUInt16();
                        var  surfFlags  = reader.ReadInt16();
                        var  normal0    = normals[planeIndex];
                        var  normal1    = normals[planeIndex];
                        var  normal2    = normals[planeIndex];
                        var  normal3    = normals[planeIndex];
                        var  uv0        = Vector3.Zero;
                        var  uv1        = Vector3.Zero;
                        var  uv2        = Vector3.Zero;
                        var  uv3        = Vector3.Zero;
                        uint tPage      = 0;
                        if (textured)
                        {
                            tPage = reader.ReadUInt32(); //todo
                            var u0 = reader.ReadByte() / 255f;
                            var v0 = reader.ReadByte() / 255f;
                            var u1 = reader.ReadByte() / 255f;
                            var v1 = reader.ReadByte() / 255f;
                            var u2 = reader.ReadByte() / 255f;
                            var v2 = reader.ReadByte() / 255f;
                            var u3 = reader.ReadByte() / 255f;
                            var v3 = reader.ReadByte() / 255f;
                            uv0 = new Vector3(u0, v0, 0f);
                            uv1 = new Vector3(u1, v1, 0f);
                            uv2 = new Vector3(u2, v2, 0f);
                            uv3 = new Vector3(u3, v3, 0f);
                        }
                        if (!invisible)
                        {
                            AddTriangle(triangleGroups, new Triangle
                            {
                                Vertices = new[] { vertex2, vertex1, vertex0 },
                                Normals  = new[] { normal2, normal1, normal0 },
                                Uv       = new[] { uv2, uv1, uv0 },
                                Colors   = new[] { color2, color1, color0 },
                                OriginalVertexIndices = new uint[] { i2, i1, i0 },
                                AttachedIndices       = new[] { attachedIndex2, attachedIndex1, attachedIndex0 },
                                AttachableIndices     = new[] { attachableIndex2, attachableIndex1, attachableIndex0 }
                            }, i, tPage);
                            if (!triangle)
                            {
                                AddTriangle(triangleGroups, new Triangle
                                {
                                    Vertices = new[] { vertex1, vertex2, vertex3 },
                                    Normals  = new[] { normal1, normal2, normal3 },
                                    Uv       = new[] { uv1, uv2, uv3 },
                                    Colors   = new[] { color1, color2, color3 },
                                    OriginalVertexIndices = new uint[] { i1, i2, i3 },
                                    AttachedIndices       = new[] { attachedIndex1, attachedIndex2, attachedIndex3 },
                                    AttachableIndices     = new[] { attachableIndex1, attachableIndex2, attachableIndex3 }
                                }, i, tPage);
                            }
                        }
                        reader.BaseStream.Seek(faceBegin + faceLength, SeekOrigin.Begin);
                    }
                    else
                    {
                        var   faceBegin  = reader.BaseStream.Position;
                        var   faceFlags  = reader.ReadUInt16();
                        var   faceLength = reader.ReadUInt16();
                        var   triangle   = (faceFlags & 0x0010) != 0;
                        var   gouraud    = (faceFlags & 0x0800) != 0;
                        var   textured   = (faceFlags & 0x0003) != 0;
                        var   invisible  = (faceFlags & 0x0080) != 0;
                        var   i0         = reader.ReadUInt16();
                        var   i1         = reader.ReadUInt16();
                        var   i2         = reader.ReadUInt16();
                        var   i3         = reader.ReadUInt16();
                        var   vertex0    = vertices[i0];
                        var   vertex1    = vertices[i1];
                        var   vertex2    = vertices[i2];
                        var   vertex3    = vertices[i3];
                        Color color0;
                        Color color1;
                        Color color2;
                        Color color3;
                        var   r0               = reader.ReadByte() / 255f;
                        var   g0               = reader.ReadByte() / 255f;
                        var   b0               = reader.ReadByte() / 255f;
                        var   command          = reader.ReadByte();
                        var   attachedIndex0   = attachedIndices.TryGetValue(i0, out var index0) ? index0 : uint.MaxValue;
                        var   attachedIndex1   = attachedIndices.TryGetValue(i1, out var index1) ? index1 : uint.MaxValue;
                        var   attachedIndex2   = attachedIndices.TryGetValue(i2, out var index2) ? index2 : uint.MaxValue;
                        var   attachedIndex3   = attachedIndices.TryGetValue(i3, out var index3) ? index3 : uint.MaxValue;
                        var   attachableIndex0 = attachableIndices.TryGetValue(i0, out var attIndex0) ? attIndex0 : uint.MaxValue;
                        var   attachableIndex1 = attachableIndices.TryGetValue(i1, out var attIndex1) ? attIndex1 : uint.MaxValue;
                        var   attachableIndex2 = attachableIndices.TryGetValue(i2, out var attIndex2) ? attIndex2 : uint.MaxValue;
                        var   attachableIndex3 = attachableIndices.TryGetValue(i3, out var attIndex3) ? attIndex3 : uint.MaxValue;
                        if (gouraud)
                        {
                            color0 = color1 = color2 = color3 = Color.Grey; //todo
                        }
                        else
                        {
                            color0 = color1 = color2 = color3 = new Color(r0, g0, b0);
                        }
                        //todo
                        var  planeIndex = reader.ReadUInt16();
                        var  surfFlags  = reader.ReadInt16();
                        var  normal0    = normals[planeIndex];
                        var  normal1    = normals[planeIndex];
                        var  normal2    = normals[planeIndex];
                        var  normal3    = normals[planeIndex];
                        var  uv0        = Vector3.Zero;
                        var  uv1        = Vector3.Zero;
                        var  uv2        = Vector3.Zero;
                        var  uv3        = Vector3.Zero;
                        uint tPage      = 0;
                        if (textured)
                        {
                            tPage = reader.ReadUInt32(); //todo
                            var u0 = reader.ReadByte() / 255f;
                            var v0 = reader.ReadByte() / 255f;
                            var u1 = reader.ReadByte() / 255f;
                            var v1 = reader.ReadByte() / 255f;
                            var u2 = reader.ReadByte() / 255f;
                            var v2 = reader.ReadByte() / 255f;
                            var u3 = reader.ReadByte() / 255f;
                            var v3 = reader.ReadByte() / 255f;
                            uv0 = new Vector3(u0, v0, 0f);
                            uv1 = new Vector3(u1, v1, 0f);
                            uv2 = new Vector3(u2, v2, 0f);
                            uv3 = new Vector3(u3, v3, 0f);
                        }
                        if (!invisible)
                        {
                            AddTriangle(triangleGroups, new Triangle
                            {
                                Vertices = new[] { vertex2, vertex1, vertex0 },
                                Normals  = new[] { normal2, normal1, normal0 },
                                Uv       = new[] { uv2, uv1, uv0 },
                                Colors   = new[] { color2, color1, color0 },
                                OriginalVertexIndices = new uint[] { i2, i1, i0 },
                                AttachedIndices       = new[] { attachedIndex2, attachedIndex1, attachedIndex0 },
                                AttachableIndices     = new[] { attachableIndex2, attachableIndex1, attachableIndex0 }
                            }, i, tPage);
                            if (!triangle)
                            {
                                AddTriangle(triangleGroups, new Triangle
                                {
                                    Vertices = new[] { vertex1, vertex2, vertex3 },
                                    Normals  = new[] { normal1, normal2, normal3 },
                                    Uv       = new[] { uv1, uv2, uv3 },
                                    Colors   = new[] { color1, color2, color3 },
                                    OriginalVertexIndices = new uint[] { i1, i2, i3 },
                                    AttachedIndices       = new[] { attachedIndex1, attachedIndex2, attachedIndex3 },
                                    AttachableIndices     = new[] { attachableIndex1, attachableIndex2, attachableIndex3 }
                                }, i, tPage);
                            }
                        }
                        reader.BaseStream.Seek(faceBegin + faceLength, SeekOrigin.Begin);
                    }
                }
                reader.BaseStream.Seek(modelPosition, SeekOrigin.Begin);
            }

            //var position = reader.BaseStream.Position;
            //reader.BaseStream.Seek(metaPtr, SeekOrigin.Begin);
            //for (; ; )
            //{
            //    var chunkId = reader.ReadBytes(4);
            //    if (chunkId[0] == 0xFF && chunkId[1] == 0xFF && chunkId[2] == 0xFF && chunkId[3] == 0xFF)
            //    {
            //        break;
            //    }
            //    var chunkString = Encoding.ASCII.GetString(chunkId);
            //    var chunkLength = reader.ReadUInt32();
            //    var chunkData = reader.ReadBytes((int)chunkLength);
            //};
            //reader.BaseStream.Seek(position, SeekOrigin.Begin);

            foreach (var psxModel in objectModels)
            {
                foreach (var kvp in triangleGroups)
                {
                    if (kvp.Key.Item1 == psxModel.ModelIndex)
                    {
                        var triangles = kvp.Value;
                        var model     = new ModelEntity
                        {
                            Triangles   = triangles.ToArray(),
                            TexturePage = kvp.Key.Item2,
                            TMDID       = 1, //todo
                            LocalMatrix = Matrix4.CreateTranslation(psxModel.X, psxModel.Y, psxModel.Z)
                        };
                        modelEntities.Add(model);
                    }
                }
            }
            RootEntity rootEntity;

            if (modelEntities.Count > 0)
            {
                rootEntity = new RootEntity();
                foreach (var modelEntity in modelEntities)
                {
                    modelEntity.ParentEntity = rootEntity;
                }
                rootEntity.ChildEntities = modelEntities.ToArray();
                rootEntity.ComputeBounds();
            }
            else
            {
                rootEntity = null;
            }
            return(rootEntity);
        }
Example #9
0
        public bool SetupAnimationFrame(float frameIndex, RootEntity[] checkedEntities, RootEntity selectedRootEntity, ModelEntity selectedModelEntity, bool updateMeshData = false)
        {
            _scene.SkeletonBatch.Reset();
            RootEntity rootEntity = null;

            if (selectedRootEntity != null)
            {
                rootEntity = selectedRootEntity;
            }
            else if (selectedModelEntity != null)
            {
                rootEntity = selectedModelEntity.GetRootEntity();
            }
            _scene.MeshBatch.SetupMultipleEntityBatch(checkedEntities, selectedModelEntity, selectedRootEntity, _scene.TextureBinder, updateMeshData || _scene.AutoAttach, false, true);
            return(ProcessAnimationObject(_animation.RootAnimationObject, frameIndex, rootEntity, Matrix4.Identity));
        }