Beispiel #1
0
        private void LoadTagDataFromFile(EndianBinaryReader reader, int tagCount, bool dumpTextures, bool dumpShaders)
        {
            for (int i = 0; i < tagCount; i++)
            {
                long tagStart = reader.BaseStream.Position;

                string tagName = reader.ReadString(4);
                int    tagSize = reader.ReadInt32();

                switch (tagName)
                {
                // INFO - Vertex Count, Scene Hierarchy
                case "INF1":
                    INF1Tag = new INF1();
                    INF1Tag.LoadINF1FromStream(reader, tagStart);
                    break;

                // VERTEX - Stores vertex arrays for pos/normal/color0/tex0 etc.
                // Contains VertexAttributes which describe how the data is stored/laid out.
                case "VTX1":
                    VTX1Tag = new VTX1();
                    VTX1Tag.LoadVTX1FromStream(reader, tagStart, tagSize);
                    break;

                // ENVELOPES - Defines vertex weights for skinning
                case "EVP1":
                    EVP1Tag = new EVP1();
                    EVP1Tag.LoadEVP1FromStream(reader, tagStart);
                    break;

                // DRAW (Skeletal Animation Data) - Stores which matrices (?) are weighted, and which are used directly
                case "DRW1":
                    DRW1Tag = new DRW1();
                    DRW1Tag.LoadDRW1FromStream(reader, tagStart);
                    break;

                // JOINTS - Stores the skeletal joints (position, rotation, scale, etc...)
                case "JNT1":
                    JNT1Tag = new JNT1();
                    JNT1Tag.LoadJNT1FromStream(reader, tagStart);
                    JNT1Tag.CalculateParentJointsForSkeleton(INF1Tag.HierarchyRoot);
                    break;

                // SHAPE - Face/Triangle information for model.
                case "SHP1":
                    SHP1Tag = new SHP1();
                    SHP1Tag.ReadSHP1FromStream(reader, tagStart);

                    CalculateModelBounds();
                    break;

                // MATERIAL - Stores materials (which describes how textures, etc. are drawn)
                case "MAT3":
                    MAT3Tag = new MAT3();
                    MAT3Tag.LoadMAT3FromStream(reader, tagStart);
                    break;

                // TEXTURES - Stores binary texture images.
                case "TEX1":
                    TEX1Tag = new TEX1();
                    TEX1Tag.LoadTEX1FromStream(reader, tagStart, dumpTextures);
                    break;

                // MODEL - Seems to be bypass commands for Materials and invokes GX registers directly.
                case "MDL3":
                    break;
                }

                // Skip the stream reader to the start of the next tag since it gets moved around during loading.
                reader.BaseStream.Position = tagStart + tagSize;
            }

            INF1Tag.LinkData(MAT3Tag, SHP1Tag);

            Tick(float.Epsilon);

            if (EVP1Tag.InverseBindPose.Count <= 0)
            {
                EVP1Tag.GenerateInverseBindMatrices(JNT1Tag);
            }

            DRW1Tag.UpdateMatrices(JNT1Tag.BindJoints, EVP1Tag);

            SHP1Tag.LinkData(VTX1Tag, DRW1Tag, EVP1Tag);
            SHP1Tag.UploadShapesToGPU();
        }
