internal void LoadIndexedData(EndianBinaryReader input, OrderedSet <GcmfVertex> vertexPool, HeaderSectionInfo headerSectionInfo) { if ((headerSectionInfo.SectionFlags & 0x01) != 0 && headerSectionInfo.Chunk1Size == 0) { throw new InvalidGmaFileException("GcmfMeshType2: Chunk1, but chunk1Size == 0?"); } if ((headerSectionInfo.SectionFlags & 0x01) == 0 && headerSectionInfo.Chunk1Size != 0) { throw new InvalidGmaFileException("GcmfMeshType2: No chunk1, but chunk1Size != 0?"); } if ((headerSectionInfo.SectionFlags & 0x01) != 0) { Obj1StripsCcw.LoadIndexed(input, headerSectionInfo.Chunk1Size, vertexPool, headerSectionInfo.VertexFlags); } if ((headerSectionInfo.SectionFlags & 0x02) != 0 && headerSectionInfo.Chunk2Size == 0) { throw new InvalidGmaFileException("GcmfMeshType2: Chunk2, but chunk2Size == 0?"); } else if ((headerSectionInfo.SectionFlags & 0x02) == 0 && headerSectionInfo.Chunk2Size != 0) { throw new InvalidGmaFileException("GcmfMeshType2: No chunk2, but chunk2Size != 0?"); } if ((headerSectionInfo.SectionFlags & 0x02) != 0) { Obj1StripsCw.LoadIndexed(input, headerSectionInfo.Chunk2Size, vertexPool, headerSectionInfo.VertexFlags); } if ((headerSectionInfo.SectionFlags & 0xFC) != 0) { throw new InvalidGmaFileException("GcmfMeshType2: Unknown present chunk flags at chunk10."); } }
internal void SaveNonIndexedData(EndianBinaryWriter output, bool is16Bit) { if (Obj1StripsCcw.Count != 0) { Obj1StripsCcw.SaveNonIndexed(output, is16Bit); } if (Obj1StripsCw.Count != 0) { Obj1StripsCw.SaveNonIndexed(output, is16Bit); } if (Obj2StripsCcw.Count != 0 || Obj2StripsCw.Count != 0) { // Extra header output.Write(TransformMatrixSpecificIdxsObj2, 0, 8); output.Write(Obj2StripsCcw.SizeOfNonIndexed(is16Bit)); output.Write(Obj2StripsCw.SizeOfNonIndexed(is16Bit)); output.Write(0); output.Write(0); output.Write(0); output.Write(0); Obj2StripsCcw.SaveNonIndexed(output, is16Bit); Obj2StripsCw.SaveNonIndexed(output, is16Bit); } }
internal void SaveHeader(EndianBinaryWriter output, bool isIndexed, bool is16Bit) { byte sectionFlags = (byte)( ((Obj1StripsCcw.Count != 0) ? 0x01 : 0) | ((Obj1StripsCw.Count != 0) ? 0x02 : 0) | ((Obj2StripsCcw.Count != 0) ? 0x04 : 0) | ((Obj2StripsCw.Count != 0) ? 0x08 : 0)); IEnumerable <GcmfVertex> allVertices = Obj1StripsCcw.Union(Obj1StripsCw) .Union(Obj2StripsCcw).Union(Obj2StripsCw).SelectMany(sg => sg); uint vertexFlagsCalc = allVertices.First().VertexFlags; if (allVertices.All(v => v.VertexFlags != vertexFlagsCalc)) { throw new InvalidGmaFileException("All vertices within the same mesh must have the same components."); } output.Write((uint)RenderFlags); output.Write(Unk4); output.Write(Unk8); output.Write(UnkC); output.Write(Unk10); byte calculatedUsedMaterialCount = (byte)( ((PrimaryMaterialIdx != ushort.MaxValue) ? 1 : 0) + ((SecondaryMaterialIdx != ushort.MaxValue) ? 1 : 0) + ((TertiaryMaterialIdx != ushort.MaxValue) ? 1 : 0)); output.Write(calculatedUsedMaterialCount); output.Write(sectionFlags); output.Write(Unk14); output.Write(PrimaryMaterialIdx); output.Write(SecondaryMaterialIdx); output.Write(TertiaryMaterialIdx); output.Write(vertexFlagsCalc); output.Write(TransformMatrixSpecificIdxsObj1, 0, 8); if (!isIndexed) { output.Write((Obj1StripsCcw.Count != 0) ? Obj1StripsCcw.SizeOfNonIndexed(is16Bit) : 0); output.Write((Obj1StripsCw.Count != 0) ? Obj1StripsCw.SizeOfNonIndexed(is16Bit) : 0); } else { // This field contains the number of 32-bit integers instead of the number of bytes, hence the div. by 4 output.Write((Obj1StripsCcw.Count != 0) ? (Obj1StripsCcw.SizeOfIndexed() / 4) : 0); output.Write((Obj1StripsCw.Count != 0) ? (Obj1StripsCw.SizeOfIndexed() / 4) : 0); } output.Write(BoundingSphereCenter.X); output.Write(BoundingSphereCenter.Y); output.Write(BoundingSphereCenter.Z); output.Write(Unk3C); output.Write(Unk40); output.Write(0); output.Write(0); output.Write(0); output.Write(0); output.Write(0); output.Write(0); output.Write(0); }
private void RecalculateBoundingSphere() { IEnumerable <GcmfTriangleStrip> allTriangleStrip = Obj1StripsCcw.Union(Obj1StripsCw).Union(Obj2StripsCcw).Union(Obj2StripsCw); IEnumerable <GcmfVertex> allVertices = allTriangleStrip.SelectMany(ts => ts); IEnumerable <Vector3> allVertexPositions = allVertices.Select(v => v.Position); BoundingSphere boundingSphere = BoundingSphere.FromPoints(allVertexPositions); BoundingSphereCenter = boundingSphere.Center; }
internal void SaveIndexedData(EndianBinaryWriter output, Dictionary <GcmfVertex, int> vertexPool) { if (Obj1StripsCcw.Count != 0) { Obj1StripsCcw.SaveIndexed(output, vertexPool); } if (Obj1StripsCw.Count != 0) { Obj1StripsCw.SaveIndexed(output, vertexPool); } }
internal int SizeOfIndexedData() { int size = 0; if (Obj1StripsCcw.Count != 0) { size += Obj1StripsCcw.SizeOfIndexed(); } if (Obj1StripsCw.Count != 0) { size += Obj1StripsCw.SizeOfIndexed(); } return(size); }
internal int SizeOfNonIndexedData(bool is16Bit) { int size = 0; if (Obj1StripsCcw.Count != 0) { size += Obj1StripsCcw.SizeOfNonIndexed(is16Bit); } if (Obj1StripsCw.Count != 0) { size += Obj1StripsCw.SizeOfNonIndexed(is16Bit); } if (Obj2StripsCcw.Count != 0 || Obj2StripsCw.Count != 0) { size += 0x20; // Extra header size += Obj2StripsCcw.SizeOfNonIndexed(is16Bit); size += Obj2StripsCw.SizeOfNonIndexed(is16Bit); } return(size); }
internal void LoadNonIndexedData(EndianBinaryReader input, HeaderSectionInfo headerSectionInfo, bool is16Bit) { if ((headerSectionInfo.SectionFlags & 0x01) != 0 && headerSectionInfo.Chunk1Size == 0) { throw new InvalidGmaFileException("GcmfMeshType1: Chunk1, but chunk1Size == 0?"); } if ((headerSectionInfo.SectionFlags & 0x01) == 0 && headerSectionInfo.Chunk1Size != 0) { throw new InvalidGmaFileException("GcmfMeshType1: No chunk1, but chunk1Size != 0?"); } if ((headerSectionInfo.SectionFlags & 0x01) != 0) { Obj1StripsCcw.LoadNonIndexed(input, headerSectionInfo.Chunk1Size, headerSectionInfo.VertexFlags, is16Bit); } if ((headerSectionInfo.SectionFlags & 0x02) != 0 && headerSectionInfo.Chunk2Size == 0) { throw new InvalidGmaFileException("GcmfMeshType1: Chunk2, but chunk2Size == 0?"); } else if ((headerSectionInfo.SectionFlags & 0x02) == 0 && headerSectionInfo.Chunk2Size != 0) { throw new InvalidGmaFileException("GcmfMeshType1: No chunk2, but chunk2Size != 0?"); } if ((headerSectionInfo.SectionFlags & 0x02) != 0) { Obj1StripsCw.LoadNonIndexed(input, headerSectionInfo.Chunk2Size, headerSectionInfo.VertexFlags, is16Bit); } if ((headerSectionInfo.SectionFlags & 0xFF) == 0x0F) // Those are always used together { // Read extra header before two extra chunks input.Read(TransformMatrixSpecificIdxsObj2, 0, 8); int chunk3Size = input.ReadInt32(); int chunk4Size = input.ReadInt32(); if (input.ReadUInt32() != 0) { throw new InvalidGmaFileException("Expected GcmfMeshType1[ExtraHdr-0x10] == 0"); } if (input.ReadUInt32() != 0) { throw new InvalidGmaFileException("Expected GcmfMeshType1[ExtraHdr-0x14] == 0"); } if (input.ReadUInt32() != 0) { throw new InvalidGmaFileException("Expected GcmfMeshType1[ExtraHdr-0x18]== 0"); } if (input.ReadUInt32() != 0) { throw new InvalidGmaFileException("Expected GcmfMeshType1[ExtraHdr-0x1C] == 0"); } if (chunk3Size == 0) { throw new InvalidGmaFileException("GcmfMeshType1: Chunk3, but chunk3Size == 0?"); } if (chunk4Size == 0) { throw new InvalidGmaFileException("GcmfMeshType1: Chunk4, but chunk4Size == 0?"); } Obj2StripsCcw.LoadNonIndexed(input, chunk3Size, headerSectionInfo.VertexFlags, is16Bit); Obj2StripsCw.LoadNonIndexed(input, chunk4Size, headerSectionInfo.VertexFlags, is16Bit); } else if ((headerSectionInfo.SectionFlags & 0xFC) != 0) { throw new InvalidGmaFileException("GcmfMeshType1: Unknown present chunk flags at chunk10."); } }
/// <summary> /// This is the same as render(), but it skips the material setup step, /// so when rendering all triangle meshes, they only need to be set up once. /// </summary> internal void RenderInternal(IRenderer renderer, GcmfRenderContext context) { /* * if (Layer == GcmfTriangleMeshLayer.Layer1) * { * GL.Disable(EnableCap.Blend); * GL.DepthMask(true); * } * else * { * GL.DepthMask(false); * GL.Enable(EnableCap.Blend); * GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); * } */ // Set up the renderer according to the render flags set renderer.SetTwoSidedFaces((RenderFlags & RenderFlag.TwoSided) != 0); // Very rarely a mesh with a material id set to 0xFFFF ((ushort)-1) is seen. // I believe this is just a that it didn't have a material assigned. if (PrimaryMaterialIdx != ushort.MaxValue) { renderer.BindMaterial(PrimaryMaterialIdx); } else { renderer.UnbindMaterial(); } // Patch the non-null default transformation matrix indexes (for obj1) // with the specific indexes set for this mesh for (int i = 0; i < TransformMatrixSpecificIdxsObj1.Length; i++) { if (TransformMatrixSpecificIdxsObj1[i] != byte.MaxValue) { context.TransformMatrixIdxs[i] = TransformMatrixSpecificIdxsObj1[i]; } } renderer.SetFrontFaceDirection(FrontFaceDirection.Ccw); Obj1StripsCcw.Render(renderer, context); renderer.SetFrontFaceDirection(FrontFaceDirection.Cw); Obj1StripsCw.Render(renderer, context); // Patch the non-null default transformation matrix indexes (for obj2) // with the specific indexes set for this mesh for (int i = 0; i < TransformMatrixSpecificIdxsObj2.Length; i++) { if (TransformMatrixSpecificIdxsObj2[i] != byte.MaxValue) { context.TransformMatrixIdxs[i] = TransformMatrixSpecificIdxsObj2[i]; } } renderer.SetFrontFaceDirection(FrontFaceDirection.Ccw); Obj2StripsCcw.Render(renderer, context); renderer.SetFrontFaceDirection(FrontFaceDirection.Cw); Obj2StripsCw.Render(renderer, context); }