Esempio n. 1
0
        public static List <dynamic> parseTGXAsset(ExpandoObject staticTgxBin)
        {
            Console.WriteLine("Parsing model data...");
            dynamic tgxBin = staticTgxBin;

            dynamic metadata = tgxBin.metadata;             // Arrangement

            dynamic meshes = new List <dynamic>();

            for (var r = 0; r < metadata.render_model.GetProperty("render_meshes").GetArrayLength(); r++)
            {
                Console.WriteLine("Parsing object " + r + "...");

                var     renderMeshIndex = r;
                dynamic renderMesh      = metadata.render_model.GetProperty("render_meshes")[renderMeshIndex];            // BoB Bunch of Bits


                // IndexBuffer
                Console.Write("Parsing object " + r + " index buffer... ");
                var    indexBufferInfo = renderMesh.GetProperty("index_buffer");
                byte[] indexBufferData = tgxBin.files[indexBufferInfo.GetProperty("file_name").GetString()].data;

                dynamic indexBuffer = new List <ushort>();
                for (int j = 0; j < indexBufferInfo.GetProperty("byte_size").GetInt32(); j += indexBufferInfo.GetProperty("value_byte_size").GetInt32())
                {
                    var indexValue = BitConverter.ToUInt16(indexBufferData, j);
                    indexBuffer.Add(indexValue);
                }
                //console.log('IndexBuffer', indexBufferInfo);
                Console.WriteLine("Done.");

                // SkinBuffer
                SkinBufferData skinBuffer     = new SkinBufferData("", new List <byte>(), new Dictionary <int, SkinBufferChunk>());
                var            skinBufferInfo = new JsonElement();
                if (renderMesh.TryGetProperty("single_pass_skin_vertex_buffer", out skinBufferInfo) && skinBufferInfo.GetProperty("byte_size").GetInt32() > 0)
                {
                    Console.Write("Parsing object " + r + " skinning buffer... ");
                    skinBuffer = parseSkinBuffer(skinBufferInfo, tgxBin.files[skinBufferInfo.GetProperty("file_name").GetString()]);
                    Console.WriteLine("Done.");
                }

                // VertexBuffer
                Console.Write("Parsing object " + r + " vertex buffers... ");
                List <Dictionary <string, dynamic> > vertexBuffer = parseVertexBuffers(staticTgxBin, renderMesh);
                Console.WriteLine("Done.");

                // DataDrivenVertexBuffer
                List <byte[]> dataDrivenVertexBuffer     = new List <byte[]>();
                var           dataDrivenVertexBufferInfo = new JsonElement();
                if (renderMesh.TryGetProperty("data_driven_vertex_buffer", out dataDrivenVertexBufferInfo) && dataDrivenVertexBufferInfo.GetProperty("byte_size").GetInt32() > 0)
                {
                    Console.Write("Parsing object " + r + " data driven vertex buffer... ");
                    byte[] rawBuffer = tgxBin.files[dataDrivenVertexBufferInfo.GetProperty("file_name").GetString()].data;
                    //Console.WriteLine(renderMesh.GetProperty("vertex_buffers")[0].GetProperty("byte_size").GetInt32()/32);
                    for (int b = 0; b < vertexBuffer.Count /*renderMesh.GetProperty("vertex_buffers")[0].GetProperty("byte_size").GetInt32()/32*/; b++)
                    {
                        //int startIndex = b*4;
                        double[] vertBuff = new double[4] {
                            0, 0, 0, 0
                        };                                                                 //{rawBuffer[b], rawBuffer[b+1], rawBuffer[b+2], rawBuffer[b+3]};
                        //dataDrivenVertexBuffer.Add(vertBuff);
                        for (int c = 0; c < 4; c++)
                        {
                            if (b >= dataDrivenVertexBufferInfo.GetProperty("byte_size").GetInt32() / 4)
                            {
                                continue;
                            }
                            vertBuff[c] = rawBuffer[(b * 4) + c] / 255.0;
                        }
                        vertexBuffer[b].Add("color0", vertBuff);
                    }
                    Console.WriteLine("Done.");
                }

                List <Dictionary <string, dynamic> > parts = new List <Dictionary <string, dynamic> >();
                List <int> partIndexList  = new List <int>();
                int[]      stagesToRender = { 0, 7, 15 };          // Hardcoded?
                //dynamic partOffsets = new JArray();

                Console.Write("Parsing object " + r + " stage parts... ");
                for (int sP = 0; sP < renderMesh.GetProperty("stage_part_list").GetArrayLength(); sP++)
                {
                    dynamic stagePart = renderMesh.GetProperty("stage_part_list")[sP];
                    if (stagePart.ValueKind == JsonValueKind.Undefined)
                    {
                        //console.warn('MissingStagePart['+renderMeshIndex+':'+partOffset+']');
                        //Console.WriteLine("MissingStagePart["+renderMeshIndex+":"+partOffset+"]");
                        continue;
                    }

                    if (partIndexList.IndexOf(stagePart.GetProperty("start_index").GetInt32()) != -1)
                    {
                        // Skip duplicate parts
                        continue;
                    }
                    partIndexList.Add(stagePart.GetProperty("start_index").GetInt32());
                    parts.Add(parseStagePart(stagePart));
                }
                Console.WriteLine("Done.");

                // Spasm.RenderMesh
                dynamic mesh = new ExpandoObject();
                mesh.positionOffset       = renderMesh.GetProperty("position_offset");
                mesh.positionScale        = renderMesh.GetProperty("position_scale");
                mesh.texcoordOffset       = renderMesh.GetProperty("texcoord_offset");
                mesh.texcoordScale        = renderMesh.GetProperty("texcoord_scale");
                mesh.texcoord0ScaleOffset = renderMesh.GetProperty("texcoord0_scale_offset");
                mesh.indexBuffer          = indexBuffer;
                mesh.vertexBuffer         = vertexBuffer;
                mesh.skinBuffer           = skinBuffer;
                //mesh.dataDrivenVertexBuffer = dataDrivenVertexBuffer.ToArray();
                mesh.parts = parts;

                meshes.Add(mesh);
            }

            Console.WriteLine("Model data parsed.");
            return(meshes);
        }
