public bool Render(RenderMode mode, float scale, BCA animation, int frame) { bool rendered_something = false; for (int i = 0; i < m_ModelChunks.Length; i++) { ModelChunk mdchunk = m_ModelChunks[i]; if (animation != null && frame > -1) { if (mdchunk.Render(mode, scale, animation, frame)) { rendered_something = true; } } else { if (mdchunk.Render(mode, scale)) { rendered_something = true; } } } return(rendered_something); }
private void WriteObject(TextWriter w, ModelChunk model, string fileName) { w.WriteLine("mtllib {0}.mtl", Path.GetFileNameWithoutExtension(fileName)); w.WriteLine(); Vector3 scale; Quaternion rotation; Vector3 translation; Matrix4x4.Decompose(model.Matrix, out scale, out rotation, out translation); foreach (var vertex in model.Mesh.Vertices) { var v = Vector3.Transform(vertex, model.Matrix); //Matrice invertita w.WriteLine(string.Format(CultureInfo.InvariantCulture, "v {0:0.0000} {1:0.0000} {2:0.0000}", v.X, v.Y, v.Z)); } w.WriteLine(); foreach (var vn in model.Mesh.Normals) { w.WriteLine(string.Format(CultureInfo.InvariantCulture, "vn {0:0.0000} {1:0.0000} {2:0.0000}", vn.X, vn.Y, vn.Z)); } w.WriteLine(); foreach (var vt in model.Mesh.UV) { w.WriteLine(string.Format(CultureInfo.InvariantCulture, "vt {0:0.0000} {1:0.0000} {2:0.0000}", vt.X, 0.0f - vt.Y, 0.0f)); } w.WriteLine(); w.WriteLine("g " + model.Name); // Face indices: S4 starts at 0 - Wavefront OBJ at 1 foreach (var texture in model.TextureData.Textures) { var tex = texture.FileName; foreach (var c in Path.GetInvalidPathChars()) { tex = tex.Replace(c, '?'); } foreach (var c in Path.GetInvalidFileNameChars()) { tex = tex.Replace(c, '?'); } tex = tex.Replace("?", ""); tex = tex.Replace("�", ""); w.WriteLine("usemtl " + Path.GetFileNameWithoutExtension(tex)); w.WriteLine(); for (int i = texture.FaceCounter; i < (texture.FaceCount + texture.FaceCounter); i++) { var face = model.Mesh.Faces[i]; float x = face.X + 1; float y = face.Y + 1; float z = face.Z + 1; w.WriteLine(string.Format(CultureInfo.InvariantCulture, "f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}", x, y, z)); } w.WriteLine(); } }
public void DestroyModel() { if (_model == null) { return; } SharpCraft.Instance.RunGlContext(_model.Destroy); _model = null; }
public Model(byte[] vox) { // MagicaVox standards: magicNumber = 4 bytes, versionNumber = 4 bytes // Set magic number; From byte 0 to byte 3 (4 bytes) -> cant use BitConverter since MagicNumber is big endian MagicNumber = " "; StringBuilder builder = new StringBuilder(4); for (int i = 0; i < 4; i++) { builder[i] = Convert.ToChar(vox[i]); } MagicNumber = builder.ToString(); // Set version number; From byte 4 to byte 7 (4 bytes) VersionNumber = BitConverter.ToInt32(vox, 4); MainChunk = new ModelChunk(vox, 8); }
public void ChangeTexture(ModelChunk model, IList <string> textures) { var texts = model.TextureData.Textures; var txt = new List <TextureEntry>(); for (int i = 0; i < texts.Count; i++) { txt.Add(new TextureEntry { FileName = textures[i], FileName2 = texts[i].FileName2, FaceCount = texts[i].FaceCount, FaceCounter = texts[i].FaceCounter }); } model.TextureData.Textures = txt; }
public void Export(string fileName, ModelChunk model) { try { using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) { } } catch { fileName = fileName.Replace(model.Name, "invalid_file_name"); } using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) using (var w = new StreamWriter(fs)) { WriteObject(w, model, fileName); } string mtl = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".mtl"); using (var fs = new FileStream(mtl, FileMode.Create, FileAccess.Write, FileShare.None)) using (var w = new StreamWriter(fs)) { WriteMaterial(w, model); } }
private void WriteMaterial(TextWriter w, ModelChunk model) { var ls = new List <string>(); foreach (var texture in model.TextureData.Textures) { var tex = texture.FileName; foreach (var c in Path.GetInvalidPathChars()) { tex = tex.Replace(c, '?'); } foreach (var c in Path.GetInvalidFileNameChars()) { tex = tex.Replace(c, '?'); } tex = tex.Replace("?", ""); tex = tex.Replace("�", ""); string name = Path.GetFileNameWithoutExtension(tex); if (ls.Contains(name)) { continue; } w.WriteLine("newmtl {0}", name); w.WriteLine("\tNs 10.0000"); w.WriteLine("\tNi 1.5000"); w.WriteLine("\td 1.0000"); w.WriteLine("\tTr 0.0000"); w.WriteLine("\tTf 1.0000 1.0000 1.0000"); w.WriteLine("\tillum 2"); w.WriteLine("\tKa 0.5880 0.5880 0.5880"); w.WriteLine("\tKd 0.5880 0.5880 0.5880"); w.WriteLine("\tKs 0.0000 0.0000 0.0000"); w.WriteLine("\tKe 0.0000 0.0000 0.0000"); w.WriteLine("\tmap_Ka {0}", tex); w.WriteLine("\tmap_Kd {0}", tex); w.WriteLine(); ls.Add(name); } }
public Model(byte[] vox) { // MagicaVox standards: magicNumber = 4 bytes, versionNumber = 4 bytes // Set magic number; From byte 0 to byte 3 (4 bytes) -> cant use BitConverter since MagicNumber is big endian MagicNumber = " "; StringBuilder builder = new StringBuilder(4); for (int i = 0; i < 4; i++) { builder[i] = Convert.ToChar(vox[i]); } MagicNumber = builder.ToString(); // Set version number; From byte 4 to byte 7 (4 bytes) VersionNumber = BitConverter.ToInt32(vox, 4); MainChunk = new ModelChunk(vox, 8); }
protected override void Visit(ModelChunk chunk) { // TODO: Remove this ModelChunk handling point, make the model directive more generic. var modelTokens = new List <RazorDirectiveToken>() { new RazorDirectiveToken { Descriptor = new RazorDirectiveTokenDescriptor { Type = RazorDirectiveTokenType.Type }, Value = chunk.ModelType, } }; var modelDirective = new RazorSingleLineDirective() { Name = "model", Tokens = modelTokens, }; _context.Builder.Add(modelDirective); }
public void ReplaceModel(string fileName, ModelChunk model, string textureName) { var VertexList = new List <Vector3>(); var NormalList = new List <Vector3>(); var UVList = new List <Vector2>(); var FacesList = new List <Vector3>(); var obj = new Obj(); obj.LoadObj(fileName); if (obj == null) { return; } var _matrix = new Matrix4x4(); Matrix4x4.Invert(model.Matrix, out _matrix); for (int index = 0; index < obj.VertexList.Count; index++) { VertexList.Add(new Vector3(float.Parse(obj.VertexList[index].X.ToString()), float.Parse(obj.VertexList[index].Y.ToString()), float.Parse(obj.VertexList[index].Z.ToString()))); } for (int index = 0; index < obj.NormalList.Count; index++) { NormalList.Add(new Vector3(float.Parse(obj.NormalList[index].X.ToString()), float.Parse(obj.NormalList[index].Y.ToString()), float.Parse(obj.NormalList[index].Z.ToString()))); } for (int index = 0; index < obj.TextureList.Count; index++) { UVList.Add(new Vector2(float.Parse(obj.TextureList[index].X.ToString()), 0.0f - float.Parse(obj.TextureList[index].Y.ToString()))); } var vector_temp = new List <Vector3>(); for (int index = 0; index < VertexList.Count; index++) { var temp = Vector3.Transform(VertexList[index], _matrix); vector_temp.Add(temp); } for (int index = 0; index < obj.FaceList.Count; index++) { string face = obj.FaceList[index].ToString(); string[] face_array = face.Split(' '); string X = Convert.ToString(face_array[1]); string Y = Convert.ToString(face_array[2]); string Z = Convert.ToString(face_array[3]); string[] _X = X.Split('/'); string[] _Y = Y.Split('/'); string[] _Z = Z.Split('/'); FacesList.Add(new Vector3(Convert.ToInt32(_X[0]) - 1, Convert.ToInt32(_Y[0]) - 1, Convert.ToInt32(_Z[0]) - 1)); } var texture = new TextureEntry(); texture.FaceCount = obj.FaceList.Count; texture.FaceCounter = 0; texture.FileName = string.IsNullOrEmpty(textureName) ? model.TextureData.Textures[0].FileName : textureName; texture.FileName2 = model.TextureData.Textures[0].FileName2; if (model.TextureData.Textures.Count != 0) { model.TextureData.Textures[0] = texture; } else { model.TextureData.Textures.Add(texture); } model.Mesh.Vertices = vector_temp; model.Mesh.Normals = NormalList; model.Mesh.UV = UVList; model.Mesh.Faces = FacesList; }
public override void OnClick() { if (loaded) { return; } STGenericModel model = new STGenericModel(Label); model.Skeleton = new SkeletonFormat(); for (int i = 0; i < DataParser.Files.Count; i++) { if (DataParser.Files[i].Hash == File.Hash && DataParser.Files[i].ChunkEntry.ChunkType == ChunkFileType.Skeleton) { if (DataParser.Version == DICT.GameVersion.LM2) { model.Skeleton = LM2.SkeletonChunk.Read(DataParser.Files[i].ChunkEntry.SubData); } if (DataParser.Version == DICT.GameVersion.LM3) { model.Skeleton = LM3.SkeletonChunk.Read(DataParser.Files[i].ChunkEntry.SubData); } } } Dictionary <uint, int> boneHashToID = ((SkeletonFormat)model.Skeleton).BoneHashToID; if (DataParser.Version == DICT.GameVersion.LM3) { var modelList = ModelChunk.Read(File.ChunkEntry.SubData, boneHashToID); /* var materialChunk = File.ChunkEntry.SubData.FirstOrDefault(x => x.ChunkType == ChunkDataType.MaterialData); * var materialLookupChunk = File.ChunkEntry.SubData.FirstOrDefault(x => x.ChunkType == ChunkDataType.MaterialLookupTable); * * var matChunks = MaterialLoaderHelper.CreateMaterialChunkList(materialChunk.Data, * materialLookupChunk.Data, modelList.SelectMany(x => x.Meshes).ToList());*/ int index = 0; foreach (var mdl in modelList) { foreach (var mesh in mdl.Meshes) { var genericMesh = new STGenericMesh(); genericMesh.Name = Hashing.CreateHashString(mesh.MeshHeader.Hash); if (Hashing.HashNames.ContainsKey(mesh.MeshHeader.MaterialHash)) { genericMesh.Name += $"_{Hashing.CreateHashString(mesh.MeshHeader.MaterialHash)}"; } Console.WriteLine($"MESH_HASHM {Hashing.CreateHashString(mesh.MeshHeader.MaterialHash)}"); Console.WriteLine($"MESH_HASHV {Hashing.CreateHashString(mesh.MeshHeader.VertexFormatHash)}"); genericMesh.Vertices.AddRange(mesh.Vertices); var poly = new STPolygonGroup(); poly.Faces = mesh.Faces.ToList(); genericMesh.PolygonGroups.Add(poly); model.Meshes.Add(genericMesh); var material = new LMMaterial(); poly.Material = material; material.TextureMaps.Add(new STGenericTextureMap() { Name = Hashing.CreateHashString(mesh.Material.DiffuseHash), Type = STTextureType.Diffuse, }); index++; } } } else { var modelList = LM2.ModelChunk.Read(File.ChunkEntry.SubData, boneHashToID); foreach (var mdl in modelList) { foreach (var mesh in mdl.Meshes) { var genericMesh = new STGenericMesh(); genericMesh.Name = Hashing.CreateHashString(mesh.MeshHeader.Hash); if (Hashing.HashNames.ContainsKey(mesh.MeshHeader.MaterialHash)) { genericMesh.Name += $"_{Hashing.CreateHashString(mesh.MeshHeader.MaterialHash)}"; } genericMesh.Name += $"_{mesh.MeshHeader.VertexFormatHash}_{VertexLoaderExtension.GetStride(mesh.MeshHeader.VertexFormatHash)}"; uint vertexStride = VertexLoaderExtension.GetStride(mesh.MeshHeader.VertexFormatHash); if (mesh.Vertices.Count == 0) { continue; } genericMesh.Vertices.AddRange(mesh.Vertices); var poly = new STPolygonGroup(); poly.Faces = mesh.Faces.ToList(); genericMesh.PolygonGroups.Add(poly); model.Meshes.Add(genericMesh); var material = new LMMaterial(); material.IsAmbientMap = mesh.Material.IsAmbientMap; poly.Material = material; material.TextureMaps.Add(new STGenericTextureMap() { Name = Hashing.CreateHashString(mesh.Material.DiffuseTextureHash), Type = STTextureType.Diffuse, }); if (mesh.Material.HasShadowMap) { material.TextureMaps.Add(new STGenericTextureMap() { Name = Hashing.CreateHashString(mesh.Material.ShadowTextureHash), Type = STTextureType.Shadow, }); } } } } Tag = new ModelFormat(model); foreach (var child in model.CreateTreeHiearchy().Children) { AddChild(child); } loaded = true; }
public void Import(string fileName, string textureName, string sceneName, string sceneSubname, SceneContainer container) { var VertexList = new List <Vector3>(); var NormalList = new List <Vector3>(); var UVList = new List <Vector2>(); var FacesList = new List <Vector3>(); var obj = new Obj(); obj.LoadObj(fileName); if (obj == null) { return; } var model = new ModelChunk(container); for (int index = 0; index < obj.VertexList.Count; index++) { VertexList.Add(new Vector3(float.Parse(obj.VertexList[index].X.ToString()) / 100, float.Parse(obj.VertexList[index].Y.ToString()) / 100, float.Parse(obj.VertexList[index].Z.ToString()) / 100)); } for (int index = 0; index < obj.NormalList.Count; index++) { NormalList.Add(new Vector3(float.Parse(obj.NormalList[index].X.ToString()) / 100, float.Parse(obj.NormalList[index].Y.ToString()) / 100, float.Parse(obj.NormalList[index].Z.ToString()) / 100)); } for (int index = 0; index < obj.TextureList.Count; index++) { UVList.Add(new Vector2(float.Parse(obj.TextureList[index].X.ToString()) / 100, 0.0f - float.Parse(obj.TextureList[index].Y.ToString()) / 100)); } for (int index = 0; index < VertexList.Count; index++) { model.Mesh.Vertices.Add(VertexList[index]); } for (int index = 0; index < obj.FaceList.Count; index++) { string face = obj.FaceList[index].ToString(); string[] face_array = face.Split(' '); string X = Convert.ToString(face_array[1]); string Y = Convert.ToString(face_array[2]); string Z = Convert.ToString(face_array[3]); string[] _X = X.Split('/'); string[] _Y = Y.Split('/'); string[] _Z = Z.Split('/'); FacesList.Add(new Vector3(Convert.ToInt32(_X[0]) - 1, Convert.ToInt32(_Y[0]) - 1, Convert.ToInt32(_Z[0]) - 1)); } var texture = new TextureEntry { FaceCount = obj.FaceList.Count, FaceCounter = 0, FileName = textureName, FileName2 = "" }; if (model.TextureData.Textures.Count != 0) { model.TextureData.Textures[0] = texture; } else { model.TextureData.Textures.Add(texture); } model.Mesh.Normals = NormalList; model.Mesh.UV = UVList; model.Mesh.Faces = FacesList; model.Name = sceneName; model.SubName = sceneSubname; model.Image = Properties.Resources.model; container.Add(model); }
private void Visit(ModelChunk chunk) { ModelType = chunk.ModelType; }
public void EditAnimation(ModelChunk model, IList <ModelAnimation> animation) => model.Animation = animation;
public void EditShader(ModelChunk model, Shader shader) => model.Shader = shader;
public void BuildChunkModelNow() { if (ModelBuilding || !QueuedForModelBuild) { return; } ModelBuilding = true; //ConcurrentDictionary<Shader<ModelBlock>, List<RawQuad>> modelRaw = new ConcurrentDictionary<Shader<ModelBlock>, List<RawQuad>>(); //List<RawQuad> quads; Stopwatch sw = Stopwatch.StartNew(); //this is just a debug thing.... var air = BlockRegistry.GetBlock <BlockAir>(); var vertexes = new List <float>(); var normals = new List <float>(); var uvs = new List <float>(); object locker = new object(); //generate the model - fill MODEL_RAW Enumerable.Range(0, ChunkHeight).AsParallel().ForAll(y => { for (int x = 0; x < ChunkSize; x++) { for (int z = 0; z < ChunkSize; z++) { BlockPos worldPos = new BlockPos(x + Pos.WorldSpaceX(), y, z + Pos.WorldSpaceZ()); BlockState state = World.GetBlockState(worldPos); if (state.Block == air) { continue; } BlockPos localPos = new BlockPos(x, y, z); ModelBlockRaw mbr = (ModelBlockRaw)state.Model?.RawModel; if (mbr == null) { continue; } if (!state.Block.IsFullCube) { lock (locker) mbr.AppendAllVertexData(vertexes, normals, uvs, localPos); continue; } for (var index = 0; index < FaceSides.AllSides.Count; index++) { FaceSides dir = FaceSides.AllSides[index]; BlockPos worldPosO = worldPos.Offset(dir); BlockState stateO = World.GetBlockState(worldPosO); if (!(stateO.Block == air || stateO.Block.HasTransparency && !state.Block.HasTransparency) && stateO.Block.IsFullCube) { continue; } lock (locker) { mbr.AppendVertexDataForSide(dir, vertexes, normals, uvs, localPos); //mbr.AppendNormalsForSide(dir, normals); //mbr.AppendUvsForSide(dir, uvs); } } } } }); sw.Stop(); Console.WriteLine($"DEBUG: built chunk model [{sw.Elapsed.TotalMilliseconds:F}ms]"); float[] vtx = vertexes.ToArray(); //this is here because this takes time and I don't want it to slow down the main thread by running it in GlContext float[] nrm = normals.ToArray(); float[] uv = uvs.ToArray(); SharpCraft.Instance.RunGlContext(() => { if (_model == null) { _model = new ModelChunk(vtx, nrm, uv, Block.DefaultShader); } else { _model.OverrideData(vtx, nrm, uv); } ModelBuilding = false; }); QueuedForModelBuild = false; }
public bool loadFile(string filename) { LuaState vm = new LuaState(); LuaExt.extendLua(vm); try { if (vm.doFile(filename) == false) { Warn.print("Unable to open BOB file {0}", filename); return(false); } LuaObject data = vm.findObject("BOB"); if (data == null) { Warn.print("Unable to find BOB data in file {0}", filename); return(false); } myVersion = data.get <UInt32>("version"); //read the registry LuaObject registry = data.get <LuaObject>("registry"); parseRegistry(registry); //read the chunks LuaObject chunks = data.get <LuaObject>("chunks"); for (int i = 1; i <= chunks.count(); i++) { LuaObject chunkData = chunks[i]; switch (chunkData.get <String>("type")) { case "model": ModelChunk model = new ModelChunk(); parseModel(model, chunkData); myChunks.Add(model); break; case "skeleton": SkeletonChunk skeleton = new SkeletonChunk(); parseSkeleton(skeleton, chunkData); myChunks.Add(skeleton); break; case "animation": AnimationChunk animation = new AnimationChunk(); parseAnimation(animation, chunkData); myChunks.Add(animation); break; case "texture": Warn.print("Skipping .BOB texture"); break; case "particle": Warn.print("Skipping .BOB particle system"); break; case "audio": Warn.print("Skipping .BOB audio"); break; default: Warn.print("Unknown type: {0}", chunkData.get <String>("type")); break; } } } catch (Exception ex) { throw new Exception("Error while loading BOB model from definition file ( " + filename + " ).", ex); } return(true); }
public override void GenerateChunk(Span target, ChunkGeneratorContext context) { var modelChunk = new ModelChunk(ModelType); context.ChunkTreeBuilder.AddChunk(modelChunk, target, topLevel: true); }
protected virtual void Visit(ModelChunk chunk) { // TODO: Should remove once a more generic directive chunk is created. }
public BMD(NitroFile file) { m_File = file; m_FileName = file.m_Name; /* if (m_File.m_ID == 741) * lolol = true; * else*/ lolol = false; // Keep a list of pointers so it's easier to add/remove entries, space etc. m_PointerList = new List <PointerReference>(); m_ScaleFactor = (float)(1 << (int)m_File.Read32(0x0)); // ModelChunk refers to Bone m_NumModelChunks = m_File.Read32(0x04); m_ModelChunksOffset = m_File.Read32(0x08); AddPointer(0x08); for (int i = 0; i < m_NumModelChunks; i++) { AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x04)); AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x34)); AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x38)); } // PolyChunk refers to Display List m_NumPolyChunks = m_File.Read32(0x0C); m_PolyChunksOffset = m_File.Read32(0x10); AddPointer(0x10); for (int i = 0; i < m_NumPolyChunks; i++) { // Offset to Display List within Display List entries AddPointer((uint)(m_PolyChunksOffset + (i * 8) + 4)); // Offsets within the Display List 16 byte headers AddPointer(m_File.Read32((uint)(m_PolyChunksOffset + (i * 8) + 4)) + 0x04); AddPointer(m_File.Read32((uint)(m_PolyChunksOffset + (i * 8) + 4)) + 0x0C); } m_NumTexChunks = m_File.Read32(0x14); m_TexChunksOffset = m_File.Read32(0x18); m_TextureIDs = new Dictionary <string, uint>(); AddPointer(0x18); for (int i = 0; i < m_NumTexChunks; i++) { AddPointer((uint)(m_TexChunksOffset + (i * 20) + 0)); AddPointer((uint)(m_TexChunksOffset + (i * 20) + 4)); m_TextureIDs.Add(m_File.ReadString(m_File.Read32((uint)(m_TexChunksOffset + (20 * i))), 0), (uint)i); } m_NumPalChunks = m_File.Read32(0x1C); m_PalChunksOffset = m_File.Read32(0x20); m_PaletteIDs = new Dictionary <string, uint>(); AddPointer(0x20); for (int i = 0; i < m_NumPalChunks; i++) { AddPointer((uint)(m_PalChunksOffset + (i * 16) + 0)); AddPointer((uint)(m_PalChunksOffset + (i * 16) + 4)); m_PaletteIDs.Add(m_File.ReadString(m_File.Read32((uint)(m_PalChunksOffset + (16 * i))), 0), (uint)i); } m_NumMatChunks = m_File.Read32(0x24); m_MatChunksOffset = m_File.Read32(0x28); AddPointer(0x28); for (int i = 0; i < m_NumMatChunks; i++) { AddPointer((uint)(m_MatChunksOffset + (i * 48) + 0)); } m_BoneMapOffset = m_File.Read32(0x2C); AddPointer(0x2C); m_Textures = new Dictionary <string, NitroTexture>(); m_ModelChunks = new ModelChunk[m_NumModelChunks]; for (uint c = 0; c < m_NumModelChunks; c++) { ModelChunk mdchunk = new ModelChunk(this); m_ModelChunks[c] = mdchunk; uint mdchunkoffset = m_ModelChunksOffset + (c * 64); mdchunk.m_ID = m_File.Read32(mdchunkoffset); mdchunk.m_Name = m_File.ReadString(m_File.Read32(mdchunkoffset + 0x04), 0); // transforms part { int xscale = (int)m_File.Read32(mdchunkoffset + 0x10); int yscale = (int)m_File.Read32(mdchunkoffset + 0x14); int zscale = (int)m_File.Read32(mdchunkoffset + 0x18); short xrot = (short)m_File.Read16(mdchunkoffset + 0x1C); short yrot = (short)m_File.Read16(mdchunkoffset + 0x1E); short zrot = (short)m_File.Read16(mdchunkoffset + 0x20); int xtrans = (int)m_File.Read32(mdchunkoffset + 0x24); int ytrans = (int)m_File.Read32(mdchunkoffset + 0x28); int ztrans = (int)m_File.Read32(mdchunkoffset + 0x2C); mdchunk.m_Scale = new Vector3((float)xscale / 4096.0f, (float)yscale / 4096.0f, (float)zscale / 4096.0f); mdchunk.m_Rotation = new Vector3(((float)xrot * (float)Math.PI) / 2048.0f, ((float)yrot * (float)Math.PI) / 2048.0f, ((float)zrot * (float)Math.PI) / 2048.0f); mdchunk.m_Translation = new Vector3((float)xtrans / 4096.0f, (float)ytrans / 4096.0f, (float)ztrans / 4096.0f); mdchunk.m_Transform = Helper.SRTToMatrix(mdchunk.m_Scale, mdchunk.m_Rotation, mdchunk.m_Translation); // Used when exporting bones mdchunk.m_20_12Scale = new uint[] { (uint)xscale, (uint)yscale, (uint)zscale }; mdchunk.m_4_12Rotation = new ushort[] { (ushort)xrot, (ushort)yrot, (ushort)zrot }; mdchunk.m_20_12Translation = new uint[] { (uint)xtrans, (uint)ytrans, (uint)ztrans }; // if the chunk has a parent, apply the parent's transform to the chunk's transform. // we don't need to go further than one level because the paren't transform already // went through its parents' transforms. short parent_offset = (short)m_File.Read16(mdchunkoffset + 0x8); if (parent_offset < 0) { int parentchunkid = (int)(c + parent_offset); Matrix4.Mult(ref mdchunk.m_Transform, ref m_ModelChunks[parentchunkid].m_Transform, out mdchunk.m_Transform); } mdchunk.m_ParentOffset = parent_offset; } // If 0x0A is set to 1 the bone has children, if 0 it doesn't mdchunk.m_HasChildren = (m_File.Read16(mdchunkoffset + 0x0A) == 1); mdchunk.m_SiblingOffset = (short)(m_File.Read16(mdchunkoffset + 0x0C)); uint flags = m_File.Read32(mdchunkoffset + 0x3C); mdchunk.m_Billboard = ((flags & 0x1) == 0x1); uint numpairs = m_File.Read32(mdchunkoffset + 0x30); uint matlist = m_File.Read32(mdchunkoffset + 0x34); uint polylist = m_File.Read32(mdchunkoffset + 0x38); mdchunk.m_MatGroups = new MaterialGroup[numpairs]; for (uint i = 0; i < numpairs; i++) { MaterialGroup matgroup = new MaterialGroup(); mdchunk.m_MatGroups[i] = matgroup; byte matID = m_File.Read8(matlist + i); byte polyID = m_File.Read8(polylist + i); uint mchunkoffset = (uint)(m_MatChunksOffset + (matID * 48)); matgroup.m_ID = matID; matgroup.m_Name = m_File.ReadString(m_File.Read32(mchunkoffset), 0); uint texid = m_File.Read32(mchunkoffset + 0x04); uint palid = m_File.Read32(mchunkoffset + 0x08); matgroup.m_TexParams = m_File.Read32(mchunkoffset + 0x20); matgroup.m_PolyAttribs = m_File.Read32(mchunkoffset + 0x24); matgroup.m_DifAmbColors = m_File.Read32(mchunkoffset + 0x28); matgroup.m_SpeEmiColors = m_File.Read32(mchunkoffset + 0x2C); if ((matgroup.m_PolyAttribs & 0x30) == 0x10) { matgroup.m_TexEnvMode = TextureEnvMode.Decal; } else { matgroup.m_TexEnvMode = TextureEnvMode.Modulate; } switch (matgroup.m_PolyAttribs & 0xC0) { case 0x00: matgroup.m_CullMode = CullFaceMode.FrontAndBack; break; case 0x40: matgroup.m_CullMode = CullFaceMode.Front; break; case 0x80: matgroup.m_CullMode = CullFaceMode.Back; break; } matgroup.m_DiffuseColor = Helper.BGR15ToColor((ushort)matgroup.m_DifAmbColors); matgroup.m_AmbientColor = Helper.BGR15ToColor((ushort)(matgroup.m_DifAmbColors >> 16)); matgroup.m_SpecularColor = Helper.BGR15ToColor((ushort)matgroup.m_SpeEmiColors); matgroup.m_EmissionColor = Helper.BGR15ToColor((ushort)(matgroup.m_SpeEmiColors >> 16)); switch (matgroup.m_TexParams >> 30) { case 0: matgroup.m_TexCoordScale = new Vector2(1.0f, 1.0f); matgroup.m_TexCoordRot = 0.0f; matgroup.m_TexCoordTrans = new Vector2(0.0f, 0.0f); break; case 1: { int sscale = (int)m_File.Read32(mchunkoffset + 0x0C); int tscale = (int)m_File.Read32(mchunkoffset + 0x10); short trot = (short)m_File.Read16(mchunkoffset + 0x14); int strans = (int)m_File.Read32(mchunkoffset + 0x18); int ttrans = (int)m_File.Read32(mchunkoffset + 0x1C); matgroup.m_TexCoordScale = new Vector2((float)sscale / 4096.0f, (float)tscale / 4096.0f); matgroup.m_TexCoordRot = ((float)trot * (float)Math.PI) / 2048.0f; matgroup.m_TexCoordTrans = new Vector2((float)strans / 4096.0f, (float)ttrans / 4096.0f); } break; case 2: goto case 1; case 3: goto case 1; default: break; // throw new Exception(String.Format("BMD: unsupported texture coord transform mode {0}", matgroup.m_TexParams >> 30)); } if (texid != 0xFFFFFFFF) { matgroup.m_Texture = ReadTexture(texid, palid); matgroup.m_TexParams |= matgroup.m_Texture.m_DSTexParam; } else { matgroup.m_Texture = null; } uint pchunkoffset = m_File.Read32((uint)(m_PolyChunksOffset + (polyID * 8) + 4)); uint dloffset = m_File.Read32(pchunkoffset + 0x0C); uint dlsize = m_File.Read32(pchunkoffset + 0x08); uint numbones = m_File.Read32(pchunkoffset); uint bonesoffset = m_File.Read32(pchunkoffset + 0x04); matgroup.m_BoneIDs = new ushort[numbones]; for (uint b = 0; b < numbones; b++) { byte idx1 = m_File.Read8(bonesoffset + b); matgroup.m_BoneIDs[b] = m_File.Read16((uint)(m_BoneMapOffset + (2 * idx1))); } matgroup.m_Geometry = new List <VertexList>(); m_CurVertex.m_Position = new Vector3(0, 0, 0); m_CurVertex.m_TexCoord = null; m_CurVertex.m_Normal = null; if ((matgroup.m_PolyAttribs & 0x8000) != 0x8000) { byte alpha = (byte)((matgroup.m_PolyAttribs >> 16) & 0x1F); alpha |= (byte)(alpha >> 5); matgroup.m_Alpha = alpha; } if ((matgroup.m_DifAmbColors & 0x8000) == 0x8000) { m_CurVertex.m_Color = Color.FromArgb(matgroup.m_Alpha << 3, matgroup.m_DiffuseColor); } else { m_CurVertex.m_Color = Color.Black; } m_CurVertex.m_MatrixID = 0; uint dlend = dloffset + dlsize; for (uint pos = dloffset; pos < dlend;) { byte cmd1 = m_File.Read8(pos++); byte cmd2 = m_File.Read8(pos++); byte cmd3 = m_File.Read8(pos++); byte cmd4 = m_File.Read8(pos++); ProcessGXCommand(matgroup, cmd1, ref pos); ProcessGXCommand(matgroup, cmd2, ref pos); ProcessGXCommand(matgroup, cmd3, ref pos); ProcessGXCommand(matgroup, cmd4, ref pos); } } } foreach (ModelChunk mdchunk in m_ModelChunks) { foreach (MaterialGroup matgroup in mdchunk.m_MatGroups) { matgroup.m_BoneMatrices = new Matrix4[matgroup.m_BoneIDs.Length]; for (uint b = 0; b < matgroup.m_BoneIDs.Length; b++) { matgroup.m_BoneMatrices[b] = m_ModelChunks[matgroup.m_BoneIDs[b]].m_Transform; } } } int index = 0; foreach (KeyValuePair <string, uint> entry in m_TextureIDs) { if (!m_Textures.ContainsKey(entry.Key)) { Console.WriteLine("NOT IN TEXTURES: " + entry.Key); uint palID = Math.Min(m_PaletteIDs.ElementAt(index).Value, (uint)m_PaletteIDs.Count - 1); ReadTexture(entry.Value, palID); } index++; } }
public static SceneContainer ReadFrom(Stream stream) { var container = new SceneContainer(); using (var r = new BinaryReader(stream)) { container.Header.Deserialize(stream); // CoreLib::Scene::CSceneGroup var chunkCount = r.ReadUInt32(); if (container.Header.Unk2 >= 0.2000000029802322f) { r.ReadByte(); // ToDo ReadString } for (var i = 0; i < chunkCount; i++) { var type = r.ReadEnum <ChunkType>(); var name = r.ReadCString(); var subName = r.ReadCString(); SceneChunk chunk; switch (type) { case ChunkType.ModelData: chunk = new ModelChunk(container) { Name = name, SubName = subName }; chunk.Deserialize(stream); container.Add(chunk); break; case ChunkType.Box: chunk = new BoxChunk(container) { Name = name, SubName = subName }; chunk.Deserialize(stream); container.Add(chunk); break; case ChunkType.Bone: chunk = new BoneChunk(container) { Name = name, SubName = subName }; chunk.Deserialize(stream); container.Add(chunk); break; case ChunkType.BoneSystem: chunk = new BoneSystemChunk(container) { Name = name, SubName = subName }; chunk.Deserialize(stream); container.Add(chunk); break; case ChunkType.Shape: chunk = new ShapeChunk(container) { Name = name, SubName = subName }; chunk.Deserialize(stream); container.Add(chunk); break; case ChunkType.SkyDirect1: chunk = new SkyDirect1Chunk(container) { Name = name, SubName = subName }; chunk.Deserialize(stream); container.Add(chunk); break; default: throw new Exception($"Unknown chunk type: 0x{(int)type:X4} StreamPosition: {r.BaseStream.Position}"); } } } return(container); }
public BMD(NitroFile file) { m_File = file; m_FileName = file.m_Name; /* if (m_File.m_ID == 741) lolol = true; else*/ lolol = false; // Keep a list of pointers so it's easier to add/remove entries, space etc. m_PointerList = new List<PointerReference>(); m_ScaleFactor = (float)(1 << (int)m_File.Read32(0x0)); // ModelChunk refers to Bone m_NumModelChunks = m_File.Read32(0x04); m_ModelChunksOffset = m_File.Read32(0x08); AddPointer(0x08); for (int i = 0; i < m_NumModelChunks; i++) { AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x04)); AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x34)); AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x38)); } // PolyChunk refers to Display List m_NumPolyChunks = m_File.Read32(0x0C); m_PolyChunksOffset = m_File.Read32(0x10); AddPointer(0x10); for (int i = 0; i < m_NumPolyChunks; i++) { // Offset to Display List within Display List entries AddPointer((uint)(m_PolyChunksOffset + (i * 8) + 4)); // Offsets within the Display List 16 byte headers AddPointer(m_File.Read32((uint)(m_PolyChunksOffset + (i * 8) + 4)) + 0x04); AddPointer(m_File.Read32((uint)(m_PolyChunksOffset + (i * 8) + 4)) + 0x0C); } m_NumTexChunks = m_File.Read32(0x14); m_TexChunksOffset = m_File.Read32(0x18); m_TextureIDs = new Dictionary<string, uint>(); AddPointer(0x18); for (int i = 0; i < m_NumTexChunks; i++) { AddPointer((uint)(m_TexChunksOffset + (i * 20) + 0)); AddPointer((uint)(m_TexChunksOffset + (i * 20) + 4)); m_TextureIDs.Add(m_File.ReadString(m_File.Read32((uint)(m_TexChunksOffset + (20 * i))), 0), (uint)i); } m_NumPalChunks = m_File.Read32(0x1C); m_PalChunksOffset = m_File.Read32(0x20); m_PaletteIDs = new Dictionary<string, uint>(); AddPointer(0x20); for (int i = 0; i < m_NumPalChunks; i++) { AddPointer((uint)(m_PalChunksOffset + (i * 16) + 0)); AddPointer((uint)(m_PalChunksOffset + (i * 16) + 4)); m_PaletteIDs.Add(m_File.ReadString(m_File.Read32((uint)(m_PalChunksOffset + (16 * i))), 0), (uint)i); } m_NumMatChunks = m_File.Read32(0x24); m_MatChunksOffset = m_File.Read32(0x28); AddPointer(0x28); for (int i = 0; i < m_NumMatChunks; i++) { AddPointer((uint)(m_MatChunksOffset + (i * 48) + 0)); } m_BoneMapOffset = m_File.Read32(0x2C); AddPointer(0x2C); m_Textures = new Dictionary<string, Texture>(); m_ModelChunks = new ModelChunk[m_NumModelChunks]; for (uint c = 0; c < m_NumModelChunks; c++) { ModelChunk mdchunk = new ModelChunk(this); m_ModelChunks[c] = mdchunk; uint mdchunkoffset = m_ModelChunksOffset + (c * 64); mdchunk.m_ID = m_File.Read32(mdchunkoffset); mdchunk.m_Name = m_File.ReadString(m_File.Read32(mdchunkoffset + 0x04), 0); // transforms part { int xscale = (int)m_File.Read32(mdchunkoffset + 0x10); int yscale = (int)m_File.Read32(mdchunkoffset + 0x14); int zscale = (int)m_File.Read32(mdchunkoffset + 0x18); short xrot = (short)m_File.Read16(mdchunkoffset + 0x1C); short yrot = (short)m_File.Read16(mdchunkoffset + 0x1E); short zrot = (short)m_File.Read16(mdchunkoffset + 0x20); int xtrans = (int)m_File.Read32(mdchunkoffset + 0x24); int ytrans = (int)m_File.Read32(mdchunkoffset + 0x28); int ztrans = (int)m_File.Read32(mdchunkoffset + 0x2C); mdchunk.m_Scale = new Vector3((float)xscale / 4096.0f, (float)yscale / 4096.0f, (float)zscale / 4096.0f); mdchunk.m_Rotation = new Vector3(((float)xrot * (float)Math.PI) / 2048.0f, ((float)yrot * (float)Math.PI) / 2048.0f, ((float)zrot * (float)Math.PI) / 2048.0f); mdchunk.m_Translation = new Vector3((float)xtrans / 4096.0f, (float)ytrans / 4096.0f, (float)ztrans / 4096.0f); mdchunk.m_Transform = Helper.SRTToMatrix(mdchunk.m_Scale, mdchunk.m_Rotation, mdchunk.m_Translation); // Used when exporting bones mdchunk.m_20_12Scale = new uint[] { (uint)xscale, (uint)yscale, (uint)zscale }; mdchunk.m_4_12Rotation = new ushort[] { (ushort)xrot, (ushort)yrot, (ushort)zrot }; mdchunk.m_20_12Translation = new uint[] { (uint)xtrans, (uint)ytrans, (uint)ztrans }; // if the chunk has a parent, apply the parent's transform to the chunk's transform. // we don't need to go further than one level because the paren't transform already // went through its parents' transforms. short parent_offset = (short)m_File.Read16(mdchunkoffset + 0x8); if (parent_offset < 0) { int parentchunkid = (int)(c + parent_offset); Matrix4.Mult(ref mdchunk.m_Transform, ref m_ModelChunks[parentchunkid].m_Transform, out mdchunk.m_Transform); } mdchunk.m_ParentOffset = parent_offset; } // If 0x0A is set to 1 the bone has children, if 0 it doesn't mdchunk.m_HasChildren = (m_File.Read16(mdchunkoffset + 0x0A) == 1); mdchunk.m_SiblingOffset = (short)(m_File.Read16(mdchunkoffset + 0x0C)); uint flags = m_File.Read32(mdchunkoffset + 0x3C); mdchunk.m_Billboard = ((flags & 0x1) == 0x1); uint numpairs = m_File.Read32(mdchunkoffset + 0x30); uint matlist = m_File.Read32(mdchunkoffset + 0x34); uint polylist = m_File.Read32(mdchunkoffset + 0x38); mdchunk.m_MatGroups = new MaterialGroup[numpairs]; for (uint i = 0; i < numpairs; i++) { MaterialGroup matgroup = new MaterialGroup(); mdchunk.m_MatGroups[i] = matgroup; byte matID = m_File.Read8(matlist + i); byte polyID = m_File.Read8(polylist + i); uint mchunkoffset = (uint)(m_MatChunksOffset + (matID * 48)); matgroup.m_ID = matID; matgroup.m_Name = m_File.ReadString(m_File.Read32(mchunkoffset), 0); uint texid = m_File.Read32(mchunkoffset + 0x04); uint palid = m_File.Read32(mchunkoffset + 0x08); matgroup.m_TexParams = m_File.Read32(mchunkoffset + 0x20); matgroup.m_PolyAttribs = m_File.Read32(mchunkoffset + 0x24); matgroup.m_DifAmbColors = m_File.Read32(mchunkoffset + 0x28); matgroup.m_SpeEmiColors = m_File.Read32(mchunkoffset + 0x2C); if ((matgroup.m_PolyAttribs & 0x30) == 0x10) matgroup.m_TexEnvMode = TextureEnvMode.Decal; else matgroup.m_TexEnvMode = TextureEnvMode.Modulate; switch (matgroup.m_PolyAttribs & 0xC0) { case 0x00: matgroup.m_CullMode = CullFaceMode.FrontAndBack; break; case 0x40: matgroup.m_CullMode = CullFaceMode.Front; break; case 0x80: matgroup.m_CullMode = CullFaceMode.Back; break; } matgroup.m_DiffuseColor = Helper.BGR15ToColor((ushort)matgroup.m_DifAmbColors); matgroup.m_AmbientColor = Helper.BGR15ToColor((ushort)(matgroup.m_DifAmbColors >> 16)); matgroup.m_SpecularColor = Helper.BGR15ToColor((ushort)matgroup.m_SpeEmiColors); matgroup.m_EmissionColor = Helper.BGR15ToColor((ushort)(matgroup.m_SpeEmiColors >> 16)); switch (matgroup.m_TexParams >> 30) { case 0: matgroup.m_TexCoordScale = new Vector2(1.0f, 1.0f); matgroup.m_TexCoordTrans = new Vector2(0.0f, 0.0f); break; case 1: { int sscale = (int)m_File.Read32(mchunkoffset + 0x0C); int tscale = (int)m_File.Read32(mchunkoffset + 0x10); int strans = (int)m_File.Read32(mchunkoffset + 0x18); int ttrans = (int)m_File.Read32(mchunkoffset + 0x1C); matgroup.m_TexCoordScale = new Vector2((float)sscale / 4096.0f, (float)tscale / 4096.0f); matgroup.m_TexCoordTrans = new Vector2((float)strans / 4096.0f, (float)ttrans / 4096.0f); //matgroup.m_TexCoordTrans = new Vector2(0.0f, 16.0f); /*System.Windows.Forms.MessageBox.Show(String.Format("textransform: scale:{0} trans:{1} rot:{2:X8}", matgroup.m_TexCoordScale, matgroup.m_TexCoordTrans, m_File.Read32(mchunkoffset + 0x1C)));*/ } break; case 2: goto case 1; case 3: goto case 1; default: break; // throw new Exception(String.Format("BMD: unsupported texture coord transform mode {0}", matgroup.m_TexParams >> 30)); } if (texid != 0xFFFFFFFF) { matgroup.m_Texture = ReadTexture(texid, palid); matgroup.m_TexParams |= matgroup.m_Texture.m_Params; } else matgroup.m_Texture = null; uint pchunkoffset = m_File.Read32((uint)(m_PolyChunksOffset + (polyID * 8) + 4)); uint dloffset = m_File.Read32(pchunkoffset + 0x0C); uint dlsize = m_File.Read32(pchunkoffset + 0x08); uint numbones = m_File.Read32(pchunkoffset); uint bonesoffset = m_File.Read32(pchunkoffset + 0x04); matgroup.m_BoneIDs = new ushort[numbones]; for (uint b = 0; b < numbones; b++) { byte idx1 = m_File.Read8(bonesoffset + b); matgroup.m_BoneIDs[b] = m_File.Read16((uint)(m_BoneMapOffset + (2 * idx1))); } matgroup.m_Geometry = new List<VertexList>(); m_CurVertex.m_Position = new Vector3(0, 0, 0); m_CurVertex.m_TexCoord = new Vector2(0, 0); if ((matgroup.m_DifAmbColors & 0x8000) == 0x8000) { byte alpha = (byte)((matgroup.m_PolyAttribs >> 13) & 0xF8); alpha |= (byte)(alpha >> 5); matgroup.m_Alpha = alpha; m_CurVertex.m_Color = Color.FromArgb(alpha, matgroup.m_DiffuseColor); } else m_CurVertex.m_Color = Color.Black; m_CurVertex.m_MatrixID = 0; uint dlend = dloffset + dlsize; for (uint pos = dloffset; pos < dlend; ) { byte cmd1 = m_File.Read8(pos++); byte cmd2 = m_File.Read8(pos++); byte cmd3 = m_File.Read8(pos++); byte cmd4 = m_File.Read8(pos++); ProcessGXCommand(matgroup, cmd1, ref pos); ProcessGXCommand(matgroup, cmd2, ref pos); ProcessGXCommand(matgroup, cmd3, ref pos); ProcessGXCommand(matgroup, cmd4, ref pos); } } } foreach (ModelChunk mdchunk in m_ModelChunks) { foreach (MaterialGroup matgroup in mdchunk.m_MatGroups) { matgroup.m_BoneMatrices = new Matrix4[matgroup.m_BoneIDs.Length]; for (uint b = 0; b < matgroup.m_BoneIDs.Length; b++) matgroup.m_BoneMatrices[b] = m_ModelChunks[matgroup.m_BoneIDs[b]].m_Transform; } } }
private bool f_import_scene() { if (container == null) { return(false); } var file = new OpenFileDialog(); file.Multiselect = true; file.Filter = ".scn_part|*.scn_part"; if (file.ShowDialog() == DialogResult.OK) { for (int i = 0; i < file.FileNames.Length; i++) { using (var fs = new FileStream(file.FileName, FileMode.Open, FileAccess.Read, FileShare.None)) using (var br = new BinaryReader(fs)) { SceneChunk chunk = null; var type = br.ReadEnum <ChunkType>(); string name = br.ReadCString(); string subname = br.ReadCString(); switch (type) { case ChunkType.Bone: chunk = new BoneChunk(container) { Name = name, SubName = subname, Image = Properties.Resources.bone }; chunk.Deserialize(fs); container.Add(chunk); break; case ChunkType.BoneSystem: chunk = new BoneSystemChunk(container) { Name = name, SubName = subname, Image = Properties.Resources.bone_system }; chunk.Deserialize(fs); container.Add(chunk); break; case ChunkType.Box: chunk = new BoxChunk(container) { Name = name, SubName = subname, Image = Properties.Resources.box }; chunk.Deserialize(fs); container.Add(chunk); break; case ChunkType.ModelData: chunk = new ModelChunk(container) { Name = name, SubName = subname, Image = Properties.Resources.model }; chunk.Deserialize(fs); container.Add(chunk); break; case ChunkType.Shape: chunk = new ShapeChunk(container) { Name = name, SubName = subname, Image = Properties.Resources.shape }; chunk.Deserialize(fs); container.Add(chunk); break; case ChunkType.SkyDirect1: chunk = new SkyDirect1Chunk(container) { Name = name, SubName = subname, Image = Properties.Resources.sky }; chunk.Deserialize(fs); container.Add(chunk); break; default: return(false); } } } return(true); } return(false); }
public bool parseModel(ModelChunk m, LuaObject data) { parseChunkHeader(m, data); String pt = data.get <String>("primativeType"); switch (pt) { case "TRI": m.primativeType = PrimitiveType.Triangles; break; case "TRISTRIP": m.primativeType = PrimitiveType.TriangleStrip; break; } String vf = data.get <String>("vertexFormat"); switch (vf) { case "V3N3T2": m.vertexFormat = ModelChunk.VertexFormat.V3N3T2; break; case "V3N3T2B4W4": m.vertexFormat = ModelChunk.VertexFormat.V3N3T2B4W4; break; } String iff = data.get <String>("indexFormat"); switch (iff) { case "UInt16": m.indexType = ModelChunk.IndexFormat.USHORT; break; case "UInt32": m.indexType = ModelChunk.IndexFormat.UINT; break; } m.vertexCount = data.get <UInt32>("vertexCount"); m.indexCount = data.get <UInt32>("indexCount"); LuaObject meshData = data.get <LuaObject>("meshes"); for (int i = 1; i <= meshData.count(); i++) { Mesh mesh = new Mesh(); if (parseMesh(mesh, meshData[i]) == true) { m.myMeshes.Add(mesh); } } LuaObject materialData = data.get <LuaObject>("materials"); for (int i = 1; i <= materialData.count(); i++) { Material material = new Material(); if (parseMaterial(material, materialData[i]) == true) { m.myMaterials.Add(material); } } LuaObject vertData = data.get <LuaObject>("verts"); switch (m.vertexFormat) { case ModelChunk.VertexFormat.V3N3T2: { m.verts = new List <Vector3>(); m.normals = new List <Vector3>(); m.uvs = new List <Vector2>(); int i = 1; for (int vert = 0; vert < m.vertexCount; vert++) { m.verts.Add(new Vector3(vertData[i++], vertData[i++], vertData[i++])); m.normals.Add(new Vector3(vertData[i++], vertData[i++], vertData[i++])); m.uvs.Add(new Vector2(vertData[i++], vertData[i++])); } break; } case ModelChunk.VertexFormat.V3N3T2B4W4: { m.verts = new List <Vector3>(); m.normals = new List <Vector3>(); m.uvs = new List <Vector2>(); m.boneIdx = new List <Vector4>(); m.boneWeights = new List <Vector4>(); int i = 1; for (int vert = 0; vert < m.vertexCount; vert++) { m.verts.Add(new Vector3(vertData[i++], vertData[i++], vertData[i++])); m.normals.Add(new Vector3(vertData[i++], vertData[i++], vertData[i++])); m.uvs.Add(new Vector2(vertData[i++], vertData[i++])); m.boneIdx.Add(new Vector4(vertData[i++], vertData[i++], vertData[i++], vertData[i++])); m.boneWeights.Add(new Vector4(vertData[i++], vertData[i++], vertData[i++], vertData[i++])); } break; } } LuaObject indexData = data.get <LuaObject>("indexes"); switch (m.indexType) { case ModelChunk.IndexFormat.USHORT: { m.indexShort = new List <UInt16>(); int i = 1; for (int idx = 0; idx < m.indexCount; idx++) { m.indexShort.Add((UInt16)((float)indexData[i++])); } break; } case ModelChunk.IndexFormat.UINT: { m.indexInt = new List <UInt32>(); int i = 1; for (int idx = 0; idx < m.indexCount; idx++) { m.indexInt.Add((UInt32)((float)indexData[i++])); } break; } } return(true); }