Exemple #1
0
        private List <J3DRenderer.VertexFormatLayout> BuildVertexArraysFromFile()
        {
            List <J3DRenderer.VertexFormatLayout> finalData = new List <J3DRenderer.VertexFormatLayout>();


            //Now, let's try to get our data.
            for (uint i = 0; i < _file.Shapes.GetBatchCount(); i++)
            {
                J3DFormat.Batch batch = _file.Shapes.GetBatch(i);

                RenderBatch renderBatch = new RenderBatch();
                _renderList.Add(renderBatch);

                //Console.WriteLine("[{0}] Unk0: {5}, Attb: {6} Mtx Type: {1} #Packets {2}[{3}] Matrix Index: {4}", i, batch.MatrixType, batch.PacketCount, batch.PacketIndex, batch.FirstMatrixIndex, batch.Unknown0, batch.AttribOffset);

                uint attributeCount = 0;
                for (uint attribIndex = 0; attribIndex < 13; attribIndex++)
                {
                    J3DFormat.BatchAttribute attrib = _file.Shapes.GetAttribute(attribIndex, batch.AttribOffset);
                    if (attrib.AttribType == J3DFormat.ArrayTypes.NullAttr)
                    {
                        break;
                    }

                    attributeCount++;
                }

                for (ushort p = 0; p < batch.PacketCount; p++)
                {
                    RenderPacket renderPacket = new RenderPacket();
                    renderBatch.Packets.Add(renderPacket);

                    //Matrix Data
                    J3DFormat.PacketMatrixData pmd = _file.Shapes.GetPacketMatrixData((ushort)(batch.FirstMatrixIndex + p));
                    renderPacket.DrawIndexes = new ushort[pmd.Count];
                    for (ushort mtx = 0; mtx < pmd.Count; mtx++)
                    {
                        //Console.WriteLine("{4} {0} Packet: {1} Index: {2} PMD Unknown: {3}", i, p, _file.Shapes.GetMatrixTableIndex((ushort) (pmd.FirstIndex + mtx)), pmd.Unknown, mtx);
                        renderPacket.DrawIndexes[mtx] = _file.Shapes.GetMatrixTableIndex((ushort)(pmd.FirstIndex + mtx));
                    }

                    J3DFormat.BatchPacketLocation packetLoc = _file.Shapes.GetBatchPacketLocation((ushort)(batch.PacketIndex + p));
                    uint numPrimitiveBytesRead = packetLoc.Offset;
                    while (numPrimitiveBytesRead < packetLoc.Offset + packetLoc.PacketSize)
                    {
                        J3DFormat.BatchPrimitive primitive = _file.Shapes.GetPrimitive(numPrimitiveBytesRead);
                        numPrimitiveBytesRead += J3DFormat.BatchPrimitive.Size;

                        //Game pads the chunks out with zeros, so this is signal for early break.
                        if (primitive.Type == 0)
                        {
                            break;
                        }

                        var primList = new PrimitiveList();
                        primList.VertexCount = primitive.VertexCount;
                        primList.VertexStart = finalData.Count;
                        primList.DrawType    = primitive.Type == J3DFormat.PrimitiveTypes.TriangleStrip ? PrimitiveType.TriangleStrip : PrimitiveType.TriangleFan; //Todo: More support
                        renderPacket.PrimList.Add(primList);

                        for (int vert = 0; vert < primitive.VertexCount; vert++)
                        {
                            J3DRenderer.VertexFormatLayout newVertex = new J3DRenderer.VertexFormatLayout();
                            for (uint vertIndex = 0; vertIndex < attributeCount; vertIndex++)
                            {
                                var    batchAttrib = _file.Shapes.GetAttribute(vertIndex, batch.AttribOffset);
                                ushort curIndex    = _file.Shapes.GetPrimitiveIndex(numPrimitiveBytesRead, batchAttrib);

                                switch (batchAttrib.AttribType)
                                {
                                case J3DFormat.ArrayTypes.Position:
                                    newVertex.Position = _file.Vertexes.GetPosition(curIndex);
                                    break;

                                case J3DFormat.ArrayTypes.Normal:
                                    newVertex.Color = new Vector4(_file.Vertexes.GetNormal(curIndex, 14), 1);     //temp
                                    break;

                                case J3DFormat.ArrayTypes.Color0:
                                    newVertex.Color = _file.Vertexes.GetColor0(curIndex);
                                    break;

                                case J3DFormat.ArrayTypes.Tex0:
                                    newVertex.TexCoord = _file.Vertexes.GetTex0(curIndex, 8);
                                    break;

                                case J3DFormat.ArrayTypes.PositionMatrixIndex:
                                    //Console.WriteLine("B: {0} P: {1} Prim: {2} Vert{3} Index: {4}", i, p, renderPacket.PrimList.Count, vert, curIndex);
                                    primList.PosMatrixIndex.Add(curIndex);
                                    break;

                                default:
                                    Console.WriteLine("Unknown AttribType {0}, Index: {1}", batchAttrib.AttribType, curIndex);
                                    break;
                                }

                                numPrimitiveBytesRead += GetAttribElementSize(batchAttrib.DataType);
                            }

                            //Add our vertex to our list of Vertexes
                            finalData.Add(newVertex);
                        }

                        //Console.WriteLine("Batch {0} Prim {1} #Vertices with PosMtxIndex: {2}", i, p, primList.PosMatrixIndex.Count);
                    }
                }

                //Console.WriteLine("Finished batch {0}, triangleStrip count: {1}", i, _renderList.Count);
            }

            return(finalData);
        }