Beispiel #2
0
        private void BindMaterialByIndex(ushort index, bool bDepthOnlyPrePass)
        {
            MAT3 mat3 = MAT3Tag;
            TEX1 tex1 = TEX1Tag;

            if (m_currentExternalMaterial != null)
            {
                if (m_currentExternalMaterial.MaterialsCount != 0)
                {
                    mat3 = m_currentExternalMaterial.MAT3;
                }
                if (m_currentExternalMaterial.TexturesCount != 0)
                {
                    tex1 = m_currentExternalMaterial.TEX1;
                }
            }

            // While the game collapses duplicate materials via the material index remap table,
            // the actual original names are preserved with their original indexes through the
            // string table.
            string materialName = mat3.MaterialNameTable[index];

            Material material = mat3.MaterialList[index];

            material.Bind();
            m_currentBoundMat = material;

            Shader shader = material.Shader;

            //GL.UniformMatrix4(shader.UniformModelMtx, false, ref m_modelMatrix);
            //GL.UniformMatrix4(shader.UniformViewMtx, false, ref m_viewMatrix);
            //GL.UniformMatrix4(shader.UniformProjMtx, false, ref m_projMatrix);

            for (int i = 0; i < 8; i++)
            {
                int idx = material.TextureIndices[i];
                if (idx < 0)
                {
                    continue;
                }

                //int glTextureIndex = GL.GetUniformLocation(shader.Program, string.Format("Texture[{0}]", i));
                Texture tex = tex1.Textures[mat3.TextureRemapTable[idx]];

                // Before we bind the texture, we need to check if this particular texture has been overriden.
                // This allows textures to be replaced on a per-name basis with another file. Used in cases of
                // broken/incorrect texture included by default in models, ie: The Wind Waker toon textures.
                if (m_textureOverrides.ContainsKey(tex.Name))
                {
                    tex = m_textureOverrides[tex.Name];
                }

                GL.Uniform1(shader.UniformTextureSamplers[i], i); // Everything dies without this, don't forget this bit.
                tex.Bind(i);
            }

            /*if (shader.UniformTexMtx >= 0)
             * {
             *  for (int i = 0; i < material.TexMatrixIndexes.Length; i++)
             *  {
             *      Matrix4 matrix = material.TexMatrixIndexes[i].TexMtx;
             *      string matrixString = string.Format("TexMtx[{0}]", i);
             *                          if(material.TexMatrixIndexes[i].MatrixUniformLocationForGPU < 0)
             *                          {
             *                                  // If the shader's broke this will try to re-assign every frame, but should vastly improve it most use cases.
             *                                  material.TexMatrixIndexes[i].MatrixUniformLocationForGPU = GL.GetUniformLocation(shader.Program, matrixString);
             *                          }
             *
             *      GL.UniformMatrix4(material.TexMatrixIndexes[i].MatrixUniformLocationForGPU, true, ref matrix);
             *  }
             * }
             *
             *          if(shader.UniformPostTexMtx >= 0)
             *          {
             *                  for(int i = 0; i < material.PostTexMatrixIndexes.Length; i++)
             *                  {
             *                          Matrix4 matrix = material.PostTexMatrixIndexes[i].TexMtx;
             *
             *                          string matrixString = string.Format("PostMtx[{0}]", i);
             *
             *                          if (material.PostTexMatrixIndexes[i].MatrixUniformLocationForGPU == 0)
             *                          {
             *                                  material.PostTexMatrixIndexes[i].MatrixUniformLocationForGPU = GL.GetUniformLocation(shader.Program, matrixString);
             *                          }
             *
             *                          GL.UniformMatrix4(material.PostTexMatrixIndexes[i].MatrixUniformLocationForGPU, true, ref matrix);
             *                  }
             *          }*/

            var color0Amb = material.AmbientColors[0];
            var color0Mat = material.MaterialColors[0];
            var color1Amb = material.AmbientColors[1];
            var color1Mat = material.MaterialColors[1];

            //if (shader.UniformColor0Amb >= 0) GL.Uniform4(shader.UniformColor0Amb, color0Amb.R, color0Amb.G, color0Amb.B, color0Amb.A);
            //if (shader.UniformColor0Mat >= 0) GL.Uniform4(shader.UniformColor0Mat, color0Mat.R, color0Mat.G, color0Mat.B, color0Mat.A);
            //if (shader.UniformColor1Amb >= 0) GL.Uniform4(shader.UniformColor1Amb, color1Amb.R, color1Amb.G, color1Amb.B, color1Amb.A);
            //if (shader.UniformColor1Mat >= 0) GL.Uniform4(shader.UniformColor1Mat, color1Mat.R, color1Mat.G, color1Mat.B, color1Mat.A);

            // Set the OpenGL State
            GXToOpenGL.SetBlendState(material.BlendMode);
            GXToOpenGL.SetCullState(material.CullMode);
            GXToOpenGL.SetDepthState(material.ZMode, bDepthOnlyPrePass);
            GXToOpenGL.SetDitherEnabled(material.Dither);

            // Check to see if we've overridden the material's ability to write to the color channel. This is used
            // to add support for bmd/bdl models who have this setting changed through game-code since the bmd/bdl
            // format does not appear to otherwise specify.
            if (m_colorWriteOverrides.ContainsKey(materialName))
            {
                bool enabled = m_colorWriteOverrides[materialName];
                GL.ColorMask(enabled, enabled, enabled, true);
            }
            else if (bDepthOnlyPrePass)
            {
                GL.ColorMask(false, false, false, false);
            }
            else
            {
                GL.ColorMask(true, true, true, true);
            }
            //if (WInput.GetKey(System.Windows.Input.Key.U))
            //    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
            //else
            //    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);


            // Update the data in the PS Block
            PSBlock psData = new PSBlock();

            m_tevColorOverrides.SetPSBlockForMaterial(material, ref psData);
            UpdateTextureDimensionsForPSBlock(ref psData, material);
            UpdateFogForPSBlock(ref psData, material);

            // Upload the PS Block to the GPU
            GL.BindBufferBase(BufferRangeTarget.UniformBuffer, (int)ShaderUniformBlockIds.PixelShaderBlock, shader.PSBlockUBO);
            GL.BufferData <PSBlock>(BufferTarget.UniformBuffer, (IntPtr)(Marshal.SizeOf(psData)), ref psData, BufferUsageHint.DynamicDraw);
        }
