Beispiel #1
0
        private short[] GetUsedVertexAttributes(GraphObject graphObject, int attribute)
        {
            HashSet <short> hashSet = new HashSet <short>();

            foreach (Part part in graphObject.parts)
            {
                foreach (Primitive primitive in batches[(int)part.BatchIndex].primitives)
                {
                    foreach (Vertex vertex in primitive.vertices)
                    {
                        switch (attribute)
                        {
                        case 0:
                            hashSet.Add(vertex.PositionIndex.GetValueOrDefault());
                            break;

                        case 1:
                            hashSet.Add(vertex.NormalIndex.GetValueOrDefault());
                            break;

                        case 2:
                            hashSet.Add(vertex.UVIndex[0].GetValueOrDefault());                                     // TEXCOORD0 (UVIndex[0]) only
                            break;
                        }
                    }
                }
            }
            return(hashSet.ToArray <short>());
        }
Beispiel #2
0
 private void btn_info_Click(object sender, EventArgs e)
 {
     if (tvw_models.SelectedNode.Tag is Bin)
     {
         Bin binMdl = (tvw_models.SelectedNode.Tag as Bin);
         MessageBox.Show($"Name: {binMdl.Name}\n"
                         + $"Visible: {binMdl.Visible}\n"
                         + $"Position: {binMdl.Position}\n"
                         + $"Rotation: {binMdl.Rotation}\n"
                         + $"Scale: {binMdl.Scale}",
                         $"Information of BIN model '{binMdl.Name}'", MessageBoxButtons.OK, MessageBoxIcon.Information);
     }
     else
     {
         GraphObject gObj   = (tvw_models.SelectedNode.Tag as GraphObject);
         string      rFlags = Enum.GetName(typeof(GraphObjectRenderFlags), gObj.RenderFlags);
         MessageBox.Show($"Visible: {gObj.Visible}\n"
                         + $"RenderFlags: {rFlags ?? "Unknown"}\n"
                         + $"PartCount: {gObj.PartCount}\n"
                         + $"BoundingBox: Min: {gObj.BoundingBox.Min}, Max: {gObj.BoundingBox.Max}\n"
                         + $"Position: {gObj.Position}\n"
                         + $"Rotation: {gObj.Rotation}\n"
                         + $"Scale: {gObj.Scale}",
                         $"Information of BIN Graph{tvw_models.SelectedNode.Text}", MessageBoxButtons.OK, MessageBoxIcon.Information);
     }
 }
Beispiel #3
0
        void RenderGraphObject(GraphObject graphObject, RenderFlags renderFlags)
        {
            // visibility check
            if (!graphObject.Visible)
            {
                return;
            }

            // render-flag check
            if (!renderFlags.HasFlag(RenderFlags.Ceilings) && graphObject.HasRenderFlag(GraphObjectRenderFlags.Ceiling))
            {
                return;
            }
            if (!renderFlags.HasFlag(RenderFlags.FourthWalls) && graphObject.HasRenderFlag(GraphObjectRenderFlags.FourthWall))
            {
                return;
            }

            // matrix transformations
            GL.PushMatrix();
            TransformMatrix(graphObject.Position, graphObject.Rotation, graphObject.Scale);

            // bounding box
            if (renderFlags.HasFlag(RenderFlags.BoundingBox))
            {
                GL.Disable(EnableCap.Lighting);
                GL.Disable(EnableCap.Texture2D);
                GL.Color3(Color.Yellow);
                GLUtility.WireCube(graphObject.BoundingBox * GlobalScaleReciprocal);
                GL.Color3(Color.White);
                GL.Enable(EnableCap.Texture2D);
                GL.Enable(EnableCap.Lighting);
            }

            if (graphObject.HasRenderFlag(GraphObjectRenderFlags.FullBright))
            {
                GL.Disable(EnableCap.Lighting);
            }

            // Render parts.
            foreach (var part in graphObject)
            {
                if (shaders[part.ShaderIndex].Tint.A > 0 && ((shaders[part.ShaderIndex].Tint.A == Color.Opaque && renderFlags.HasFlag(RenderFlags.Opaque)) || (shaders[part.ShaderIndex].Tint.A < Color.Opaque && renderFlags.HasFlag(RenderFlags.Translucent))))
                {
                    RenderPart(part, renderFlags);
                }
            }

            GL.Enable(EnableCap.Lighting);

            // Render children.
            for (int childIndex = graphObject.ChildIndex; childIndex >= 0; childIndex = graphObjects[childIndex].NextIndex)
            {
                RenderGraphObject(graphObjects[childIndex], renderFlags);
            }

            GL.PopMatrix();
        }