Esempio n. 2
0
        public static SkinBufferData parseSkinBuffer(
            dynamic VertexBufferInfo,
            ExpandoObject TGXFileEntry = null
            )
        {
            dynamic info = VertexBufferInfo;
            dynamic file = TGXFileEntry;
            //debug("TGXLoader:SkinBuffer", VertexBufferInfo);

            SkinBufferData skinBuffer = new SkinBufferData
                                        (
                info.GetProperty("file_name").GetString(), //id
                new List <byte>(),                         //header
                new Dictionary <int, SkinBufferChunk>()    //data
                                        );

            if (TGXFileEntry != null)
            {
                bool isHeader     = true;
                int  chunkWeight  = 0;
                int  weightOffset = 0;
                int  stride       = info.GetProperty("stride_byte_size").GetInt32();
                for (int i = 0; i < info.GetProperty("byte_size").GetInt32(); i += stride)
                {
                    uint skinVertex = BitConverter.ToUInt32(file.data, i);

                    if (stride != 4)
                    {
                        ConsoleEx.Warn("Skinbuffer stride is not equal to 4.");
                    }

                    byte index0  = (byte)((skinVertex >> 0) & 0xff);
                    byte index1  = (byte)((skinVertex >> 8) & 0xff);
                    byte weight0 = (byte)((skinVertex >> 16) & 0xff);
                    byte weight1 = (byte)((skinVertex >> 24) & 0xff);

                    if (chunkWeight == 0)
                    {
                        weightOffset = i;
                    }
                    int chunkIndex = weightOffset / 4;

                    int strideIndex = i / 4;
                    if (!skinBuffer.data.ContainsKey(strideIndex))
                    {
                        skinBuffer.data.Add(strideIndex, new SkinBufferChunk(
                                                strideIndex,
                                                0,
                                                new List <byte>(),
                                                new List <byte>()
                                                )
                                            );
                    }
                    SkinBufferChunk chunkData = skinBuffer.data[chunkIndex];

                    //Console.WriteLine($"{i} {index0} {index1} {weight0} {weight1}");
                    //if(i>31) // for brute forcing past the header when someone needs an item and I can't figure out a fix quickly.
                    // Odds of a header chunk having unmatched index0+weight0 AND total weight bytes of 255 is very low,
                    // toss in similarly low odds of first weight chunk being 4-bone skinning and it should hopefully never fail.
                    if (isHeader && (index0 != weight0) && (weight0 + weight1 == 255) && i + stride < file.data.Length)
                    {
                        uint nextSkinVertex = BitConverter.ToUInt32(file.data, i + stride);
                        uint nextIndex0     = (nextSkinVertex >> 0) & 0xff;
                        uint nextIndex1     = (nextSkinVertex >> 8) & 0xff;
                        uint nextWeight0    = (nextSkinVertex >> 16) & 0xff;
                        uint nextWeight1    = (nextSkinVertex >> 24) & 0xff;
                        // DENDRITE SHIMMER BOND F*****G BROKE THIS!!!!!!!!!! :))))))))))
                        if ((nextIndex0 != nextWeight0) && (nextWeight0 + nextWeight1 == 255))
                        {
                            isHeader = false;
                            ConsoleEx.Warn($"1 {i} {index0} {index1} {weight0} {weight1}");
                        }
                    }
                    else if (isHeader && i + stride < file.data.Length)
                    {
                        uint nextSkinVertex = BitConverter.ToUInt32(file.data, i + stride);
                        uint nextIndex0     = (nextSkinVertex >> 0) & 0xff;
                        uint nextIndex1     = (nextSkinVertex >> 8) & 0xff;
                        uint nextWeight0    = (nextSkinVertex >> 16) & 0xff;
                        uint nextWeight1    = (nextSkinVertex >> 24) & 0xff;

                        if ((index0 != weight0) && (weight0 + weight1 + nextWeight0 + nextWeight1 == 255))
                        {
                            ConsoleEx.Warn($"2 {i} {index0} {index1} {weight0} {weight1}");
                            isHeader = false;
                        }
                    }
                    if (isHeader)
                    {
                        skinBuffer.header.Add(index0);
                        skinBuffer.header.Add(index1);
                        skinBuffer.header.Add(weight0);
                        skinBuffer.header.Add(weight1);
                    }
                    else if (skinVertex == 0)
                    {
                        // Skip empty blocks
                    }
                    else
                    {
                        //{weight0, weight1}.forEach((weight) => {
                        foreach (byte weight in new byte[] { weight0, weight1 })
                        {
                            if (weight > 0)
                            {
                                chunkData.count++;
                            }
                            chunkWeight += weight;
                        }
                        ;

                        chunkData.indices.Add(index0);
                        chunkData.indices.Add(index1);
                        chunkData.weights.Add(weight0);
                        chunkData.weights.Add(weight1);
                        if (chunkWeight >= 255)
                        {
                            chunkWeight = 0;
                        }
                    }
                }
            }
            return(skinBuffer);
        }