/// <summary> /// Create objects from model. Requires FrameMesh/FrameModel to be already set and a model already read into the data. /// </summary> public void CreateObjectsFromModel() { frameGeometry = new FrameGeometry(); frameMaterial = new FrameMaterial(); //set lods for all data. indexBuffers = new IndexBuffer[model.Lods.Length]; vertexBuffers = new VertexBuffer[model.Lods.Length]; List <Vertex[]> vertData = new List <Vertex[]>(); for (int i = 0; i != model.Lods.Length; i++) { vertData.Add(model.Lods[i].Vertices); } frameMesh.Boundings = new BoundingBox(); frameMesh.Boundings.CalculateBounds(vertData); frameMaterial.Bounds = FrameMesh.Boundings; CalculateDecompression(); UpdateObjectsFromModel(); BuildIndexBuffer("M2TK." + model.Name + ".IB0"); BuildVertexBuffer("M2TK." + model.Name + ".VB0"); frameGeometry.LOD[0].IndexBufferRef = new Hash("M2TK." + model.Name + ".IB0"); frameGeometry.LOD[0].VertexBufferRef = new Hash("M2TK." + model.Name + ".VB0"); }
/// <summary> /// Constructor used to build Lods. This is used when you want to compile all mesh data together, ready for exporting. /// </summary> public Model(FrameObjectModel frameModel, IndexBuffer[] indexBuffers, VertexBuffer[] vertexBuffers, FrameGeometry frameGeometry, FrameMaterial frameMaterial) { this.frameModel = frameModel; this.indexBuffers = indexBuffers; this.vertexBuffers = vertexBuffers; this.frameGeometry = frameGeometry; this.frameMaterial = frameMaterial; model = new M2TStructure(); model.IsSkinned = true; model.Name = frameMesh.Name.String; model.BuildLods(frameGeometry, frameMaterial, vertexBuffers, indexBuffers); }
/// <summary> /// Build Lods from retrieved data. /// </summary> public void BuildLods(FrameGeometry frameGeometry, FrameMaterial frameMaterial, VertexBuffer[] vertexBuffers, IndexBuffer[] indexBuffers) { lods = new Lod[frameGeometry.NumLods]; for (int i = 0; i != lods.Length; i++) { FrameLOD frameLod = frameGeometry.LOD[i]; lods[i] = new Lod { VertexDeclaration = frameGeometry.LOD[i].VertexDeclaration }; IndexBuffer indexBuffer = indexBuffers[i]; VertexBuffer vertexBuffer = vertexBuffers[i]; int vertexSize; Dictionary <VertexFlags, FrameLOD.VertexOffset> vertexOffsets = frameLod.GetVertexOffsets(out vertexSize); lods[i].NumUVChannels = 4; lods[i].Vertices = new Vertex[frameLod.NumVertsPr]; for (int v = 0; v != lods[i].Vertices.Length; v++) { Vertex vertex = new Vertex(); vertex.UVs = new UVVector2[lods[i].NumUVChannels]; if (lods[i].VertexDeclaration.HasFlag(VertexFlags.Position)) { int startIndex = v * vertexSize + vertexOffsets[VertexFlags.Position].Offset; vertex.ReadPositionData(vertexBuffer.Data, startIndex, frameGeometry.DecompressionFactor, frameGeometry.DecompressionOffset); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.Tangent)) { int startIndex = v * vertexSize + vertexOffsets[VertexFlags.Position].Offset; vertex.ReadTangentData(vertexBuffer.Data, startIndex); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.Normals)) { int startIndex = v * vertexSize + vertexOffsets[VertexFlags.Normals].Offset; vertex.ReadNormalData(vertexBuffer.Data, startIndex); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.BlendData)) { int startIndex = v * vertexSize + vertexOffsets[VertexFlags.BlendData].Offset; vertex.ReadBlendData(vertexBuffer.Data, startIndex); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.flag_0x80)) { Console.WriteLine("Skip vertex with flag_0x80"); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.TexCoords0)) { int startIndex = v * vertexSize + vertexOffsets[VertexFlags.TexCoords0].Offset; vertex.ReadUvData(vertexBuffer.Data, startIndex, 0); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.TexCoords1)) { int startIndex = v * vertexSize + vertexOffsets[VertexFlags.TexCoords1].Offset; vertex.ReadUvData(vertexBuffer.Data, startIndex, 1); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.TexCoords2)) { int startIndex = v * vertexSize + vertexOffsets[VertexFlags.TexCoords2].Offset; vertex.ReadUvData(vertexBuffer.Data, startIndex, 2); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.TexCoords7)) { int startIndex = v * vertexSize + vertexOffsets[VertexFlags.TexCoords7].Offset; vertex.ReadUvData(vertexBuffer.Data, startIndex, 3); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.flag_0x20000)) { Console.WriteLine("Skip vertex with flag_0x20000"); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.flag_0x40000)) { Console.WriteLine("Skip vertex with flag_0x40000"); } if (lods[i].VertexDeclaration.HasFlag(VertexFlags.DamageGroup)) { int startIndex = v * vertexSize + vertexOffsets[VertexFlags.DamageGroup].Offset; vertex.ReadDamageGroup(vertexBuffer.Data, startIndex); } if (lods[i].NormalMapInfoPresent) { vertex.BuildBinormals(); } lods[i].Vertices[v] = vertex; MaterialStruct[] materials = frameMaterial.Materials[i]; lods[i].Parts = new ModelPart[materials.Length]; for (int x = 0; x != materials.Length; x++) { ModelPart modelPart = new ModelPart(); Material mat = MaterialsManager.LookupMaterialByHash(materials[x].MaterialHash); if (mat == null || mat.SPS.Length == 0) { modelPart.Material = "_test_gray"; } else { modelPart.Material = (mat == null) ? "null" : mat.SPS[0].File; } int num = materials[x].StartIndex + materials[x].NumFaces * 3; List <Short3> intList = new List <Short3>(materials[x].NumFaces); int startIndex = materials[x].StartIndex; while (startIndex < num) { Short3 indice = new Short3(); indice.S1 = indexBuffer.Data[startIndex + 0]; indice.S2 = indexBuffer.Data[startIndex + 1]; indice.S3 = indexBuffer.Data[startIndex + 2]; intList.Add(indice); startIndex += 3; } modelPart.Indices = intList.ToArray(); lods[i].Parts[x] = modelPart; } } } }
/// <summary> /// Reads the file into the memory. /// </summary> /// <param name="reader"></param> public void ReadFromFile(BinaryReader reader) { header = new FrameHeader(); header.ReadFromFile(reader); objectTypes = new int[header.NumObjects]; frameBlocks = new int[header.SceneFolders.Length + header.NumGeometries + header.NumMaterialResources + header.NumBlendInfos + header.NumSkeletons + header.NumSkelHierachies]; int j = 0; for (int i = 0; i != header.SceneFolders.Length; i++) { frameScenes.Add(header.SceneFolders[i].RefID, header.SceneFolders[i]); frameBlocks[j++] = header.SceneFolders[i].RefID; } for (int i = 0; i != header.NumGeometries; i++) { FrameGeometry geo = new FrameGeometry(reader); frameGeometries.Add(geo.RefID, geo); frameBlocks[j++] = geo.RefID; } for (int i = 0; i != header.NumMaterialResources; i++) { FrameMaterial mat = new FrameMaterial(reader); frameMaterials.Add(mat.RefID, mat); frameBlocks[j++] = mat.RefID; } for (int i = 0; i != header.NumBlendInfos; i++) { FrameBlendInfo blendInfo = new FrameBlendInfo(reader); frameBlendInfos.Add(blendInfo.RefID, blendInfo); frameBlocks[j++] = blendInfo.RefID; } for (int i = 0; i != header.NumSkeletons; i++) { FrameSkeleton skeleton = new FrameSkeleton(reader); frameSkeletons.Add(skeleton.RefID, skeleton); frameBlocks[j++] = skeleton.RefID; } for (int i = 0; i != header.NumSkelHierachies; i++) { FrameSkeletonHierachy skeletonHierachy = new FrameSkeletonHierachy(reader); frameSkeletonHierachies.Add(skeletonHierachy.RefID, skeletonHierachy); frameBlocks[j++] = skeletonHierachy.RefID; } if (header.NumObjects > 0) { for (int i = 0; i != header.NumObjects; i++) { objectTypes[i] = reader.ReadInt32(); } for (int i = 0; i != header.NumObjects; i++) { FrameObjectBase newObject = new FrameObjectBase(); if (objectTypes[i] == (int)ObjectType.Joint) { newObject = new FrameObjectJoint(reader); } else if (objectTypes[i] == (int)ObjectType.SingleMesh) { newObject = new FrameObjectSingleMesh(reader); FrameObjectSingleMesh mesh = newObject as FrameObjectSingleMesh; if (mesh.MeshIndex != -1) { mesh.AddRef(FrameEntryRefTypes.Mesh, frameBlocks[mesh.MeshIndex]); } if (mesh.MaterialIndex != -1) { mesh.AddRef(FrameEntryRefTypes.Material, frameBlocks[mesh.MaterialIndex]); } } else if (objectTypes[i] == (int)ObjectType.Frame) { newObject = new FrameObjectFrame(reader); } else if (objectTypes[i] == (int)ObjectType.Light) { newObject = new FrameObjectLight(reader); } else if (objectTypes[i] == (int)ObjectType.Camera) { newObject = new FrameObjectCamera(reader); } else if (objectTypes[i] == (int)ObjectType.Component_U00000005) { newObject = new FrameObjectComponent_U005(reader); } else if (objectTypes[i] == (int)ObjectType.Sector) { newObject = new FrameObjectSector(reader); } else if (objectTypes[i] == (int)ObjectType.Dummy) { newObject = new FrameObjectDummy(reader); } else if (objectTypes[i] == (int)ObjectType.ParticleDeflector) { newObject = new FrameObjectDeflector(reader); } else if (objectTypes[i] == (int)ObjectType.Area) { newObject = new FrameObjectArea(reader); } else if (objectTypes[i] == (int)ObjectType.Target) { newObject = new FrameObjectTarget(reader); } else if (objectTypes[i] == (int)ObjectType.Model) { FrameObjectModel mesh = new FrameObjectModel(reader); mesh.ReadFromFile(reader); mesh.ReadFromFilePart2(reader, frameSkeletons[frameBlocks[mesh.SkeletonIndex]], frameBlendInfos[frameBlocks[mesh.BlendInfoIndex]]); mesh.AddRef(FrameEntryRefTypes.Mesh, frameBlocks[mesh.MeshIndex]); mesh.AddRef(FrameEntryRefTypes.Material, frameBlocks[mesh.MaterialIndex]); mesh.AddRef(FrameEntryRefTypes.BlendInfo, frameBlocks[mesh.BlendInfoIndex]); mesh.AddRef(FrameEntryRefTypes.Skeleton, frameBlocks[mesh.SkeletonIndex]); mesh.AddRef(FrameEntryRefTypes.SkeletonHierachy, frameBlocks[mesh.SkeletonHierachyIndex]); newObject = mesh; } else if (objectTypes[i] == (int)ObjectType.Collision) { newObject = new FrameObjectCollision(reader); } frameObjects.Add(newObject.RefID, newObject); } } DefineFrameBlockParents(); }