Beispiel #3
0
        private void LoadTagDataFromFile(EndianBinaryReader reader, int tagCount, bool dumpTextures, bool dumpShaders)
        {
            for (int i = 0; i < tagCount; i++)
            {
                long tagStart = reader.BaseStream.Position;

                string tagName = reader.ReadString(4);
                int    tagSize = reader.ReadInt32();

                switch (tagName)
                {
                // INFO - Vertex Count, Scene Hierarchy
                case "INF1":
                    INF1Tag = new INF1();
                    INF1Tag.LoadINF1FromStream(reader, tagStart);
                    break;

                // VERTEX - Stores vertex arrays for pos/normal/color0/tex0 etc.
                // Contains VertexAttributes which describe how the data is stored/laid out.
                case "VTX1":
                    VTX1Tag = new VTX1();
                    VTX1Tag.LoadVTX1FromStream(reader, tagStart, tagSize);
                    break;

                // ENVELOPES - Defines vertex weights for skinning
                case "EVP1":
                    EVP1Tag = new EVP1();
                    EVP1Tag.LoadEVP1FromStream(reader, tagStart);
                    break;

                // DRAW (Skeletal Animation Data) - Stores which matrices (?) are weighted, and which are used directly
                case "DRW1":
                    DRW1Tag = new DRW1();
                    DRW1Tag.LoadDRW1FromStream(reader, tagStart);
                    break;

                // JOINTS - Stores the skeletal joints (position, rotation, scale, etc...)
                case "JNT1":
                    JNT1Tag = new JNT1();
                    JNT1Tag.LoadJNT1FromStream(reader, tagStart);
                    JNT1Tag.CalculateParentJointsForSkeleton(INF1Tag.HierarchyRoot);
                    break;

                // SHAPE - Face/Triangle information for model.
                case "SHP1":
                    SHP1Tag = new SHP1();
                    SHP1Tag.ReadSHP1FromStream(reader, tagStart, VTX1Tag.VertexData);
                    break;

                // MATERIAL - Stores materials (which describes how textures, etc. are drawn)
                case "MAT3":
                    MAT3Tag = new MAT3();
                    MAT3Tag.LoadMAT3FromStream(reader, tagStart);
                    break;

                // TEXTURES - Stores binary texture images.
                case "TEX1":
                    TEX1Tag = new TEX1();
                    TEX1Tag.LoadTEX1FromStream(reader, tagStart, dumpTextures);
                    break;

                // MODEL - Seems to be bypass commands for Materials and invokes GX registers directly.
                case "MDL3":
                    break;
                }

                // Skip the stream reader to the start of the next tag since it gets moved around during loading.
                reader.BaseStream.Position = tagStart + tagSize;
            }

            // To generate shaders we need to know which vertex attributes need to be enabled for the shader. However,
            // the shader has no knowledge in our book as to what attributes are enabled. Theoretically we could enable
            // them on the fly as something requested it, but that'd involve more code that I don't want to do right now.
            // To resolve, we iterate once through the hierarchy to see which mesh is called after a material and bind the
            // vertex descriptions.
            Material dummyMat = null;

            AssignVertexAttributesToMaterialsRecursive(INF1Tag.HierarchyRoot, ref dummyMat, MAT3Tag);

            // Now that the vertex attributes are assigned to the materials, generate a shader from the data.
            GenerateShadersForMaterials(MAT3Tag, dumpShaders);

            // Iterate through the shapes and calculate a bounding box which encompasses all of them.
            Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
            Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);

            foreach (var shape in SHP1Tag.Shapes)
            {
                Vector3 sMin = shape.BoundingBox.Min;
                Vector3 sMax = shape.BoundingBox.Max;

                if (sMin.X < min.X)
                {
                    min.X = sMin.X;
                }
                if (sMax.X > max.X)
                {
                    max.X = sMax.X;
                }

                if (sMin.Y < min.Y)
                {
                    min.Y = sMin.Y;
                }
                if (sMax.Y > max.Y)
                {
                    max.Y = sMax.Y;
                }

                if (sMin.Z < min.Z)
                {
                    min.Z = sMin.Z;
                }
                if (sMax.Z > max.Z)
                {
                    max.Z = sMax.Z;
                }
            }

            BoundingBox    = new FAABox(min, max);
            BoundingSphere = new FSphere(BoundingBox.Center, BoundingBox.Max.Length);
        }