public void Load(System.IO.Stream stream) { CanSave = false; Renderer = new CMB_Renderer(); DrawableContainer.Drawables.Add(Renderer); Skeleton = new STSkeleton(); //These models/skeletons come out massive so scale them with an overridden scale Skeleton.PreviewScale = Renderer.PreviewScale; Skeleton.BonePointScale = 40; Renderer.Skeleton = Skeleton; DrawableContainer.Drawables.Add(Skeleton); cmb.ReadCMB(stream); Text = cmb.Header.Name; DrawableContainer.Name = Text; //Load textures if (cmb.TexturesChunk != null) { texFolder = new TextureFolder("Texture"); TreeNode meshFolder = new TreeNode("Meshes"); TreeNode materialFolder = new TreeNode("Materials"); TreeNode skeletonFolder = new TreeNode("Skeleton"); bool HasTextures = cmb.TexturesChunk.Textures != null && cmb.TexturesChunk.Textures.Count != 0; bool HasMeshes = cmb.MeshesChunk.SHP.SEPDs != null && cmb.MeshesChunk.SHP.SEPDs.Count != 0; bool HasSkeleton = cmb.SkeletonChunk != null && cmb.SkeletonChunk.Bones.Count != 0; bool HasMaterials = cmb.MaterialsChunk != null && cmb.MaterialsChunk.Materials.Count != 0; if (HasSkeleton) { var bonesOrdered = cmb.SkeletonChunk.Bones.OrderBy(x => x.ID).ToList(); foreach (var bone in bonesOrdered) { STBone genericBone = new STBone(Skeleton); genericBone.parentIndex = bone.ParentID; genericBone.Checked = true; genericBone.Text = $"Bone {bone.ID}"; genericBone.RotationType = STBone.BoneRotationType.Euler; genericBone.Position = new OpenTK.Vector3( bone.Translation.X, bone.Translation.Y, bone.Translation.Z ); genericBone.EulerRotation = new OpenTK.Vector3( bone.Rotation.X, bone.Rotation.Y, bone.Rotation.Z ); genericBone.Scale = new OpenTK.Vector3( bone.Scale.X, bone.Scale.Y, bone.Scale.Z ); Skeleton.bones.Add(genericBone); } foreach (var bone in Skeleton.bones) { if (bone.Parent == null) { skeletonFolder.Nodes.Add(bone); } } Skeleton.reset(); Skeleton.update(); } if (HasTextures) { int texIndex = 0; foreach (var tex in cmb.TexturesChunk.Textures) { var texWrapper = new CTXB.TextureWrapper(new CTXB.Texture()); texWrapper.Text = $"Texture {texIndex++}"; texWrapper.ImageKey = "texture"; texWrapper.SelectedImageKey = texWrapper.ImageKey; if (tex.Name != string.Empty) { texWrapper.Text = tex.Name; } texWrapper.Width = tex.Width; texWrapper.Height = tex.Height; CTXB.Texture.TextureFormat Format = (CTXB.Texture.TextureFormat)((tex.DataType << 16) | tex.ImageFormat); texWrapper.Format = CTR_3DS.ConvertPICAToGenericFormat(CTXB.Texture.FormatList[Format]); texWrapper.ImageData = tex.ImageData; texFolder.Nodes.Add(texWrapper); Renderer.TextureList.Add(texWrapper); } } if (HasMaterials) { int materialIndex = 0; foreach (var mat in cmb.MaterialsChunk.Materials) { H3DMaterial H3D = ToH3DMaterial(mat); CMBMaterialWrapper material = new CMBMaterialWrapper(mat, this, H3D); material.Text = $"Material {materialIndex++}"; materialFolder.Nodes.Add(material); Materials.Add(material); bool HasDiffuse = false; foreach (var tex in mat.TextureMappers) { if (tex.TextureID != -1) { CMBTextureMapWrapper matTexture = new CMBTextureMapWrapper(tex, this); matTexture.TextureIndex = tex.TextureID; material.TextureMaps.Add(matTexture); if (tex.TextureID < Renderer.TextureList.Count && tex.TextureID >= 0) { matTexture.Name = Renderer.TextureList[tex.TextureID].Text; material.Nodes.Add(matTexture.Name); } if (!HasDiffuse && matTexture.Name != "bg_syadowmap") //Quick hack till i do texture env stuff { matTexture.Type = STGenericMatTexture.TextureType.Diffuse; HasDiffuse = true; } } } } } if (HasMeshes) { int MeshIndex = 0; foreach (var mesh in cmb.MeshesChunk.MSHS.Meshes) { STGenericMaterial mat = Materials[mesh.MaterialIndex]; CmbMeshWrapper genericMesh = new CmbMeshWrapper(mat); genericMesh.Text = $"Mesh_{MeshIndex++}_ID_{mesh.VisIndex}"; genericMesh.MaterialIndex = mesh.MaterialIndex; var shape = cmb.MeshesChunk.SHP.SEPDs[mesh.SEPDIndex]; genericMesh.Mesh = shape; List <ushort> SkinnedBoneTable = new List <ushort>(); foreach (var prim in shape.PRMS) { if (prim.BoneIndices != null) { SkinnedBoneTable.AddRange(prim.BoneIndices); } } //Now load the vertex and face data foreach (var prm in shape.PRMS) { if (shape.HasPosition) { int VertexCount = prm.VertexCount; for (int v = 0; v < VertexCount; v++) { Vertex vert = new Vertex(); vert.pos = new OpenTK.Vector3( prm.Vertices.Position[v].X, prm.Vertices.Position[v].Y, prm.Vertices.Position[v].Z); if (shape.HasNormal) { vert.nrm = new OpenTK.Vector3( prm.Vertices.Normal[v].X, prm.Vertices.Normal[v].Y, prm.Vertices.Normal[v].Z).Normalized(); } if (shape.HasColor) { vert.col = new OpenTK.Vector4( prm.Vertices.Color[v].X, prm.Vertices.Color[v].Y, prm.Vertices.Color[v].Z, prm.Vertices.Color[v].W).Normalized(); } if (shape.HasUV0) { vert.uv0 = new OpenTK.Vector2(prm.Vertices.UV0[v].X, -prm.Vertices.UV0[v].Y + 1); } if (shape.HasUV1) { vert.uv1 = new OpenTK.Vector2(prm.Vertices.UV1[v].X, -prm.Vertices.UV1[v].Y + 1); } if (shape.HasUV2) { vert.uv2 = new OpenTK.Vector2(prm.Vertices.UV2[v].X, -prm.Vertices.UV2[v].Y + 1); } if (prm.SkinningMode == SkinningMode.Smooth) { //Indices if (shape.HasIndices) { if (shape.BoneDimensionCount >= 1) { vert.boneIds.Add((int)prm.Vertices.BoneIndices[v].X); } if (shape.BoneDimensionCount >= 2) { vert.boneIds.Add((int)prm.Vertices.BoneIndices[v].Y); } if (shape.BoneDimensionCount >= 3) { vert.boneIds.Add((int)prm.Vertices.BoneIndices[v].Z); } if (shape.BoneDimensionCount >= 4) { vert.boneIds.Add((int)prm.Vertices.BoneIndices[v].W); } } //Weights if (shape.HasWeights) { if (shape.BoneDimensionCount >= 1) { vert.boneWeights.Add(prm.Vertices.BoneWeights[v].X); } if (shape.BoneDimensionCount >= 2) { vert.boneWeights.Add(prm.Vertices.BoneWeights[v].Y); } if (shape.BoneDimensionCount >= 3) { vert.boneWeights.Add(prm.Vertices.BoneWeights[v].Z); } if (shape.BoneDimensionCount >= 4) { vert.boneWeights.Add(prm.Vertices.BoneWeights[v].W); } } } if (prm.SkinningMode == SkinningMode.Rigid) { int boneId = (int)prm.Vertices.BoneIndices[v].X; vert.boneIds.Add(boneId); vert.boneWeights.Add(1); vert.pos = OpenTK.Vector3.TransformPosition(vert.pos, Skeleton.bones[boneId].Transform); if (shape.HasNormal) { vert.nrm = OpenTK.Vector3.TransformNormal(vert.nrm, Skeleton.bones[boneId].Transform); } } if (prm.SkinningMode == SkinningMode.Mixed) { int boneId = prm.BoneIndices[0]; vert.boneIds.Add(boneId); vert.boneWeights.Add(1); vert.pos = OpenTK.Vector3.TransformPosition(vert.pos, Skeleton.bones[boneId].Transform); if (shape.HasNormal) { vert.nrm = OpenTK.Vector3.TransformNormal(vert.nrm, Skeleton.bones[boneId].Transform); } } genericMesh.vertices.Add(vert); } } STGenericPolygonGroup group = new STGenericPolygonGroup(); genericMesh.PolygonGroups.Add(group); for (int i = 0; i < prm.FaceIndices.Count; i++) { group.faces.Add((int)prm.FaceIndices[i].X); group.faces.Add((int)prm.FaceIndices[i].Y); group.faces.Add((int)prm.FaceIndices[i].Z); } } Renderer.Meshes.Add(genericMesh); meshFolder.Nodes.Add(genericMesh); } } if (meshFolder.Nodes.Count > 0) { Nodes.Add(meshFolder); } if (skeletonFolder.Nodes.Count > 0) { Nodes.Add(skeletonFolder); } if (materialFolder.Nodes.Count > 0) { Nodes.Add(materialFolder); } if (texFolder.Nodes.Count > 0) { Nodes.Add(texFolder); } } }
public void Load(System.IO.Stream stream) { DrawableContainer.Name = FileName; Renderer = new PunchOutWii_Renderer(); DrawableContainer.Drawables.Add(Renderer); Text = FileName; HeaderFile = new DictionaryFile(); HeaderFile.Read(new FileReader(stream), FilePath); var HashList = NLG_Common.HashNames; string DataFile = $"{FilePath.Replace(".dict", ".data")}"; if (System.IO.File.Exists(DataFile)) { using (var reader = new FileReader(DataFile, true)) { reader.SetByteOrder(true); TreeNode blocks = new TreeNode("Blocks"); TreeNode chunks = new TreeNode("Chunks"); TreeNode modelFolder = new TreeNode("Models"); foreach (var blockInfo in HeaderFile.Blocks) { ChunkViewer chunkNode = new ChunkViewer("block"); if (blockInfo.Size > 0) { blocks.Nodes.Add(chunkNode); } chunkNode.FileData = new SubStream(reader.BaseStream, blockInfo.Offset, blockInfo.Size); } List <PO_Texture> currentTextures = new List <PO_Texture>(); List <ModelFileData> modelData = new List <ModelFileData>(); ModelFileData currentModel = null; STTextureFolder textureFolder = new STTextureFolder("Textures"); Nodes.Add(blocks); Nodes.Add(chunks); Nodes.Add(textureFolder); Nodes.Add(modelFolder); foreach (var chunk in HeaderFile.DataChunks) { if (chunk.BlockIndex == -1) { continue; } ChunkViewer chunkNode = new ChunkViewer(chunk.Type.ToString("") + " " + chunk.Type.ToString("X")); chunks.Nodes.Add(chunkNode); var blockInfo = HeaderFile.Blocks[chunk.BlockIndex]; if (blockInfo.Offset + chunk.Offset + chunk.Size > reader.BaseStream.Length) { continue; } chunkNode.FileData = new SubStream(reader.BaseStream, blockInfo.Offset + chunk.Offset, chunk.Size); uint chunkPos = blockInfo.Offset + chunk.Offset; reader.SeekBegin(chunkPos); switch (chunk.Type) { case SectionMagic.MaterialData: currentModel = new ModelFileData(); currentModel.MaterialOffset = chunkPos; modelData.Add(currentModel); break; case SectionMagic.TextureHeaders: uint numTextures = chunk.Size / 96; for (int i = 0; i < numTextures; i++) { var tex = new PO_Texture(); tex.ImageKey = "texture"; tex.SelectedImageKey = "texture"; tex.Read(reader); tex.Text = tex.HashID.ToString("X"); if (HashList.ContainsKey(tex.HashID)) { tex.Text = HashList[tex.HashID]; } currentTextures.Add(tex); Renderer.TextureList.Add(tex.Text, tex); textureFolder.Nodes.Add(tex); } break; case SectionMagic.TextureData: for (int i = 0; i < currentTextures.Count; i++) { reader.SeekBegin(chunkPos + currentTextures[i].DataOffset); currentTextures[i].ImageData = reader.ReadBytes((int)currentTextures[i].ImageSize); } break; case SectionMagic.IndexData: currentModel.indexBufferOffset = chunkPos; break; case SectionMagic.VertexData: currentModel.vertexBufferOffset = chunkPos; break; case SectionMagic.MeshData: uint numMeshes = chunk.Size / 52; for (int i = 0; i < numMeshes; i++) { reader.SeekBegin(chunkPos + (i * 52)); PO_Mesh mesh = new PO_Mesh(reader); currentModel.meshes.Add(mesh); } break; case SectionMagic.VertexAttributePointerData: uint numAttributes = chunk.Size / 8; for (int i = 0; i < numAttributes; i++) { PO_VertexAttribute att = new PO_VertexAttribute(); att.Offset = reader.ReadUInt32(); att.Type = reader.ReadByte(); att.Stride = reader.ReadByte(); reader.ReadUInt16(); currentModel.attributes.Add(att); } break; case SectionMagic.ModelData: uint numModels = chunk.Size / 12; Console.WriteLine($"numModels {numModels}"); for (int i = 0; i < numModels; i++) { PO_Model mdl = new PO_Model(); mdl.ParentDictionary = this; mdl.HashID = reader.ReadUInt32(); mdl.NumMeshes = reader.ReadUInt32(); reader.ReadUInt32(); //0 currentModel.models.Add(mdl); } break; case SectionMagic.BoneData: STSkeleton Skeleton = new STSkeleton(); DrawableContainer.Drawables.Add(Skeleton); uint numBones = chunk.Size / 68; for (int i = 0; i < numBones; i++) { reader.SeekBegin(chunkPos + (i * 68)); uint HashID = reader.ReadUInt32(); reader.ReadUInt32(); //unk reader.ReadUInt32(); //unk reader.ReadUInt32(); //unk reader.ReadSingle(); //0 STBone bone = new STBone(Skeleton); var Scale = new OpenTK.Vector3( reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); reader.ReadSingle(); //0 bone.EulerRotation = new OpenTK.Vector3( reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); reader.ReadSingle(); //0 bone.Position = new OpenTK.Vector3( reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); reader.ReadSingle(); //1 bone.Text = HashID.ToString("X"); if (NLG_Common.HashNames.ContainsKey(HashID)) { bone.Text = NLG_Common.HashNames[HashID]; } else { Console.WriteLine($"bone hash {HashID}"); } bone.Scale = new Vector3(0.2f, 0.2f, 0.2f); bone.RotationType = STBone.BoneRotationType.Euler; Skeleton.bones.Add(bone); } Skeleton.reset(); Skeleton.update(); break; } } foreach (var modelFile in modelData) { int pointerIndex = 0; foreach (var model in modelFile.models) { model.Text = model.HashID.ToString("X"); if (HashList.ContainsKey(model.HashID)) { model.Text = HashList[model.HashID]; } modelFolder.Nodes.Add(model); for (int i = 0; i < model.NumMeshes; i++) { var mesh = modelFile.meshes[i]; RenderableMeshWrapper genericMesh = new RenderableMeshWrapper(); model.Nodes.Add(genericMesh); model.RenderedMeshes.Add(genericMesh); Renderer.Meshes.Add(genericMesh); genericMesh.Text = mesh.HashID.ToString("X"); if (HashList.ContainsKey(mesh.HashID)) { genericMesh.Text = HashList[mesh.HashID]; } string material = mesh.MaterialHashID.ToString("X"); if (HashList.ContainsKey(mesh.MaterialHashID)) { material = HashList[mesh.MaterialHashID]; } genericMesh.Nodes.Add(material); genericMesh.Material = new STGenericMaterial(); reader.SeekBegin(modelFile.MaterialOffset + mesh.MaterialOffset); switch (mesh.MaterailPreset) { case MaterailPresets.EnvDiffuseDamage: { uint diffuseMapHashID = reader.ReadUInt32(); uint diffuseMapParam = reader.ReadUInt32(); uint envSpecMapHashID = reader.ReadUInt32(); uint envSpecMapParam = reader.ReadUInt32(); uint specMapHashID = reader.ReadUInt32(); uint specMapParam = reader.ReadUInt32(); uint megaStrikeMapHashID = reader.ReadUInt32(); uint megaStrikeMapParam = reader.ReadUInt32(); uint dirtMapHashID = reader.ReadUInt32(); uint dirtMapParam = reader.ReadUInt32(); uint iceMapHashID = reader.ReadUInt32(); uint iceMapParam = reader.ReadUInt32(); string diffuseName = diffuseMapHashID.ToString("X"); if (HashList.ContainsKey(diffuseMapHashID)) { diffuseName = HashList[diffuseMapHashID]; } var texUnit = 1; genericMesh.Material.TextureMaps.Add(new STGenericMatTexture() { textureUnit = texUnit++, Type = STGenericMatTexture.TextureType.Diffuse, Name = diffuseName, }); } break; default: { uint diffuseMapHashID = reader.ReadUInt32(); string diffuseName = diffuseMapHashID.ToString("X"); if (HashList.ContainsKey(diffuseMapHashID)) { diffuseName = HashList[diffuseMapHashID]; } Console.WriteLine($"diffuseName {diffuseName}"); var texUnit = 1; genericMesh.Material.TextureMaps.Add(new STGenericMatTexture() { textureUnit = texUnit++, Type = STGenericMatTexture.TextureType.Diffuse, Name = diffuseName, }); } break; } Console.WriteLine($"mesh {i}"); STGenericPolygonGroup polyGroup = new STGenericPolygonGroup(); genericMesh.PolygonGroups.Add(polyGroup); reader.SeekBegin(modelFile.indexBufferOffset + mesh.IndexStartOffset); List <int> faces = new List <int>(); for (int f = 0; f < mesh.IndexCount; f++) { if (mesh.IndexFormat == 0) { polyGroup.faces.Add(reader.ReadUInt16()); } else { polyGroup.faces.Add(reader.ReadByte()); } } if (mesh.FaceType == PO_Mesh.PolygonType.TriangleStrips) { polyGroup.PrimativeType = STPrimitiveType.TrangleStrips; } else { polyGroup.PrimativeType = STPrimitiveType.Triangles; } for (int a = 0; a < mesh.NumAttributePointers; a++) { Console.WriteLine($"pointer {genericMesh.Text} { modelFile.vertexBufferOffset + modelFile.attributes[pointerIndex + a].Offset}"); } for (int v = 0; v < mesh.VertexCount; v++) { Vertex vert = new Vertex(); genericMesh.vertices.Add(vert); int attributeIndex = 0; for (int a = 0; a < mesh.NumAttributePointers; a++) { var pointer = modelFile.attributes[pointerIndex + a]; reader.SeekBegin(modelFile.vertexBufferOffset + pointer.Offset + (pointer.Stride * v)); if (attributeIndex == 0) { if (pointer.Stride == 12) { vert.pos = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } } if (attributeIndex == 1) { if (pointer.Stride == 12) { vert.nrm = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } } if (attributeIndex == 2) { if (pointer.Stride == 4) { vert.uv0 = new Vector2(reader.ReadUInt16() / 1024f, reader.ReadUInt16() / 1024f); } } /* if (pointer.Type == 0xD4) * { * vert.boneIds = new List<int>() { reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte() }; * } * if (pointer.Type == 0xB0) * { * vert.boneWeights = new List<float>() { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }; * }*/ attributeIndex++; } } genericMesh.TransformPosition(new Vector3(0), new Vector3(-90, 0, 0), new Vector3(1)); pointerIndex += mesh.NumAttributePointers; } } } } } }