Beispiel #4
0
        GraphObject GetGraphObject(int index)
        {
            const int itemSize = 0x8C;

            binaryReader.Goto(GraphOffset + itemSize * index);
            binaryReader.PositionAnchor = GraphOffset;
            GraphObject graphObject = new GraphObject(binaryReader);

            binaryReader.ResetAnchor();
            binaryReader.Back();

            return(graphObject);
        }
Beispiel #5
0
        GraphObject[] GetGraphObjects(int index)
        {
            List <GraphObject> graphObjects = new List <GraphObject>(10);
            GraphObject        graphObject  = GetGraphObject(index);

            graphObjects.Add(graphObject);

            if (graphObject.ChildIndex >= 0)
            {
                graphObjects.AddRange(GetGraphObjects(graphObject.ChildIndex));
            }

            if (graphObject.NextIndex >= 0)
            {
                graphObjects.AddRange(GetGraphObjects(graphObject.NextIndex));
            }

            return(graphObjects.ToArray());
        }
Beispiel #6
0
        private void ExportGraphObject(string outputFolder, int index, bool onlyVisible, bool ignoreTransforms, bool swapU, bool swapV, bool exportTextures, ImageFormat textureFormat)
        {
            GraphObject graphObject = graphObjects[index];

            if (graphObject.Visible && graphObject.PartCount > 0)
            {
                using (StreamWriter streamWriter = File.CreateText(Path.Combine(outputFolder, string.Format("object{0}.obj", index))))
                    using (StreamWriter streamWriter2 = (exportTextures) ? File.CreateText(Path.Combine(outputFolder, string.Format("object{0}.mtl", index))) : null)
                    {
                        if (exportTextures)
                        {
                            streamWriter2.WriteLine("# object{0}.mtl converted at {1} using Demolisher v{2} by arookas", index, DateTime.Now, Program.Version);
                        }

                        streamWriter.WriteLine("# object{0}.obj converted at {1} using Demolisher v{2} by arookas", index, DateTime.Now, Program.Version);
                        if (exportTextures)
                        {
                            streamWriter.WriteLine("mtllib object{0}.mtl", index);
                        }
                        short[]   posIndices = GetUsedVertexAttributes(graphObject, 0);
                        Vector3[] array      = CollectionHelper.Initialize <Vector3>(posIndices.Length, (int i) => positions[(int)posIndices[i]]);
                        if (!ignoreTransforms)
                        {
                            array.Transform(delegate(Vector3 oP)
                            {
                                Vector3 vector4 = Vector3.Zero;
                                Vector3 left    = Vector3.Zero;
                                Vector3 vector5 = Vector3.One;
                                for (int num2 = index; num2 >= 0; num2 = (int)graphObjects[num2].ParentIndex)
                                {
                                    vector4 += graphObjects[num2].Position;
                                    left    += graphObjects[num2].Rotation;
                                    vector5  = Vector3.Multiply(vector5, graphObjects[num2].Scale);
                                }
                                Vector3 left2 = Vector3.Multiply(oP, vector5);
                                return(left2 + vector4 * 0.0039f);
                            });
                        }
                        streamWriter.WriteLine();
                        streamWriter.WriteLine("# vertices");
                        foreach (Vector3 vector in array)
                        {
                            TextWriter textWriter = streamWriter;
                            string     format     = "v {0} {1} {2}";
                            float      x          = vector.X;
                            object     arg        = x.ToString(CultureInfo.InvariantCulture);
                            float      y          = vector.Y;
                            object     arg2       = y.ToString(CultureInfo.InvariantCulture);
                            float      z          = vector.Z;
                            textWriter.WriteLine(format, arg, arg2, z.ToString(CultureInfo.InvariantCulture));
                        }
                        short[]   normalIndices = GetUsedVertexAttributes(graphObject, 1);
                        Vector3[] array3        = CollectionHelper.Initialize <Vector3>(normalIndices.Length, (int i) => normals[(int)normalIndices[i]]);
                        streamWriter.WriteLine();
                        streamWriter.WriteLine("# normals");
                        foreach (Vector3 vector2 in array3)
                        {
                            TextWriter textWriter2 = streamWriter;
                            string     format2     = "vn {0} {1} {2}";
                            float      x2          = vector2.X;
                            object     arg3        = x2.ToString(CultureInfo.InvariantCulture);
                            float      y2          = vector2.Y;
                            object     arg4        = y2.ToString(CultureInfo.InvariantCulture);
                            float      z2          = vector2.Z;
                            textWriter2.WriteLine(format2, arg3, arg4, z2.ToString(CultureInfo.InvariantCulture));
                        }
                        short[]   uvIndices = GetUsedVertexAttributes(graphObject, 2);
                        Vector2[] array5    = CollectionHelper.Initialize <Vector2>(uvIndices.Length, (int i) => texCoord0s[(int)uvIndices[i]]);             // TODO: Because the legacy code only worked with TEXCOORDS0, we ignore TEXCOORDS1. TEXCOORDS1 could be implemented in the future with a format other than OBJ.
                        streamWriter.WriteLine();
                        streamWriter.WriteLine("# uvs");
                        foreach (Vector2 vector3 in array5)
                        {
                            streamWriter.WriteLine("vt {0} {1}", (swapU ? (-vector3.X) : vector3.X).ToString(CultureInfo.InvariantCulture), (swapV ? (-vector3.Y) : vector3.Y).ToString(CultureInfo.InvariantCulture));
                        }
                        streamWriter.WriteLine();
                        streamWriter.WriteLine("# faces");
                        int num = 0;
                        foreach (Part part in graphObject.parts)
                        {
                            streamWriter.WriteLine();
                            for (int texUnit = 0; texUnit < 8; texUnit++)
                            {
                                if (shaders[(int)part.ShaderIndex].MaterialIndex[texUnit] < 0)
                                {
                                    streamWriter.WriteLine("g object{0}_part{1}", index, num++);
                                }
                                else
                                {
                                    int      objIndex = num++;
                                    Shader   objShd   = shaders[(int)part.ShaderIndex];
                                    Material objMat   = materials[objShd.MaterialIndex[texUnit]];

                                    // Start faces group with texture material (smoothing off)
                                    streamWriter.WriteLine("g object{0}_part{1}_texture{2}", index, objIndex, objMat.textureIndex);
                                    // Material definition is still written, even if exportTextures/mtl isnt specified
                                    streamWriter.WriteLine("usemtl object{0}_part{1}_texture{2}", index, objIndex, objMat.textureIndex); // We still specify a material, so one can add textures later
                                    streamWriter.WriteLine("s 1");                                                                       // Smoothing groups on, so groups are imported and not ignored

                                    // Save texture to file
                                    if (exportTextures)
                                    {
                                        Bitmap tex = textures[objMat.textureIndex].ToBitmap();
                                        tex.Save(Path.Combine(outputFolder, string.Format("object{0}_part{1}_texture{2}.{3}", index, objIndex, objMat.textureIndex, textureFormat.GetExtension())), textureFormat);

                                        // Write texture material information
                                        streamWriter2.WriteLine();
                                        streamWriter2.WriteLine("# object{0} - part{1} - texture{2}", index, objIndex, objMat.textureIndex);
                                        streamWriter2.WriteLine("# WrapS - {0}", objMat.wrapS.ToString());
                                        streamWriter2.WriteLine("# WrapT - {0}", objMat.wrapT.ToString());
                                        streamWriter2.WriteLine("newmtl object{0}_part{1}_texture{2}", index, objIndex, objMat.textureIndex);
                                        streamWriter2.WriteLine("Ka 1.000000 1.000000 1.000000");
                                        streamWriter2.WriteLine("Kd {0} {1} {2}", Color.ToScale(objShd.Tint.R).ToString("0.000000"),
                                                                Color.ToScale(objShd.Tint.G).ToString("0.000000"),
                                                                Color.ToScale(objShd.Tint.B).ToString("0.000000"));
                                        streamWriter2.WriteLine("d {0}", Color.ToScale(objShd.Tint.A).ToString("0.000000"));
                                        streamWriter2.WriteLine("illum 1");
                                        streamWriter2.WriteLine("map_Kd object{0}_part{1}_texture{2}.{3}", index, objIndex, objMat.textureIndex, textureFormat.GetExtension());
                                    }
                                }
                            }
                            Primitive[] primitives = batches[(int)part.BatchIndex].primitives;
                            for (int m = 0; m < primitives.Length; m++)
                            {
                                Primitive     primitive = primitives[m];
                                PrimitiveType type      = primitive.Type;
                                if (type != PrimitiveType.TriangleStrip)
                                {
                                    if (type == PrimitiveType.TriangleFan)
                                    {
                                        streamWriter.WriteLine();
                                        streamWriter.WriteLine("# fan 0xA0");
                                        int vertex;
                                        for (vertex = 2; vertex < primitive.vertices.Length; vertex++)
                                        {
                                            TextWriter textWriter3 = streamWriter;
                                            string     format3     = "f {0}/{3}/{6} {1}/{4}/{7} {2}/{5}/{8}";
                                            object[]   array7      = new object[9];
                                            array7[0] = posIndices.IndexOfFirst((short pos) => pos == primitive.vertices[0].PositionIndex) + 1;
                                            array7[1] = posIndices.IndexOfFirst((short pos) => pos == primitive.vertices[vertex - 1].PositionIndex) + 1;
                                            array7[2] = posIndices.IndexOfFirst((short pos) => pos == primitive.vertices[vertex].PositionIndex) + 1;
                                            array7[3] = uvIndices.IndexOfFirst((short uv) => uv == primitive.vertices[0].UVIndex[0].GetValueOrDefault()) + 1;                                     // TEXCOORD0 (UVIndex[0]) only
                                            array7[4] = uvIndices.IndexOfFirst((short uv) => uv == primitive.vertices[vertex - 1].UVIndex[0].GetValueOrDefault()) + 1;                            // TEXCOORD0 (UVIndex[0]) only
                                            array7[5] = uvIndices.IndexOfFirst((short uv) => uv == primitive.vertices[vertex].UVIndex[0].GetValueOrDefault()) + 1;                                // TEXCOORD0 (UVIndex[0]) only
                                            array7[6] = normalIndices.IndexOfFirst((short normal) => normal == primitive.vertices[0].NormalIndex) + 1;
                                            array7[7] = normalIndices.IndexOfFirst((short normal) => normal == primitive.vertices[vertex - 1].NormalIndex) + 1;
                                            array7[8] = normalIndices.IndexOfFirst((short normal) => normal == primitive.vertices[vertex].NormalIndex) + 1;
                                            textWriter3.WriteLine(format3, array7);
                                        }
                                    }
                                }
                                else
                                {
                                    streamWriter.WriteLine();
                                    streamWriter.WriteLine("# strip 0x98");
                                    bool flag   = true;
                                    int  vertex = 2;
                                    while (vertex < primitive.vertices.Length)
                                    {
                                        TextWriter textWriter4 = streamWriter;
                                        string     format4     = flag ? "f {2}/{5}/{8} {1}/{4}/{7} {0}/{3}/{6}" : "f {0}/{3}/{6} {1}/{4}/{7} {2}/{5}/{8}";
                                        object[]   array8      = new object[9];
                                        array8[0] = posIndices.IndexOfFirst((short pos) => pos == primitive.vertices[vertex - 2].PositionIndex) + 1;
                                        array8[1] = posIndices.IndexOfFirst((short pos) => pos == primitive.vertices[vertex - 1].PositionIndex) + 1;
                                        array8[2] = posIndices.IndexOfFirst((short pos) => pos == primitive.vertices[vertex].PositionIndex) + 1;
                                        array8[3] = uvIndices.IndexOfFirst((short uv) => uv == primitive.vertices[vertex - 2].UVIndex[0].GetValueOrDefault()) + 1;                             // TEXCOORD0 (UVIndex[0]) only
                                        array8[4] = uvIndices.IndexOfFirst((short uv) => uv == primitive.vertices[vertex - 1].UVIndex[0].GetValueOrDefault()) + 1;                             // TEXCOORD0 (UVIndex[0]) only
                                        array8[5] = uvIndices.IndexOfFirst((short uv) => uv == primitive.vertices[vertex].UVIndex[0].GetValueOrDefault()) + 1;                                 // TEXCOORD0 (UVIndex[0]) only
                                        array8[6] = normalIndices.IndexOfFirst((short normal) => normal == primitive.vertices[vertex - 2].NormalIndex) + 1;
                                        array8[7] = normalIndices.IndexOfFirst((short normal) => normal == primitive.vertices[vertex - 1].NormalIndex) + 1;
                                        array8[8] = normalIndices.IndexOfFirst((short normal) => normal == primitive.vertices[vertex].NormalIndex) + 1;
                                        textWriter4.WriteLine(format4, array8);
                                        vertex++;
                                        flag = !flag;
                                    }
                                }
                            }
                        }
                    }
            }
            if (graphObject.Visible)
            {
                for (int n = (int)graphObject.ChildIndex; n >= 0; n = (int)graphObjects[n].ChildIndex)
                {
                    ExportGraphObject(outputFolder, n, onlyVisible, ignoreTransforms, swapU, swapV, exportTextures, textureFormat);
                }
            }
            for (int nextIndex = (int)graphObject.NextIndex; nextIndex >= 0; nextIndex = (int)graphObjects[nextIndex].NextIndex)
            {
                ExportGraphObject(outputFolder, nextIndex, onlyVisible, ignoreTransforms, swapU, swapV, exportTextures, textureFormat);
            }
        }