Exemple #2
0
        private void DrawModelRecursive(ref Matrix4[] jointMatrix, SceneGraph curNode, BaseRenderer renderer, bool bSelectedPass)
        {
            switch (curNode.NodeType)
            {
            case J3DFormat.HierarchyDataTypes.Material:
                if (!bSelectedPass)
                {
                    GL.BindTexture(TextureTarget.Texture2D, GetGLTexIdFromCache(curNode.DataIndex));
                }
                break;

            case J3DFormat.HierarchyDataTypes.Batch:
                /* For each batch, we're going to enable the
                 * appropriate Vertex Attributes for that batch
                 * and set default values for vertex attribs that
                 * the batch doesn't use, then draw all primitives
                 * within it.*/

                if (bSelectedPass)
                {
                    #region Selected
                    float[] front_face_wireframe_color = { 1.0f, 1.0f, 1.0f, 1.0f };
                    float[] back_face_wireframe_color  = { 0.7f, 0.7f, 0.7f, 0.7f };

                    GL.LineWidth(1);
                    GL.Enable(EnableCap.CullFace);
                    //GL.Disable(EnableCap.DepthTest);
                    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
                    GL.EnableVertexAttribArray((int)BaseRenderer.ShaderAttributeIds.Position);

                    // 1. Draw the back-faces with a darker color:
                    GL.CullFace(CullFaceMode.Back);
                    GL.VertexAttrib4((int)BaseRenderer.ShaderAttributeIds.Color, back_face_wireframe_color);
                    foreach (var packet in _renderList[curNode.DataIndex].Packets)
                    {
                        int vertexIndex = 0;
                        foreach (var primitive in packet.PrimList)
                        {
                            //Uhh...
                            ushort drawIndex  = packet.DrawIndexes[primitive.PosMatrixIndex[vertexIndex] / 3];
                            bool   isWeighted = _file.Draw.IsWeighted(drawIndex);

                            if (isWeighted)
                            {
                            }
                            else
                            {
                                var     jnt       = _file.Joints.GetJoint(curNode.DataIndex);
                                Vector3 jntRot    = jnt.GetRotation().ToDegrees();
                                Vector3 trans     = jnt.GetTranslation();
                                Matrix4 trnMatrix = Matrix4.CreateTranslation(trans);
                                Matrix4 rtMatrix  = Matrix4.CreateRotationX(jntRot.X) * Matrix4.CreateRotationY(jntRot.Y) *
                                                    Matrix4.CreateRotationZ(jntRot.Z);
                                Matrix4 sclMatrix = Matrix4.CreateScale(jnt.GetScale());

                                Matrix4 final = trnMatrix * rtMatrix * sclMatrix;

                                //renderer.SetModelMatrix(Matrix4.Identity);
                                renderer.SetModelMatrix(final);
                            }

                            GL.DrawArrays(primitive.DrawType, primitive.VertexStart, primitive.VertexCount);

                            vertexIndex++;
                        }
                    }


                    // 2. Draw the front-faces with a lighter color:
                    GL.CullFace(CullFaceMode.Front);
                    GL.VertexAttrib4((int)BaseRenderer.ShaderAttributeIds.Color, front_face_wireframe_color);

                    /*foreach (var primitive in _renderList[curNode.DataIndex])
                     * {
                     *  GL.DrawArrays(primitive.DrawType, primitive.VertexStart, primitive.VertexCount);
                     * }*/

                    GL.DisableVertexAttribArray((int)BaseRenderer.ShaderAttributeIds.Position);
                    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
                    //GL.Enable(EnableCap.DepthTest);
                    GL.LineWidth(1);
                    #endregion
                }
                else
                {
                    SetVertexAttribArraysForBatch(true, curNode.DataIndex);
                    //GL.CullFace(CullFaceMode.Front);
                    for (int packetIndex = 0; packetIndex < _renderList[curNode.DataIndex].Packets.Count; packetIndex++)
                    {
                        RenderPacket packet = _renderList[curNode.DataIndex].Packets[packetIndex];
                        foreach (var primitive in packet.PrimList)
                        {
                            renderer.SetModelMatrix(Matrix4.Identity);

                            if (primitive.PosMatrixIndex.Count > 0)
                            {
                                var transformedData = new J3DRenderer.VertexFormatLayout[primitive.VertexCount];

                                //For each vertex within this primitive, we're going to get its id.
                                for (int vertexIndex = 0; vertexIndex < primitive.VertexCount; vertexIndex++)
                                {
                                    ushort vertIndex = primitive.PosMatrixIndex[vertexIndex];
                                    ushort drawIndex = packet.DrawIndexes[vertIndex / 3];

                                    //ehh
                                    int seriously = 0;
                                    while (drawIndex == 0xFFFF)
                                    {
                                        RenderPacket prevPacket =
                                            _renderList[curNode.DataIndex].Packets[packetIndex - seriously];
                                        drawIndex = prevPacket.DrawIndexes[vertIndex / 3];
                                        seriously++;
                                    }

                                    bool isWeighted = _file.Draw.IsWeighted(drawIndex);
                                    if (isWeighted)
                                    {
                                        ushort numBonesAffecting =
                                            _file.Envelopes.GetCount(_file.Draw.GetIndex(drawIndex));

                                        //Much WTFs
                                        ushort offset = 0;
                                        for (ushort i = 0; i < _file.Draw.GetIndex(drawIndex); i++)
                                        {
                                            offset += _file.Envelopes.GetCount(i);
                                        }

                                        offset *= 2;
                                        Matrix4 finalTransform = Matrix4.Identity;
                                        for (ushort i = 0; i < numBonesAffecting; i++)
                                        {
                                            ushort boneIndex =
                                                _file.Envelopes.GetIndexOffset((ushort)(offset + (i * 0x2)));
                                            float boneWeight = _file.Envelopes.GetWeight((ushort)((offset / 2) + i));

                                            Matrix3x4 envMatrix      = _file.Envelopes.GetMatrix(boneIndex);
                                            Matrix4   newEnvelopeMtx = new Matrix4(envMatrix.Row0, envMatrix.Row1,
                                                                                   envMatrix.Row2, new Vector4(0, 0, 0, 1));

                                            SkeletonJoint joint = _skeleCopy[boneIndex];
                                            //Matrix4 transMatrix = Matrix4.CreateTranslation(joint.Position);
                                            //We need to use the bone's matrix from EVP1 to get the joint matrix
                                            Matrix4 jointMtx = joint.Rotation * newEnvelopeMtx;

                                            //finalTransform = Matrix4.Mult(jointMtx * newEnvelopeMtx, boneWeight) * finalTransform;
                                            //ToDo: This is the wrong scale.
                                            //AddScaleMatrix(ref finalTransform, Matrix4.Mult(jointMtx, newEnvelopeMtx), 1f);
                                        }

                                        transformedData[vertexIndex] = _vertDataBind[primitive.VertexStart + vertexIndex];

                                        Vector3 vertPosition = transformedData[vertexIndex].Position;
                                        transformedData[vertexIndex].Position = Vector3.TransformPosition(vertPosition, finalTransform);
                                    }
                                    else
                                    {
                                        //If the vertex is not weighted, we're just going to use the position
                                        //from the bone matrix. Something like this.
                                        Vector3 vertPosition =
                                            _vertDataBind[primitive.VertexStart + vertexIndex].Position;

                                        transformedData[vertexIndex] = _vertDataBind[primitive.VertexStart + vertexIndex];

                                        SkeletonJoint joint       = _skeleCopy[_file.Draw.GetIndex(drawIndex)];
                                        Matrix4       transMatrix = Matrix4.CreateTranslation(joint.Position);
                                        Matrix4       final       = joint.Rotation * transMatrix;
                                        transformedData[vertexIndex].Position = Vector3.TransformPosition(vertPosition, final);
                                    }
                                }

                                //Re-upload the subsection to the buffer.
                                GL.BindBuffer(BufferTarget.ArrayBuffer, _glVbo);
                                GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr)(primitive.VertexStart * (9 * 4)),
                                                 (IntPtr)(primitive.VertexCount * (9 * 4)), transformedData);

                                float[] front_face_wireframe_color = { 1.0f, 1.0f, 1.0f, 1.0f };
                                GL.VertexAttrib4((int)BaseRenderer.ShaderAttributeIds.Color, front_face_wireframe_color);
                            }


                            GL.DrawArrays(primitive.DrawType, primitive.VertexStart, primitive.VertexCount);
                        }
                    }

                    SetVertexAttribArraysForBatch(false, curNode.DataIndex);
                }

                break;
            }

            foreach (SceneGraph subNode in curNode.Children)
            {
                DrawModelRecursive(ref jointMatrix, subNode, renderer, bSelectedPass);
            }
        }