diff --git a/File_Format_Library/FileFormats/Grezzo/CMB.cs b/File_Format_Library/FileFormats/Grezzo/CMB.cs index 69be053d..becd485e 100644 --- a/File_Format_Library/FileFormats/Grezzo/CMB.cs +++ b/File_Format_Library/FileFormats/Grezzo/CMB.cs @@ -1,16 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; using Toolbox.Library.Forms; using Toolbox.Library; using Toolbox.Library.IO; using Toolbox.Library.Rendering; -using Grezzo.CmbEnums; -using OpenTK.Graphics.OpenGL; using FirstPlugin.Forms; +using ZeldaLib.CtrModelBinary.Types; using SPICA.Formats.CtrH3D.Model.Material; using SPICA.PICA.Commands; @@ -29,7 +26,7 @@ namespace FirstPlugin public bool Identify(System.IO.Stream stream) { - using (var reader = new Toolbox.Library.IO.FileReader(stream, true)) + using (var reader = new FileReader(stream, true)) { return reader.CheckSignature(4, "cmb "); } @@ -105,17 +102,17 @@ namespace FirstPlugin public DrawableContainer DrawableContainer = new DrawableContainer(); List Materials = new List(); - public Header header; + public ZeldaLib.CtrModelBinary.CMB cmb = new ZeldaLib.CtrModelBinary.CMB(); STTextureFolder texFolder; public STSkeleton Skeleton; public void Load(System.IO.Stream stream) { - CanSave = true; + 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 @@ -125,40 +122,40 @@ namespace FirstPlugin DrawableContainer.Drawables.Add(Skeleton); - header = new Header(); - header.Read(new FileReader(stream)); - Text = header.Name; + cmb.ReadCMB(stream); + + Text = cmb.Header.Name; DrawableContainer.Name = Text; //Load textures - if (header.SectionData.TextureChunk != null) + 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 = header.SectionData.TextureChunk != null && - header.SectionData.TextureChunk.Textures.Count != 0; + bool HasTextures = cmb.TexturesChunk.Textures != null && + cmb.TexturesChunk.Textures.Count != 0; - bool HasMeshes = header.SectionData.SkeletalMeshChunk != null && - header.SectionData.SkeletalMeshChunk.ShapeChunk.SeperateShapes.Count != 0; + bool HasMeshes = cmb.MeshesChunk.SHP.SEPDs != null && + cmb.MeshesChunk.SHP.SEPDs.Count != 0; - bool HasSkeleton = header.SectionData.SkeletonChunk != null && - header.SectionData.SkeletonChunk.Bones.Count != 0; + bool HasSkeleton = cmb.SkeletonChunk != null && + cmb.SkeletonChunk.Bones.Count != 0; - bool HasMaterials = header.SectionData.MaterialChunk != null && - header.SectionData.MaterialChunk.Materials.Count != 0; + bool HasMaterials = cmb.MaterialsChunk != null && + cmb.MaterialsChunk.Materials.Count != 0; if (HasSkeleton) { - var bonesOrdered = header.SectionData.SkeletonChunk.Bones.OrderBy(x => x.ID).ToList(); + var bonesOrdered = cmb.SkeletonChunk.Bones.OrderBy(x => x.ID).ToList(); foreach (var bone in bonesOrdered) { STBone genericBone = new STBone(Skeleton); - genericBone.parentIndex = bone.ParentIndex; + genericBone.parentIndex = bone.ParentID; genericBone.Checked = true; genericBone.Text = $"Bone {bone.ID}"; @@ -195,9 +192,10 @@ namespace FirstPlugin if (HasTextures) { int texIndex = 0; - foreach (var tex in header.SectionData.TextureChunk.Textures) + foreach (var tex in cmb.TexturesChunk.Textures) { - var texWrapper = new CTXB.TextureWrapper(tex); + + var texWrapper = new CTXB.TextureWrapper(new CTXB.Texture()); texWrapper.Text = $"Texture {texIndex++}"; texWrapper.ImageKey = "texture"; texWrapper.SelectedImageKey = texWrapper.ImageKey; @@ -207,7 +205,9 @@ namespace FirstPlugin texWrapper.Width = tex.Width; texWrapper.Height = tex.Height; - texWrapper.Format = CTR_3DS.ConvertPICAToGenericFormat(tex.PicaFormat); + 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); @@ -218,25 +218,27 @@ namespace FirstPlugin if (HasMaterials) { int materialIndex = 0; - foreach (var mat in header.SectionData.MaterialChunk.Materials) + foreach (var mat in cmb.MaterialsChunk.Materials) { - CMBMaterialWrapper material = new CMBMaterialWrapper(mat, this); + 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.TextureMaps) + foreach (var tex in mat.TextureMappers) { - if (tex.TextureIndex != -1) + if (tex.TextureID != -1) { CMBTextureMapWrapper matTexture = new CMBTextureMapWrapper(tex, this); - matTexture.TextureIndex = tex.TextureIndex; + matTexture.TextureIndex = tex.TextureID; material.TextureMaps.Add(matTexture); - if (tex.TextureIndex < Renderer.TextureList.Count && tex.TextureIndex >= 0) + if (tex.TextureID < Renderer.TextureList.Count && tex.TextureID >= 0) { - matTexture.Name = Renderer.TextureList[tex.TextureIndex].Text; + matTexture.Name = Renderer.TextureList[tex.TextureID].Text; material.Nodes.Add(matTexture.Name); } @@ -253,128 +255,131 @@ namespace FirstPlugin if (HasMeshes) { int MeshIndex = 0; - foreach (var mesh in header.SectionData.SkeletalMeshChunk.MeshChunk.Meshes) + foreach (var mesh in cmb.MeshesChunk.MSHS.Meshes) { - STGenericMaterial mat = new STGenericMaterial(); - if (Materials.Count > mesh.MaterialIndex) //Incase materials for some reason are in a seperate file, check this - mat = Materials[mesh.MaterialIndex]; + STGenericMaterial mat = Materials[mesh.MaterialIndex]; CmbMeshWrapper genericMesh = new CmbMeshWrapper(mat); - genericMesh.Text = $"Mesh_{MeshIndex++}"; + genericMesh.Text = $"Mesh_{MeshIndex++}_ID_{mesh.VisIndex}"; genericMesh.MaterialIndex = mesh.MaterialIndex; - //Wow this is long - var shape = header.SectionData.SkeletalMeshChunk.ShapeChunk.SeperateShapes[(int)mesh.SepdIndex]; - genericMesh.Shape = shape; + var shape = cmb.MeshesChunk.SHP.SEPDs[mesh.SEPDIndex]; + genericMesh.Mesh = shape; List SkinnedBoneTable = new List(); - foreach (var prim in shape.Primatives) + foreach (var prim in shape.PRMS) { - if (prim.BoneIndexTable != null) { - SkinnedBoneTable.AddRange(prim.BoneIndexTable); - foreach (var bone in prim.BoneIndexTable) - Console.WriteLine($"{genericMesh.Text} SkeletonB {Skeleton.bones[(int)bone].Text} index {bone}"); + if (prim.BoneIndices != null) { + SkinnedBoneTable.AddRange(prim.BoneIndices); } } //Now load the vertex and face data - if (shape.Position.VertexData != null) + + foreach (var prm in shape.PRMS) { - int VertexCount = shape.Position.VertexData.Length; - for (int v = 0; v < VertexCount; v++) + if (shape.HasPosition) { - Vertex vert = new Vertex(); - vert.pos = new OpenTK.Vector3( - shape.Position.VertexData[v].X, - shape.Position.VertexData[v].Y, - shape.Position.VertexData[v].Z); - - if (shape.Normal.VertexData != null && shape.Normal.VertexData.Length > v) + int VertexCount = prm.VertexCount; + for (int v = 0; v < VertexCount; v++) { - vert.nrm = new OpenTK.Vector3( - shape.Normal.VertexData[v].X, - shape.Normal.VertexData[v].Y, - shape.Normal.VertexData[v].Z).Normalized(); - } - - if (shape.Color.VertexData != null && shape.Color.VertexData.Length > v) - { - vert.col = new OpenTK.Vector4( - shape.Color.VertexData[v].X, - shape.Color.VertexData[v].Y, - shape.Color.VertexData[v].Z, - shape.Color.VertexData[v].W).Normalized(); - } - - if (shape.TexCoord0.VertexData != null && shape.TexCoord0.VertexData.Length > v) - { - vert.uv0 = new OpenTK.Vector2( - shape.TexCoord0.VertexData[v].X, - 1 - shape.TexCoord0.VertexData[v].Y); - } - - if (shape.TexCoord1.VertexData != null) - { - - } - - if (shape.TexCoord2.VertexData != null) - { - - } - - for (int i = 0; i < 16; i++) - { - if (i < shape.Primatives[0].BoneIndexTable.Length) + 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) { - int boneId = shape.Primatives[0].BoneIndexTable[i]; + vert.nrm = new OpenTK.Vector3( + prm.Vertices.Normal[v].X, + prm.Vertices.Normal[v].Y, + prm.Vertices.Normal[v].Z).Normalized(); + } - if (shape.Primatives[0].SkinningMode == SkinningMode.RIGID_SKINNING) + 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) { - vert.pos = OpenTK.Vector3.TransformPosition(vert.pos, Skeleton.bones[boneId].Transform); - vert.nrm = OpenTK.Vector3.TransformNormal(vert.nrm, Skeleton.bones[boneId].Transform); + 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); } } - } - bool HasSkinning = shape.Primatives[0].SkinningMode != SkinningMode.SINGLE_BONE - && shape.BoneIndices.Type == CmbDataType.UByte; //Noclip checks the type for ubyte so do the same - - bool HasWeights = shape.Primatives[0].SkinningMode == SkinningMode.SMOOTH_SKINNING; - - if (shape.BoneIndices.VertexData != null && HasSkinning && shape.BoneIndices.VertexData.Length > v) - { - var BoneIndices = shape.BoneIndices.VertexData[v]; - for (int j = 0; j < shape.boneDimension; j++) + if (prm.SkinningMode == SkinningMode.Rigid) { - if (BoneIndices[j] < SkinnedBoneTable.Count) - vert.boneIds.Add((int)SkinnedBoneTable[(int)BoneIndices[j]]); - // Console.WriteLine("boneIds " + BoneIndices[j]); + int boneId = (int)prm.Vertices.BoneIndices[v].X; + vert.boneIds.Add(boneId); + vert.boneWeights.Add(1); - // ushort index = shape.Primatives[0].BoneIndexTable[(uint)BoneIndices[j]]; + 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 (shape.BoneWeights.VertexData != null && HasWeights && shape.BoneWeights.VertexData.Length > v) - { - var BoneWeights = shape.BoneWeights.VertexData[v]; - for (int j = 0; j < shape.boneDimension; j++) + + if (prm.SkinningMode == SkinningMode.Mixed) { - vert.boneWeights.Add(BoneWeights[j]); - } - } + int boneId = prm.BoneIndices[0]; + vert.boneIds.Add(boneId); + vert.boneWeights.Add(1); - genericMesh.vertices.Add(vert); + 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); + } } - } - foreach (var prim in shape.Primatives) - { STGenericPolygonGroup group = new STGenericPolygonGroup(); genericMesh.PolygonGroups.Add(group); - for (int i = 0; i < prim.Primatives[0].Indices.Length; i++) + for (int i = 0; i < prm.FaceIndices.Count; i++) { - group.faces.Add((int)prim.Primatives[0].Indices[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); } } @@ -382,7 +387,7 @@ namespace FirstPlugin meshFolder.Nodes.Add(genericMesh); } } - + if (meshFolder.Nodes.Count > 0) Nodes.Add(meshFolder); @@ -404,9 +409,8 @@ namespace FirstPlugin public void Save(System.IO.Stream stream) { - using (var writer = new FileWriter(stream)) { - header.Write(writer); - } + var f = new FileWriter(stream); + f.Write(cmb.WriteFile("", cmb, false).ToArray()); } public enum CMBVersion @@ -431,7 +435,7 @@ namespace FirstPlugin return meshes; } - public CMBMaterialWrapper(Material material, CMB cmb) : base(material.CTRMaterial) + public CMBMaterialWrapper(Material material, CMB cmb, H3DMaterial h3D) : base(h3D) { ParentCMB = cmb; CMBMaterial = material; @@ -442,15 +446,15 @@ namespace FirstPlugin var editor = ParentCMB.LoadEditor(); editor.LoadMaterial(this); - /* STPropertyGrid editor = (STPropertyGrid)LibraryGUI.GetActiveContent(typeof(STPropertyGrid)); - if (editor == null) - { - editor = new STPropertyGrid(); - LibraryGUI.LoadEditor(editor); - } - editor.Text = Text; - editor.Dock = DockStyle.Fill; - editor.LoadProperty(Material, null);*/ + /* STPropertyGrid editor = (STPropertyGrid)LibraryGUI.GetActiveContent(typeof(STPropertyGrid)); + if (editor == null) + { + editor = new STPropertyGrid(); + LibraryGUI.LoadEditor(editor); + } + editor.Text = Text; + editor.Dock = DockStyle.Fill; + editor.LoadProperty(Material, null);*/ } } @@ -460,7 +464,7 @@ namespace FirstPlugin public int TextureIndex { get; set; } - public TextureMap TextureMapData; + public TextureMapper TextureMapData; public override STGenericTexture GetTexture() { @@ -471,53 +475,49 @@ namespace FirstPlugin return null; } - public CMBTextureMapWrapper(TextureMap texMap, CMB cmb) + public CMBTextureMapWrapper(TextureMapper texMap, CMB cmb) { CMBParent = cmb; TextureMapData = texMap; - //Linear filtering looks better according to noclip - if (TextureMapData.MinFiler == TextureFilter.LINEAR_MIPMAP_NEAREST) - TextureMapData.MinFiler = TextureFilter.LINEAR_MIPMAP_LINEAR; - - this.WrapModeS = ConvertWrapMode(TextureMapData.WrapS); - this.WrapModeT = ConvertWrapMode(TextureMapData.WrapT); - this.MinFilter = ConvertMinFilterMode(TextureMapData.MinFiler); - this.MagFilter = ConvertMagFilterMode(TextureMapData.MagFiler); + this.WrapModeS = ConvertWrapMode(TextureMapData.WrapU); + this.WrapModeT = ConvertWrapMode(TextureMapData.WrapV); + this.MinFilter = ConvertMinFilterMode(TextureMapData.TextureMinFilter); + this.MagFilter = ConvertMagFilterMode(TextureMapData.TextureMagFilter); } - private STTextureMinFilter ConvertMinFilterMode(TextureFilter PicaFilterMode) + private STTextureMinFilter ConvertMinFilterMode(ZeldaLib.CtrModelBinary.Types.TextureMinFilter PicaFilterMode) { switch (PicaFilterMode) { - case TextureFilter.LINEAR: return STTextureMinFilter.Linear; - case TextureFilter.LINEAR_MIPMAP_LINEAR: return STTextureMinFilter.LinearMipMapNearest; - case TextureFilter.LINEAR_MIPMAP_NEAREST: return STTextureMinFilter.NearestMipmapLinear; - case TextureFilter.NEAREST: return STTextureMinFilter.Nearest; - case TextureFilter.NEAREST_MIPMAP_LINEAR: return STTextureMinFilter.NearestMipmapLinear; - case TextureFilter.NEAREST_MIPMAP_NEAREST: return STTextureMinFilter.NearestMipmapNearest; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Linear: return STTextureMinFilter.Linear; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Linear_Mipmap_Linear: return STTextureMinFilter.LinearMipMapNearest; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Linear_Mipmap_Nearest: return STTextureMinFilter.NearestMipmapLinear; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Nearest: return STTextureMinFilter.Nearest; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Nearest_Mipmap_Linear: return STTextureMinFilter.NearestMipmapLinear; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Nearest_Mipmap_Nearest: return STTextureMinFilter.NearestMipmapNearest; default: return 0; } } - private STTextureMagFilter ConvertMagFilterMode(TextureFilter PicaFilterMode) + private STTextureMagFilter ConvertMagFilterMode(ZeldaLib.CtrModelBinary.Types.TextureMagFilter PicaFilterMode) { switch (PicaFilterMode) { - case TextureFilter.LINEAR: return STTextureMagFilter.Linear; - case TextureFilter.NEAREST: return STTextureMagFilter.Nearest; + case ZeldaLib.CtrModelBinary.Types.TextureMagFilter.Linear: return STTextureMagFilter.Linear; + case ZeldaLib.CtrModelBinary.Types.TextureMagFilter.Nearest: return STTextureMagFilter.Nearest; default: return 0; } } - private STTextureWrapMode ConvertWrapMode(CMBTextureWrapMode PicaWrapMode) + private STTextureWrapMode ConvertWrapMode(TextureWrap PicaWrapMode) { switch (PicaWrapMode) { - case CMBTextureWrapMode.REPEAT: return STTextureWrapMode.Repeat; - case CMBTextureWrapMode.MIRRORED_REPEAT: return STTextureWrapMode.Mirror; - case CMBTextureWrapMode.CLAMP: return STTextureWrapMode.Clamp; - case CMBTextureWrapMode.CLAMP_TO_EDGE: return STTextureWrapMode.Clamp; + case TextureWrap.Repeat: return STTextureWrapMode.Repeat; + case TextureWrap.Mirror: return STTextureWrapMode.Mirror; + case TextureWrap.ClampToBorder: return STTextureWrapMode.Clamp; + case TextureWrap.ClampToEdge: return STTextureWrapMode.Clamp; default: return STTextureWrapMode.Repeat; } } @@ -525,7 +525,7 @@ namespace FirstPlugin public class CmbMeshWrapper : GenericRenderedObject { - public SeperateShape Shape { get; set; } + public ZeldaLib.CtrModelBinary.CMB_SEPD Mesh { get; set; } STGenericMaterial material; @@ -553,7 +553,7 @@ namespace FirstPlugin return textures; } - set {} + set { } } public TextureFolder(string text) : base(text) @@ -562,1956 +562,281 @@ namespace FirstPlugin } } - public class Header + public H3DMaterial ToH3DMaterial(Material mat) { - public string Name { get; set; } + H3DMaterial h3dMaterial = new H3DMaterial(); + var matParams = h3dMaterial.MaterialParams; - public CMBVersion Version; + if (mat.IsVertexLightingEnabled) + matParams.Flags |= H3DMaterialFlags.IsVertexLightingEnabled; + if (mat.IsFragmentLightingEnabled) + matParams.Flags |= H3DMaterialFlags.IsFragmentLightingEnabled; + if (mat.IsHemiSphereLightingEnabled) + matParams.Flags |= H3DMaterialFlags.IsHemiSphereLightingEnabled; + if (mat.IsHemiSphereOcclusionEnabled) + matParams.Flags |= H3DMaterialFlags.IsHemiSphereOcclusionEnabled; - public uint ChunkCount; //Fixed count per game - - public uint Unknown; - - public SectionData SectionData; - - public void Read(FileReader reader) + switch (mat.LayerConfig) { - string magic = reader.ReadSignature(4, "cmb "); - uint FileSize = reader.ReadUInt32(); - ChunkCount = reader.ReadUInt32(); - Unknown = reader.ReadUInt32(); - - Name = reader.ReadString(0x10).TrimEnd('\0'); - - //Check the chunk count used by the game - if (ChunkCount == 0x0F) - Version = CMBVersion.LM3DS; - else if (ChunkCount == 0x0A) - Version = CMBVersion.MM3DS; - else if (ChunkCount == 0x06) - Version = CMBVersion.OOT3DS; - else - throw new Exception("Unexpected chunk count! " + ChunkCount); - - SectionData = new SectionData(); - SectionData.Read(reader, this); + case LayerConfig.LayerConfig0: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig0; break; + case LayerConfig.LayerConfig1: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig1; break; + case LayerConfig.LayerConfig2: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig2; break; + case LayerConfig.LayerConfig3: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig3; break; + case LayerConfig.LayerConfig4: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig4; break; + case LayerConfig.LayerConfig5: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig5; break; + case LayerConfig.LayerConfig6: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig6; break; + case LayerConfig.LayerConfig7: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig7; break; } - public void Write(FileWriter writer) + for (int i = 0; i < mat.TextureMappers?.Count; i++) { - writer.WriteSignature("cmb "); - writer.Write(uint.MaxValue); //Reserve space for file size offset - writer.Write(ChunkCount); - writer.Write(Unknown); - writer.WriteString(Name, 0x10); + string texture = GetTextureName(mat.TextureMappers[i].TextureID); + if (texture == string.Empty) + continue; - SectionData.Write(writer, this); + if (i == 0) h3dMaterial.Texture0Name = texture; + if (i == 0) h3dMaterial.Texture1Name = texture; + if (i == 0) h3dMaterial.Texture2Name = texture; - //Write the total file size - using (writer.TemporarySeek(4, System.IO.SeekOrigin.Begin)) - { - writer.Write((uint)writer.BaseStream.Length); - } + h3dMaterial.TextureMappers[i].WrapU = ConvertWrapMode(mat.TextureMappers[i].WrapU); + h3dMaterial.TextureMappers[i].WrapV = ConvertWrapMode(mat.TextureMappers[i].WrapV); + h3dMaterial.TextureMappers[i].MagFilter = ConvertTexMagFilter(mat.TextureMappers[i].TextureMagFilter); + h3dMaterial.TextureMappers[i].MinFilter = ConvertTexMinFilter(mat.TextureMappers[i].TextureMinFilter); + h3dMaterial.TextureMappers[i].LODBias = mat.TextureMappers[i].LODBias; + h3dMaterial.TextureMappers[i].MinLOD = (byte)(mat.TextureMappers[i].MinLODBias / 255); + h3dMaterial.TextureMappers[i].BorderColor = new SPICA.Math3D.RGBA( + mat.TextureMappers[i].BorderColor.R, + mat.TextureMappers[i].BorderColor.G, + mat.TextureMappers[i].BorderColor.B, + mat.TextureMappers[i].BorderColor.A); + + matParams.TextureCoords[i].TransformType = H3DTextureTransformType.DccMaya; + matParams.TextureCoords[i].MappingType = H3DTextureMappingType.UvCoordinateMap; + + matParams.TextureCoords[i].Scale = new System.Numerics.Vector2( + mat.TextureCoords[i].Scale.X, mat.TextureCoords[i].Scale.Y); + matParams.TextureCoords[i].Translation = new System.Numerics.Vector2( + mat.TextureCoords[i].Translation.X, mat.TextureCoords[i].Translation.Y); + + matParams.TextureCoords[i].Rotation = mat.TextureCoords[i].Rotation; + } + + matParams.DiffuseColor = ConvertRGBA(mat.DiffuseColor); + matParams.Specular0Color = ConvertRGBA(mat.Specular0Color); + matParams.Specular1Color = ConvertRGBA(mat.Specular1Color); + matParams.EmissionColor = ConvertRGBA(mat.EmissionColor); + matParams.Constant0Color = ConvertRGBA(mat.ConstantColors[0]); + matParams.Constant1Color = ConvertRGBA(mat.ConstantColors[1]); + matParams.Constant2Color = ConvertRGBA(mat.ConstantColors[2]); + matParams.Constant3Color = ConvertRGBA(mat.ConstantColors[3]); + matParams.Constant4Color = ConvertRGBA(mat.ConstantColors[4]); + matParams.Constant5Color = ConvertRGBA(mat.ConstantColors[5]); + matParams.BlendColor = ConvertRGBA(mat.BlendColor); + matParams.TexEnvBufferColor = ConvertRGBA(mat.BufferColor); + + if (mat.CullMode == CullMode.Back) + matParams.FaceCulling = PICAFaceCulling.BackFace; + else if (mat.CullMode == CullMode.Front) + matParams.FaceCulling = PICAFaceCulling.FrontFace; + else + matParams.FaceCulling = PICAFaceCulling.Never; + + matParams.AlphaTest.Enabled = mat.AlphaTest.Enabled; + matParams.AlphaTest.Function = ConvertTestFunction(mat.AlphaTest.Function); + matParams.AlphaTest.Reference = mat.AlphaTest.Reference; + matParams.BlendFunction.ColorSrcFunc = ConvertBlendFunc(mat.BlendFunction.ColorSrcFunc); + matParams.BlendFunction.ColorDstFunc = ConvertBlendFunc(mat.BlendFunction.ColorDstFunc); + matParams.BlendFunction.AlphaSrcFunc = ConvertBlendFunc(mat.BlendFunction.AlphaSrcFunc); + matParams.BlendFunction.AlphaDstFunc = ConvertBlendFunc(mat.BlendFunction.AlphaDstFunc); + + for (int i = 0; i < mat.TexEnvStages.Count; i++) + { + var combiner = mat.TexEnvStages[i]; + var h3dStage = new PICATexEnvStage(); + h3dStage.Source.Color[0] = ConvertCombinerSrc[combiner.Source.Color[0]]; + h3dStage.Source.Color[1] = ConvertCombinerSrc[combiner.Source.Color[1]]; + h3dStage.Source.Color[2] = ConvertCombinerSrc[combiner.Source.Color[2]]; + h3dStage.Source.Alpha[0] = ConvertCombinerSrc[combiner.Source.Alpha[0]]; + h3dStage.Source.Alpha[1] = ConvertCombinerSrc[combiner.Source.Alpha[1]]; + h3dStage.Source.Alpha[2] = ConvertCombinerSrc[combiner.Source.Alpha[2]]; + h3dStage.Operand.Alpha[0] = ConvertConvertCombinerAlphaOp[combiner.Operand.Alpha[0]]; + h3dStage.Operand.Alpha[1] = ConvertConvertCombinerAlphaOp[combiner.Operand.Alpha[1]]; + h3dStage.Operand.Alpha[2] = ConvertConvertCombinerAlphaOp[combiner.Operand.Alpha[2]]; + h3dStage.Operand.Color[0] = ConvertConvertCombinerColorOp[combiner.Operand.Color[0]]; + h3dStage.Operand.Color[1] = ConvertConvertCombinerColorOp[combiner.Operand.Color[1]]; + h3dStage.Operand.Color[2] = ConvertConvertCombinerColorOp[combiner.Operand.Color[2]]; + h3dStage.Scale.Color = ConvertScale[combiner.Scale.Color]; + h3dStage.Scale.Alpha = ConvertScale[combiner.Scale.Alpha]; + h3dStage.Combiner.Alpha = ConvertConvertCombiner[combiner.Combiner.Alpha]; + h3dStage.Combiner.Color = ConvertConvertCombiner[combiner.Combiner.Color]; + + matParams.TexEnvStages[i] = h3dStage; + } + + matParams.LUTInputAbsolute.Dist0 = mat.Distibution0SamplerIsAbs; + matParams.LUTInputAbsolute.Dist1 = mat.Distibution1SamplerIsAbs; + matParams.LUTInputAbsolute.ReflecR = mat.ReflectanceRSamplerIsAbs; + matParams.LUTInputAbsolute.ReflecG = mat.ReflectanceGSamplerIsAbs; + matParams.LUTInputAbsolute.ReflecB = mat.ReflectanceBSamplerIsAbs; + matParams.LUTInputAbsolute.Fresnel = mat.FresnelSamplerIsAbs; + + return h3dMaterial; + } + + private Dictionary ConvertConvertCombiner = + new Dictionary() + { + { TextureCombinerMode.Add, PICATextureCombinerMode.Add }, + { TextureCombinerMode.AddMult, PICATextureCombinerMode.AddMult }, + { TextureCombinerMode.AddSigned, PICATextureCombinerMode.AddSigned }, + { TextureCombinerMode.DotProduct3Rgb, PICATextureCombinerMode.DotProduct3Rgb }, + { TextureCombinerMode.DotProduct3Rgba, PICATextureCombinerMode.DotProduct3Rgba }, + { TextureCombinerMode.Interpolate, PICATextureCombinerMode.Interpolate }, + { TextureCombinerMode.Modulate, PICATextureCombinerMode.Modulate }, + { TextureCombinerMode.MultAdd, PICATextureCombinerMode.MultAdd }, + { TextureCombinerMode.Replace, PICATextureCombinerMode.Replace }, + { TextureCombinerMode.Subtract, PICATextureCombinerMode.Subtract }, + }; + + private Dictionary ConvertCombinerSrc = + new Dictionary() + { + { TextureCombinerSource.Constant, PICATextureCombinerSource.Constant }, + { TextureCombinerSource.FragmentPrimaryColor, PICATextureCombinerSource.FragmentPrimaryColor }, + { TextureCombinerSource.FragmentSecondaryColor, PICATextureCombinerSource.FragmentSecondaryColor }, + { TextureCombinerSource.Previous, PICATextureCombinerSource.Previous }, + { TextureCombinerSource.PreviousBuffer, PICATextureCombinerSource.PreviousBuffer }, + { TextureCombinerSource.PrimaryColor, PICATextureCombinerSource.PrimaryColor }, + { TextureCombinerSource.Texture0, PICATextureCombinerSource.Texture0 }, + { TextureCombinerSource.Texture1, PICATextureCombinerSource.Texture1 }, + { TextureCombinerSource.Texture2, PICATextureCombinerSource.Texture2 }, + { TextureCombinerSource.Texture3, PICATextureCombinerSource.Texture3 }, + }; + + private Dictionary ConvertConvertCombinerAlphaOp = + new Dictionary() + { + { TextureCombinerAlphaOp.OneMinusAlpha, PICATextureCombinerAlphaOp.OneMinusAlpha }, + { TextureCombinerAlphaOp.OneMinusRed, PICATextureCombinerAlphaOp.OneMinusRed }, + { TextureCombinerAlphaOp.OneMinusGreen, PICATextureCombinerAlphaOp.OneMinusGreen }, + { TextureCombinerAlphaOp.OneMinusBlue, PICATextureCombinerAlphaOp.OneMinusBlue }, + { TextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha }, + { TextureCombinerAlphaOp.Red, PICATextureCombinerAlphaOp.Red }, + { TextureCombinerAlphaOp.Green, PICATextureCombinerAlphaOp.Green }, + { TextureCombinerAlphaOp.Blue, PICATextureCombinerAlphaOp.Blue }, + }; + + private Dictionary ConvertConvertCombinerColorOp = + new Dictionary() + { + { TextureCombinerColorOp.OneMinusColor, PICATextureCombinerColorOp.OneMinusColor }, + { TextureCombinerColorOp.OneMinusAlpha, PICATextureCombinerColorOp.OneMinusAlpha }, + { TextureCombinerColorOp.OneMinusRed, PICATextureCombinerColorOp.OneMinusRed }, + { TextureCombinerColorOp.OneMinusGreen, PICATextureCombinerColorOp.OneMinusGreen }, + { TextureCombinerColorOp.OneMinusBlue, PICATextureCombinerColorOp.OneMinusBlue }, + { TextureCombinerColorOp.Alpha, PICATextureCombinerColorOp.Alpha }, + { TextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color }, + { TextureCombinerColorOp.Red, PICATextureCombinerColorOp.Red }, + { TextureCombinerColorOp.Green, PICATextureCombinerColorOp.Green }, + { TextureCombinerColorOp.Blue, PICATextureCombinerColorOp.Blue }, + }; + + private Dictionary ConvertScale = + new Dictionary() + { + { TextureCombinerScale.One, PICATextureCombinerScale.One }, + { TextureCombinerScale.Two, PICATextureCombinerScale.Two }, + { TextureCombinerScale.Four, PICATextureCombinerScale.Four }, + }; + + private PICABlendFunc ConvertBlendFunc(BlendFunc factor) + { + switch (factor) + { + case BlendFunc.ConstantAlpha: return PICABlendFunc.ConstantAlpha; + case BlendFunc.ConstantColor: return PICABlendFunc.ConstantColor; + case BlendFunc.DestinationAlpha: return PICABlendFunc.DestinationAlpha; + case BlendFunc.DestinationColor: return PICABlendFunc.DestinationColor; + case BlendFunc.One: return PICABlendFunc.One; + case BlendFunc.OneMinusConstantAlpha: return PICABlendFunc.OneMinusConstantAlpha; + case BlendFunc.OneMinusConstantColor: return PICABlendFunc.OneMinusConstantColor; + case BlendFunc.OneMinusDestinationAlpha: return PICABlendFunc.OneMinusDestinationAlpha; + case BlendFunc.OneMinusDestinationColor: return PICABlendFunc.OneMinusDestinationColor; + case BlendFunc.OneMinusSourceAlpha: return PICABlendFunc.OneMinusSourceAlpha; + case BlendFunc.OneMinusSourceColor: return PICABlendFunc.OneMinusSourceColor; + case BlendFunc.SourceAlpha: return PICABlendFunc.SourceAlpha; + case BlendFunc.SourceColor: return PICABlendFunc.SourceColor; + case BlendFunc.SourceAlphaSaturate: return PICABlendFunc.SourceAlphaSaturate; + case BlendFunc.Zero: return PICABlendFunc.Zero; + default: return PICABlendFunc.Zero; } } - public class SectionData + private PICATestFunc ConvertTestFunction(TestFunc func) { - public SkeletonChunk SkeletonChunk; - public QuadTreeChunk QuadTreeChunk; - public MaterialChunk MaterialChunk; - - public TextureChunk TextureChunk; - public SkeletalMeshChunk SkeletalMeshChunk; - public LUTSChunk LUTSChunk; - public VertexAttributesChunk VertexAttributesChunk; - - public void Read(FileReader reader, Header header) + switch (func) { - uint numIndices = reader.ReadUInt32(); - SkeletonChunk = ReadChunkSection(reader, header); - if (header.Version >= CMBVersion.MM3DS) - QuadTreeChunk = ReadChunkSection(reader, header); - - MaterialChunk = ReadChunkSection(reader, header); - TextureChunk = ReadChunkSection(reader, header); - SkeletalMeshChunk = ReadChunkSection(reader, header); - LUTSChunk = ReadChunkSection(reader, header); - VertexAttributesChunk = ReadChunkSection(reader, header); - - uint indexBufferOffset = reader.ReadUInt32(); - uint textureDataOffset = reader.ReadUInt32(); - - if (header.Version >= CMBVersion.MM3DS) - reader.ReadUInt32(); //Padding? - - if (VertexAttributesChunk != null) - { - long bufferStart = VertexAttributesChunk.StartPosition; - foreach (var shape in SkeletalMeshChunk.ShapeChunk.SeperateShapes) - { - ReadVertexDataFromSlice(reader, VertexAttributesChunk.PositionSlice, shape.Position, 3, bufferStart); - ReadVertexDataFromSlice(reader, VertexAttributesChunk.NormalSlice, shape.Normal, 3, bufferStart); - ReadVertexDataFromSlice(reader, VertexAttributesChunk.TangentSlice, shape.Tangent, 3, bufferStart); - ReadVertexDataFromSlice(reader, VertexAttributesChunk.ColorSlice, shape.Color, 4, bufferStart); - ReadVertexDataFromSlice(reader, VertexAttributesChunk.Texcoord0Slice, shape.TexCoord0, 2, bufferStart); - ReadVertexDataFromSlice(reader, VertexAttributesChunk.Texcoord1Slice, shape.TexCoord1, 2, bufferStart); - ReadVertexDataFromSlice(reader, VertexAttributesChunk.Texcoord2Slice, shape.TexCoord2, 2, bufferStart); - - ReadVertexDataFromSlice(reader, VertexAttributesChunk.BoneIndicesSlice, shape.BoneIndices, shape.boneDimension, bufferStart); - ReadVertexDataFromSlice(reader, VertexAttributesChunk.BoneWeightsSlice, shape.BoneWeights, shape.boneDimension, bufferStart); - } - } - - if (indexBufferOffset != 0) - { - foreach (var shape in SkeletalMeshChunk.ShapeChunk.SeperateShapes) - { - foreach (var prim in shape.Primatives) - { - foreach (var subprim in prim.Primatives) //Note 3DS usually only has one sub primative - { - subprim.Indices = new uint[subprim.IndexCount]; - - reader.SeekBegin(indexBufferOffset + subprim.Offset); - - switch (subprim.IndexType) - { - case CmbDataType.UByte: - for (int i = 0; i < subprim.IndexCount; i++) - subprim.Indices[i] = reader.ReadByte(); - break; - case CmbDataType.UShort: - for (int i = 0; i < subprim.IndexCount; i++) - subprim.Indices[i] = reader.ReadUInt16(); - break; - case CmbDataType.UInt: - for (int i = 0; i < subprim.IndexCount; i++) - subprim.Indices[i] = reader.ReadUInt32(); - break; - default: - throw new Exception("Unsupported index type! " + subprim.IndexType); - } - } - } - } - } - - foreach (var tex in TextureChunk.Textures) - { - reader.SeekBegin(textureDataOffset + tex.DataOffset); - tex.ImageData = reader.ReadBytes((int)tex.ImageSize); - } - } - - private static void ReadVertexDataFromSlice(FileReader reader, BufferSlice Slice, SepdVertexAttribute VertexAttribute, int elementCount, long bufferStart) - { - if (Slice == null || Slice.Size == 0) - return; - - reader.SeekBegin(bufferStart + VertexAttribute.StartPosition + Slice.Offset); - - int StrideSize = CalculateStrideSize(VertexAttribute.Type, elementCount); - int VertexCount = (int)Slice.Size / StrideSize; - - VertexAttribute.VertexData = new Syroot.Maths.Vector4F[VertexCount]; - if (VertexAttribute.Mode == SepdVertexAttribMode.ARRAY) - { - for (int v = 0; v < VertexCount; v++) { - VertexAttribute.VertexData[v] = ReadVertexBufferData(reader, VertexAttribute, elementCount); - } - } - else - { - VertexAttribute.VertexData[0] = new Syroot.Maths.Vector4F( - VertexAttribute.Constants[0], - VertexAttribute.Constants[1], - VertexAttribute.Constants[2], - VertexAttribute.Constants[3]); - } - - } - - private static Syroot.Maths.Vector4F ReadVertexBufferData(FileReader reader, SepdVertexAttribute VertexAttribute, int elementCount) - { - List values = new List(); - - for (int i = 0; i < elementCount; i++) - { - switch (VertexAttribute.Type) - { - case CmbDataType.Byte: - values.Add(reader.ReadSByte()); - break; - case CmbDataType.Float: - values.Add(reader.ReadSingle()); - break; - case CmbDataType.Int: - values.Add(reader.ReadInt32()); - break; - case CmbDataType.Short: - values.Add(reader.ReadInt16()); - break; - case CmbDataType.UByte: - values.Add(reader.ReadByte()); - break; - case CmbDataType.UInt: - values.Add(reader.ReadUInt32()); - break; - case CmbDataType.UShort: - values.Add(reader.ReadUInt16()); - break; - default: throw new Exception("Unknown format! " + VertexAttribute.Type); - } - } - - while (values.Count < 4) values.Add(0); - - return new Syroot.Maths.Vector4F( - values[0] * VertexAttribute.Scale, - values[1] * VertexAttribute.Scale, - values[2] * VertexAttribute.Scale, - values[3] * VertexAttribute.Scale); - } - - private static void WriteVertexBufferData(FileWriter writer, long startPos, BufferSlice Slice, - SepdVertexAttribute VertexAttribute, int elementCount) - { - if (Slice == null || VertexAttribute == null) - return; - - writer.SeekBegin(startPos + VertexAttribute.StartPosition + Slice.Offset); - for (int v = 0; v < VertexAttribute.VertexData?.Length; v++) { - WriteVertexBufferData(writer, VertexAttribute, VertexAttribute.VertexData[v], elementCount); - } - } - - private static void WriteVertexBufferData(FileWriter writer, SepdVertexAttribute VertexAttribute, - Syroot.Maths.Vector4F value, int elementCount) - { - float[] values = new float[4] { value.X, value.Y, value.Z, value.W }; - - for (int i = 0; i < elementCount; i++) - { - switch (VertexAttribute.Type) - { - case CmbDataType.Byte: - writer.Write((sbyte)values[i]); - break; - case CmbDataType.Float: - writer.Write(values[i]); - break; - case CmbDataType.Int: - writer.Write((int)values[i]); - break; - case CmbDataType.Short: - writer.Write((short)values[i]); - break; - case CmbDataType.UByte: - writer.Write((byte)values[i]); - break; - case CmbDataType.UInt: - writer.Write((uint)values[i]); - break; - case CmbDataType.UShort: - writer.Write((ushort)values[i]); - break; - default: throw new Exception("Unknown format! " + VertexAttribute.Type); - } - } - } - - private static int CalculateStrideSize(CmbDataType type, int elementCount) - { - switch (type) - { - case CmbDataType.Byte: return elementCount * sizeof(sbyte); - case CmbDataType.Float: return elementCount * sizeof(float); - case CmbDataType.Int: return elementCount * sizeof(int); - case CmbDataType.Short: return elementCount * sizeof(short); - case CmbDataType.UByte: return elementCount * sizeof(byte); - case CmbDataType.UInt: return elementCount * sizeof(uint); - case CmbDataType.UShort: return elementCount * sizeof(ushort); - default: throw new Exception("Unknwon format! " + type); - } - } - - private uint GetTotalIndexCount() - { - uint total = 0; - foreach (var shape in SkeletalMeshChunk.ShapeChunk.SeperateShapes) - { - foreach (var prim in shape.Primatives) - { - foreach (var subprim in prim.Primatives) //Note 3DS usually only has one sub primative - total += (uint)subprim.Indices.Length; - } - } - return total; - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.Write(GetTotalIndexCount()); - //Reserve space for all the offses - writer.Write(0); //SkeletonChunk - if (header.Version >= CMBVersion.MM3DS) - writer.Write(0); //QuadTreeChunk - writer.Write(0); //MaterialChunk - writer.Write(0); //TextureChunk - writer.Write(0); //SkeletalMeshChunk - writer.Write(0); //LUTSChunk - writer.Write(0); //VertexAttributesChunk - writer.Write(0); //indexBufferOffset - writer.Write(0); //textureDataOffset - - if (header.Version >= CMBVersion.MM3DS) - writer.Write(0); //padding or unknown unused section - - //Write sections and offsets - int _offsetPos = 4; - if (SkeletonChunk != null) - { - writer.WriteUint32Offset(pos + _offsetPos); - SkeletonChunk.Write(writer, header); - } - - if (QuadTreeChunk != null && header.Version >= CMBVersion.MM3DS) - { - writer.WriteUint32Offset(pos + (_offsetPos += 4)); - QuadTreeChunk.Write(writer, header); - } - - _offsetPos += 4; - if (MaterialChunk != null) - { - writer.WriteUint32Offset(pos + (_offsetPos)); - MaterialChunk.Write(writer, header); - } - - _offsetPos += 4; - if (TextureChunk != null) - { - writer.WriteUint32Offset(pos + (_offsetPos)); - TextureChunk.Write(writer, header); - } - - _offsetPos += 4; - if (SkeletalMeshChunk != null) - { - writer.WriteUint32Offset(pos + (_offsetPos)); - SkeletalMeshChunk.Write(writer, header); - } - - _offsetPos += 4; - if (LUTSChunk != null) - { - writer.WriteUint32Offset(pos + (_offsetPos)); - LUTSChunk.Write(writer, header); - } - - _offsetPos += 4; - if (VertexAttributesChunk != null) - { - writer.WriteUint32Offset(pos + (_offsetPos)); - long vatrPos = writer.Position; - VertexAttributesChunk.Write(writer, header); - foreach (var shape in SkeletalMeshChunk.ShapeChunk.SeperateShapes) - { - WriteVertexBufferData(writer, vatrPos, VertexAttributesChunk.PositionSlice, shape.Position, 3); - WriteVertexBufferData(writer, vatrPos, VertexAttributesChunk.NormalSlice, shape.Normal, 3); - WriteVertexBufferData(writer, vatrPos, VertexAttributesChunk.TangentSlice, shape.Tangent, 3); - WriteVertexBufferData(writer, vatrPos, VertexAttributesChunk.ColorSlice, shape.Color, 4); - WriteVertexBufferData(writer, vatrPos, VertexAttributesChunk.Texcoord0Slice, shape.TexCoord0, 2); - WriteVertexBufferData(writer, vatrPos, VertexAttributesChunk.Texcoord1Slice, shape.TexCoord1, 2); - WriteVertexBufferData(writer, vatrPos, VertexAttributesChunk.Texcoord2Slice, shape.TexCoord2, 2); - - WriteVertexBufferData(writer, vatrPos, VertexAttributesChunk.BoneIndicesSlice, shape.BoneIndices, shape.boneDimension); - WriteVertexBufferData(writer, vatrPos, VertexAttributesChunk.BoneWeightsSlice, shape.BoneWeights, shape.boneDimension); - } - writer.WriteSectionSizeU32(vatrPos + 4, vatrPos, writer.Position); - } - - if (SkeletalMeshChunk != null && SkeletalMeshChunk.ShapeChunk.SeperateShapes.Count > 0) - { - writer.WriteUint32Offset(pos + (_offsetPos += 4)); - - long indexBufferPos = writer.Position; - foreach (var shape in SkeletalMeshChunk.ShapeChunk.SeperateShapes) - { - foreach (var prim in shape.Primatives) - { - foreach (var subprim in prim.Primatives) //Note 3DS usually only has one sub primative - { - writer.SeekBegin(indexBufferPos + subprim.Offset); - - switch (subprim.IndexType) - { - case CmbDataType.UByte: - for (int i = 0; i < subprim.IndexCount; i++) - writer.Write((byte)subprim.Indices[i]); - break; - case CmbDataType.UShort: - for (int i = 0; i < subprim.IndexCount; i++) - writer.Write((ushort)subprim.Indices[i]); - break; - case CmbDataType.UInt: - for (int i = 0; i < subprim.IndexCount; i++) - writer.Write((uint)subprim.Indices[i]); - break; - default: - throw new Exception("Unsupported index type! " + subprim.IndexType); - } - } - } - } - writer.Align(64); - } - - if (TextureChunk != null && TextureChunk.Textures.Count > 0) - { - long dataStart = writer.Position; - writer.WriteUint32Offset(pos + (_offsetPos += 4)); - //Save image data - foreach (var tex in TextureChunk.Textures) - writer.Write(tex.ImageData); - } + case TestFunc.Always: return PICATestFunc.Always; + case TestFunc.Equal: return PICATestFunc.Equal; + case TestFunc.Gequal: return PICATestFunc.Gequal; + case TestFunc.Greater: return PICATestFunc.Greater; + case TestFunc.Lequal: return PICATestFunc.Lequal; + case TestFunc.Less: return PICATestFunc.Less; + case TestFunc.Never: return PICATestFunc.Never; + case TestFunc.Notequal: return PICATestFunc.Notequal; + default: return PICATestFunc.Greater; } } - //Connects all the meshes, vertex attributes, and shape data together - public class SkeletalMeshChunk : IChunkCommon + private SPICA.Math3D.RGBA ConvertRGBA(RGBA color) { - private const string Magic = "sklm"; + return new SPICA.Math3D.RGBA(color.R, color.G, color.B, color.A); + } - public MeshesChunk MeshChunk { get; set; } - public ShapesChunk ShapeChunk { get; set; } - - public void Read(FileReader reader, Header header) + private H3DTextureMagFilter ConvertTexMagFilter(ZeldaLib.CtrModelBinary.Types.TextureMagFilter filterMode) + { + switch (filterMode) { - long pos = reader.Position; + case ZeldaLib.CtrModelBinary.Types.TextureMagFilter.Linear: return H3DTextureMagFilter.Linear; + case ZeldaLib.CtrModelBinary.Types.TextureMagFilter.Nearest: return H3DTextureMagFilter.Nearest; + default: return H3DTextureMagFilter.Linear; - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - MeshChunk = ReadChunkSection(reader, header, pos); - ShapeChunk = ReadChunkSection(reader, header,pos); - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - long _offsetPos = writer.Position; - writer.Write(uint.MaxValue);//MeshChunk - writer.Write(uint.MaxValue);//ShapeChunk - - if (MeshChunk != null) - { - writer.WriteUint32Offset(_offsetPos, pos); - MeshChunk.Write(writer, header); - } - - if (ShapeChunk != null) - { - writer.WriteUint32Offset(_offsetPos + 4, pos); - ShapeChunk.Write(writer, header); - } - - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } } } - public class MeshesChunk : IChunkCommon + private H3DTextureMinFilter ConvertTexMinFilter(ZeldaLib.CtrModelBinary.Types.TextureMinFilter filterMode) { - private const string Magic = "mshs"; - - public List Meshes = new List(); - - public uint Unknown; - - public void Read(FileReader reader, Header header) + switch (filterMode) { - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - uint meshCount = reader.ReadUInt32(); - Unknown = reader.ReadUInt32(); + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Linear: return H3DTextureMinFilter.Linear; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Linear_Mipmap_Linear: return H3DTextureMinFilter.LinearMipmapLinear; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Linear_Mipmap_Nearest: return H3DTextureMinFilter.LinearMipmapNearest; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Nearest: return H3DTextureMinFilter.Nearest; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Nearest_Mipmap_Linear: return H3DTextureMinFilter.NearestMipmapLinear; + case ZeldaLib.CtrModelBinary.Types.TextureMinFilter.Nearest_Mipmap_Nearest: return H3DTextureMinFilter.NearestMipmapNearest; + default: return H3DTextureMinFilter.Linear; - long meshPos = reader.Position; - for (int i = 0; i < meshCount; i++) - { - Mesh mesh = new Mesh(); - - mesh.SepdIndex = reader.ReadUInt16(); - mesh.MaterialIndex = reader.ReadByte(); - mesh.ID = reader.ReadByte(); - Meshes.Add(mesh); - - if (header.Version == CMBVersion.MM3DS) - mesh.unks = reader.ReadBytes(8); - else if (header.Version >= CMBVersion.LM3DS) - mesh.unks = reader.ReadBytes(84); - - Console.WriteLine($"SepdIndex {mesh.SepdIndex}"); - Console.WriteLine($"MaterialIndex { mesh.MaterialIndex}"); - } - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - writer.Write(Meshes.Count); - writer.Write(Unknown); - - for (int i = 0; i < Meshes.Count; i++) { - writer.Write(Meshes[i].SepdIndex); - writer.Write(Meshes[i].MaterialIndex); - writer.Write(Meshes[i].ID); - if (Meshes[i].unks != null) - writer.Write(Meshes[i].unks); - } - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } - } - - public class Mesh - { - public byte[] unks; - - public ushort SepdIndex { get; set; } - public byte MaterialIndex { get; set; } - public byte ID { get; set; } } } - public class ShapesChunk : IChunkCommon + private PICATextureWrap ConvertWrapMode(TextureWrap wrapMode) { - private const string Magic = "shp "; - - public uint Unknown; - - public List SeperateShapes = new List(); - - public void Read(FileReader reader, Header header) + switch (wrapMode) { - long pos = reader.Position; - - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - uint sepdCount = reader.ReadUInt32(); - Unknown = reader.ReadUInt32(); - ushort[] offsets = reader.ReadUInt16s((int)sepdCount); - for (int i = 0; i < sepdCount; i++) - { - reader.SeekBegin(pos + offsets[i]); - var sepd = new SeperateShape(); - sepd.Read(reader, header); - SeperateShapes.Add(sepd); - } - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - writer.Write(SeperateShapes.Count); - writer.Write(Unknown); - long offsetPos = writer.Position; - writer.Write(new ushort[SeperateShapes.Count]); - for (int i = 0; i < SeperateShapes.Count; i++) - { - writer.WriteUint16Offset(offsetPos + (i * 2), pos); - SeperateShapes[i].Write(writer, header); - } - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } + case TextureWrap.ClampToBorder: return PICATextureWrap.ClampToBorder; + case TextureWrap.ClampToEdge: return PICATextureWrap.ClampToEdge; + case TextureWrap.Mirror: return PICATextureWrap.Mirror; + case TextureWrap.Repeat: return PICATextureWrap.Repeat; + default: return PICATextureWrap.Repeat; } } - public class SeperateShape : IChunkCommon + private string GetTextureName(int index) { - private const string Magic = "sepd"; - - public SepdVertexAttribute Position { get; set; } - public SepdVertexAttribute Normal { get; set; } - public SepdVertexAttribute Tangent { get; set; } - public SepdVertexAttribute Color { get; set; } - public SepdVertexAttribute TexCoord0 { get; set; } - public SepdVertexAttribute TexCoord1 { get; set; } - public SepdVertexAttribute TexCoord2 { get; set; } - public SepdVertexAttribute BoneIndices { get; set; } - public SepdVertexAttribute BoneWeights { get; set; } - - public List Primatives = new List(); - - public ushort boneDimension; - public ushort Unknown; - - private byte[] unks; - - public void Read(FileReader reader, Header header) - { - long pos = reader.Position; - - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - uint count = reader.ReadUInt16(); - - if (header.Version >= CMBVersion.LM3DS) - unks = reader.ReadBytes(50); - else - unks = reader.ReadBytes(26); - - Position = ReadVertexAttrib(reader); - Normal = ReadVertexAttrib(reader); - if (header.Version >= CMBVersion.MM3DS) - Tangent = ReadVertexAttrib(reader); - - Color = ReadVertexAttrib(reader); - TexCoord0 = ReadVertexAttrib(reader); - TexCoord1 = ReadVertexAttrib(reader); - TexCoord2 = ReadVertexAttrib(reader); - BoneIndices = ReadVertexAttrib(reader); - BoneWeights = ReadVertexAttrib(reader); - - boneDimension = reader.ReadUInt16(); - Unknown = reader.ReadUInt16(); - - ushort[] Offsets = reader.ReadUInt16s((int)count); - - for (int i = 0; i < count; i++) - { - reader.SeekBegin(pos + Offsets[i]); - PrimativesChunk prim = new PrimativesChunk(); - prim.Read(reader, header); - Primatives.Add(prim); - } - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue); //section size - writer.Write((ushort)Primatives.Count); - writer.Write(unks); - WriteVertexAttrib(writer, Position); - WriteVertexAttrib(writer, Normal); - if (header.Version >= CMBVersion.MM3DS) - WriteVertexAttrib(writer, Tangent); - - WriteVertexAttrib(writer, Color); - WriteVertexAttrib(writer, TexCoord0); - WriteVertexAttrib(writer, TexCoord1); - WriteVertexAttrib(writer, TexCoord2); - WriteVertexAttrib(writer, BoneIndices); - WriteVertexAttrib(writer, BoneWeights); - writer.Write((ushort)boneDimension); - writer.Write((ushort)Unknown); - - long offsetPos = writer.Position; - writer.Write(new ushort[Primatives.Count]); - writer.Write((ushort)0); - for (int i = 0; i < Primatives.Count; i++) - { - writer.WriteUint16Offset(offsetPos + (i * 2), pos); - Primatives[i].Write(writer, header); - } - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } - } - - private SepdVertexAttribute ReadVertexAttrib(FileReader reader) - { - long pos = reader.Position; - - SepdVertexAttribute att = new SepdVertexAttribute(); - att.StartPosition = reader.ReadUInt32(); - att.Scale = reader.ReadSingle(); - att.Type = reader.ReadEnum(true); - att.Mode = reader.ReadEnum(true); - att.Constants = new float[4]; - att.Constants[0] = reader.ReadSingle(); - att.Constants[1] = reader.ReadSingle(); - att.Constants[2] = reader.ReadSingle(); - att.Constants[3] = reader.ReadSingle(); - - reader.SeekBegin(pos + 0x1C); - - return att; - } - - private void WriteVertexAttrib(FileWriter writer, SepdVertexAttribute att) - { - long pos = writer.Position; - - writer.Write(att.StartPosition); - writer.Write(att.Scale); - writer.Write(att.Type, true); - writer.Write(att.Mode, true); - writer.Write(att.Constants[0]); - writer.Write(att.Constants[1]); - writer.Write(att.Constants[2]); - writer.Write(att.Constants[3]); - - writer.SeekBegin(pos + 0x1C); - } - } - - public class SepdVertexAttribute - { - public uint StartPosition { get; set; } - public float Scale { get; set; } - public CmbDataType Type { get; set; } - public SepdVertexAttribMode Mode { get; set; } - - public Syroot.Maths.Vector4F[] VertexData { get; set; } - - public float[] Constants { get; set; } - } - - public class PrimativesChunk : IChunkCommon - { - private const string Magic = "prms"; - - public SkinningMode SkinningMode; - - public List Primatives = new List(); - - public ushort[] BoneIndexTable { get; set; } - - public void Read(FileReader reader, Header header) - { - long pos = reader.Position; - - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - uint count = reader.ReadUInt32(); - SkinningMode = reader.ReadEnum(true); - ushort boneTableCount = reader.ReadUInt16(); - uint boneIndexOffset = reader.ReadUInt32(); - uint primativeOffset = reader.ReadUInt32(); - - reader.SeekBegin(pos + boneIndexOffset); - BoneIndexTable = reader.ReadUInt16s(boneTableCount); - - reader.SeekBegin(pos + primativeOffset); - for (int i = 0; i < count; i++) - { - SubPrimativeChunk prim = new SubPrimativeChunk(); - prim.Read(reader, header); - Primatives.Add(prim); - } - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - writer.Write(Primatives.Count); - writer.Write(SkinningMode, true); - writer.Write((ushort)BoneIndexTable.Length); - - long boneIndexOfsPos = writer.Position; - writer.Write(uint.MaxValue); //bone index offset - - long primativeOfsPos = writer.Position; - writer.Write(uint.MaxValue); //primative offset - - writer.WriteUint32Offset(boneIndexOfsPos, pos); - writer.Write(BoneIndexTable); - writer.Align(4); - - writer.WriteUint32Offset(primativeOfsPos, pos); - for (int i = 0; i < Primatives.Count; i++) - Primatives[i].Write(writer, header); - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } - } - } - - public class SubPrimativeChunk : IChunkCommon - { - private const string Magic = "prm "; - - public SkinningMode SkinningMode { get; private set; } - - public CmbDataType IndexType { get; private set; } - - public ushort IndexCount { get; private set; } - - public uint Offset { get; private set; } - - private uint[] _indices; - public uint[] Indices - { - get - { - return _indices; - } - set - { - _indices = value; - } - } - - public uint Unknown; - public uint Unknown2; - - public void Read(FileReader reader, Header header) - { - long pos = reader.Position; - - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - Unknown = reader.ReadUInt32(); - Unknown2 = reader.ReadUInt32(); - IndexType = reader.ReadEnum(true); - reader.Seek(2); //padding - - IndexCount = reader.ReadUInt16(); - - //This value is the index, so we'll use it as an offset - //Despite the data type, this is always * 2 - Offset = (uint)reader.ReadUInt16() * sizeof(ushort); - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - writer.Write(Unknown); - writer.Write(Unknown2); - writer.Write(IndexType, true); - writer.Seek(2); - writer.Write(IndexCount); - writer.Write((ushort)(Offset / sizeof(ushort))); - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } - } - } - - public class LUTSChunk : IChunkCommon - { - private const string Magic = "luts"; - - private byte[] data; - - public void Read(FileReader reader, Header header) - { - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - - data = reader.getSection((uint)reader.Position, sectionSize - 8); - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - writer.Write(data); - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } - } - } - - public class VertexAttributesChunk : IChunkCommon - { - private const string Magic = "vatr"; - - public BufferSlice PositionSlice; - public BufferSlice NormalSlice; - public BufferSlice TangentSlice; //Used in MM3DS and newer - public BufferSlice ColorSlice; - public BufferSlice Texcoord0Slice; - public BufferSlice Texcoord1Slice; - public BufferSlice Texcoord2Slice; - public BufferSlice BoneIndicesSlice; - public BufferSlice BoneWeightsSlice; - - public long StartPosition; - - public uint MaxIndex; - - public void Read(FileReader reader, Header header) - { - StartPosition = reader.Position; - - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - MaxIndex = reader.ReadUInt32(); - - PositionSlice = ReadSlice(reader); - NormalSlice = ReadSlice(reader); - if (header.Version >= CMBVersion.MM3DS) - TangentSlice = ReadSlice(reader); - - ColorSlice = ReadSlice(reader); - Texcoord0Slice = ReadSlice(reader); - Texcoord1Slice = ReadSlice(reader); - Texcoord2Slice = ReadSlice(reader); - BoneIndicesSlice = ReadSlice(reader); - BoneWeightsSlice = ReadSlice(reader); - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - writer.Write(MaxIndex); - WriteSlice(writer, PositionSlice); - WriteSlice(writer, NormalSlice); - if (header.Version >= CMBVersion.MM3DS) - WriteSlice(writer, TangentSlice); - - WriteSlice(writer, ColorSlice); - WriteSlice(writer, Texcoord0Slice); - WriteSlice(writer, Texcoord1Slice); - WriteSlice(writer, Texcoord2Slice); - WriteSlice(writer, BoneIndicesSlice); - WriteSlice(writer, BoneWeightsSlice); - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } - } - - private void WriteSlice(FileWriter writer, BufferSlice slice) { - writer.Write(slice.Size); - writer.Write(slice.Offset); - } - - private BufferSlice ReadSlice(FileReader reader) - { - BufferSlice slice = new BufferSlice(); - slice.Size = reader.ReadUInt32(); - slice.Offset = reader.ReadUInt32(); - return slice; - } - } - - public class BufferSlice - { - public uint Offset; - public uint Size; - } - - public class SkeletonChunk : IChunkCommon - { - private const string Magic = "skl "; - - public List Bones = new List(); - - public uint Unknown; - - public void Read(FileReader reader, Header header) - { - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - uint boneCount = reader.ReadUInt32(); - Unknown = reader.ReadUInt32(); - - for (int i = 0; i < boneCount; i++) - { - BoneChunk bone = new BoneChunk(); - bone.ID = reader.ReadInt16() & 0xFFFF; - bone.ParentIndex = reader.ReadInt16(); - bone.Scale = reader.ReadVec3SY(); - bone.Rotation = reader.ReadVec3SY(); - bone.Translation = reader.ReadVec3SY(); - if (header.Version >= CMBVersion.MM3DS) - bone.Unknown = reader.ReadInt32(); - - Bones.Add(bone); - } - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - writer.Write(Bones.Count); - writer.Write(Unknown); - for (int i = 0; i < Bones.Count; i++) - { - writer.Write((ushort)Bones[i].ID); - writer.Write((short)Bones[i].ParentIndex); - writer.Write(Bones[i].Scale); - writer.Write(Bones[i].Rotation); - writer.Write(Bones[i].Translation); - if (header.Version >= CMBVersion.MM3DS) - writer.Write(Bones[i].Unknown); - } - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } - } - } - - public class BoneChunk - { - public int ID { get; set; } - public int ParentIndex { get; set; } - - public Syroot.Maths.Vector3F Scale { get; set; } - public Syroot.Maths.Vector3F Rotation { get; set; } - public Syroot.Maths.Vector3F Translation { get; set; } - - //An unknown value used in versions MM3DS and newer - public int Unknown { get; set; } - } - - public class QuadTreeChunk : IChunkCommon - { - private const string Magic = "qtrs"; - - byte[] data; - - public void Read(FileReader reader, Header header) - { - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - - data = reader.getSection((uint)reader.Position, sectionSize); - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - writer.Write(data); - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } - } - } - - public class MaterialChunk : IChunkCommon - { - private const string Magic = "mats"; - - public List Materials = new List(); - - internal int textureCombinerSettingsTableOffs; - public void Read(FileReader reader, Header header) - { - long pos = reader.Position; - - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - uint count = reader.ReadUInt32(); - - int materialSize = 0x15C; - if (header.Version >= CMBVersion.MM3DS) - materialSize = 0x16C; - - Console.WriteLine($"materialSize {materialSize.ToString("x")}"); - - textureCombinerSettingsTableOffs = (int)(pos + 12 + (count * materialSize)); - - for (int i = 0; i < count; i++) - { - reader.SeekBegin(pos + 0xC + (i * materialSize)); - - Material mat = new Material(); - mat.Read(reader, header, this); - Materials.Add(mat); - } - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - writer.Write(Materials.Count); - - for (int i = 0; i < Materials.Count; i++) - Materials[i].Write(writer, header); - for (int i = 0; i < Materials.Count; i++) { - foreach (var combiner in Materials[i].TextureCombiners) - { - writer.Write(combiner.combineRGB, false); - writer.Write(combiner.combineAlpha, false); - writer.Write(combiner.scaleRGB, false); - writer.Write(combiner.scaleAlpha, false); - writer.Write(combiner.bufferInputRGB, false); - writer.Write(combiner.bufferInputAlpha, false); - writer.Write(combiner.source0RGB, false); - writer.Write(combiner.source1RGB, false); - writer.Write(combiner.source2RGB, false); - writer.Write(combiner.op0RGB, false); - writer.Write(combiner.op1RGB, false); - writer.Write(combiner.op2RGB, false); - writer.Write(combiner.source0Alpha, false); - writer.Write(combiner.source1Alpha, false); - writer.Write(combiner.source2Alpha, false); - writer.Write(combiner.op0Alpha, false); - writer.Write(combiner.op1Alpha, false); - writer.Write(combiner.op2Alpha, false); - writer.Write(combiner.constantIndex); - } - } - - long endPos = writer.Position; - using (writer.TemporarySeek(pos + 4, System.IO.SeekOrigin.Begin)) { - writer.Write((uint)(endPos - pos)); - } - } - } - - //Thanks for noclip for material RE stuff - //https://github.com/magcius/noclip.website/blob/9270b9e5022c691703689990f9c536cd9058e5cd/src/oot3d/cmb.ts#L232 - public class Material - { - private Header CMBHeader; - - private H3DMaterial ctrMaterial; - public H3DMaterial CTRMaterial - { - get - { - if (ctrMaterial == null) - ctrMaterial = ToH3DMaterial(); - return ctrMaterial; - } - } - - public bool IsTransparent = false; - - public bool IsFragmentLightingEnabled; - public bool IsVertexLightingEnabled; - public bool IsHemiSphereLightingEnabled; - public bool IsHemiSphereOcclusionEnabled; - - public CullMode CullMode { get; set; } - - public bool IsPolygonOffsetEnabled { get; set; } - public ushort PolygonOffset { get; set; } - - public TextureMap[] TextureMaps { get; set; } - public TextureMatrix[] TextureMaticies { get; set; } - - public uint TotalUsedTextures { get; set; } - public uint TotalUsedTextureCoords { get; set; } - - public List TextureCombiners { get; set; } - - public STColor8 EmissionColor { get; set; } - - public STColor8 AmbientColor { get; set; } - - public STColor8 Diffuse { get; set; } - - public STColor8 Specular0 { get; set; } - - public STColor8 Specular1 { get; set; } - - public STColor8[] ConstantColors { get; set; } - - public bool AlphaTestEnable { get; set; } - public float AlphaTestReference { get; set; } - - public bool DepthTestEnable { get; set; } - - public bool DepthWriteEnable { get; set; } - - public AlphaFunction AlphaTestFunction { get; set; } - - public DepthFunction DepthTestFunction { get; set; } - - public bool BlendEnaled { get; set; } - - public BlendingFactor BlendingFactorSrcRGB { get; set; } - public BlendingFactor BlendingFactorDestRGB { get; set; } - public BlendEquationMode BlendingEquationRGB { get; set; } - - public BlendingFactor BlendingFactorSrcAlpha { get; set; } - public BlendingFactor BlendingFactorDestAlpha { get; set; } - public BlendEquationMode BlendingEquationAlpha { get; set; } - - - public float BlendColorR { get; set; } - public float BlendColorG { get; set; } - public float BlendColorB { get; set; } - public float BlendColorA { get; set; } - - public float BufferColorR { get; set; } - public float BufferColorG { get; set; } - public float BufferColorB { get; set; } - public float BufferColorA { get; set; } - - public TextureUnit BumpMapIndex { get; set; } - public BumpMode BumpMapMode { get; set; } - public short IsBumpRenormalize { get; set; } - - public LayerConfig LayerConfig { get; set; } - - public FresnelSelector FresnelSelector { get; set; } - - public bool IsClampHighLight { get; set; } - public bool IsDistribution0Enabled { get; set; } - public bool IsDistribution1Enabled { get; set; } - public bool IsGeometricFactor0Enabled { get; set; } - public bool IsGeometricFactor1Enabled { get; set; } - public bool IsReflectionEnabled { get; set; } - - private byte[] data; - - public H3DMaterial ToH3DMaterial() - { - H3DMaterial h3dMaterial = new H3DMaterial(); - var matParams = h3dMaterial.MaterialParams; - - if (IsVertexLightingEnabled) - matParams.Flags |= H3DMaterialFlags.IsVertexLightingEnabled; - if (IsFragmentLightingEnabled) - matParams.Flags |= H3DMaterialFlags.IsFragmentLightingEnabled; - if (IsHemiSphereLightingEnabled) - matParams.Flags |= H3DMaterialFlags.IsHemiSphereLightingEnabled; - if (IsHemiSphereOcclusionEnabled) - matParams.Flags |= H3DMaterialFlags.IsHemiSphereOcclusionEnabled; - - switch (LayerConfig) - { - case LayerConfig.LayerConfig0: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig0; break; - case LayerConfig.LayerConfig1: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig1; break; - case LayerConfig.LayerConfig2: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig2; break; - case LayerConfig.LayerConfig3: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig3; break; - case LayerConfig.LayerConfig4: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig4; break; - case LayerConfig.LayerConfig5: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig5; break; - case LayerConfig.LayerConfig6: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig6; break; - case LayerConfig.LayerConfig7: matParams.TranslucencyKind = H3DTranslucencyKind.LayerConfig7; break; - } - - for (int i = 0; i < TextureMaps?.Length; i++) - { - string texture = GetTextureName(TextureMaps[i].TextureIndex); - if (texture == string.Empty) - continue; - - if (i == 0) h3dMaterial.Texture0Name = texture; - if (i == 0) h3dMaterial.Texture1Name = texture; - if (i == 0) h3dMaterial.Texture2Name = texture; - - h3dMaterial.TextureMappers[i].WrapU = ConvertWrapMode(TextureMaps[i].WrapS); - h3dMaterial.TextureMappers[i].WrapV = ConvertWrapMode(TextureMaps[i].WrapT); - h3dMaterial.TextureMappers[i].MagFilter = ConvertTexMagFilter(TextureMaps[i].MagFiler); - h3dMaterial.TextureMappers[i].MinFilter = ConvertTexMinFilter(TextureMaps[i].MinFiler); - h3dMaterial.TextureMappers[i].LODBias = TextureMaps[i].LodBias; - h3dMaterial.TextureMappers[i].MinLOD = (byte)(TextureMaps[i].MinLOD / 255); - h3dMaterial.TextureMappers[i].BorderColor = new SPICA.Math3D.RGBA( - TextureMaps[i].borderColorR, - TextureMaps[i].borderColorG, - TextureMaps[i].borderColorB, - TextureMaps[i].borderColorA); - - matParams.TextureCoords[i].TransformType = H3DTextureTransformType.DccMaya; - matParams.TextureCoords[i].MappingType = H3DTextureMappingType.UvCoordinateMap; - - matParams.TextureCoords[i].Scale = new System.Numerics.Vector2( - TextureMaticies[i].Scale.X, TextureMaticies[i].Scale.Y); - matParams.TextureCoords[i].Translation = new System.Numerics.Vector2( - TextureMaticies[i].Translate.X, TextureMaticies[i].Translate.Y); - - matParams.TextureCoords[i].Rotation = TextureMaticies[i].Rotate; - } - - matParams.DiffuseColor = ConvertRGBA(Diffuse); - matParams.Specular0Color = ConvertRGBA(Specular0); - matParams.Specular1Color = ConvertRGBA(Specular1); - matParams.EmissionColor = ConvertRGBA(EmissionColor); - matParams.Constant0Color = ConvertRGBA(ConstantColors[0]); - matParams.Constant1Color = ConvertRGBA(ConstantColors[1]); - matParams.Constant2Color = ConvertRGBA(ConstantColors[2]); - matParams.Constant3Color = ConvertRGBA(ConstantColors[3]); - matParams.Constant4Color = ConvertRGBA(ConstantColors[4]); - matParams.Constant5Color = ConvertRGBA(ConstantColors[5]); - matParams.BlendColor = ConvertRGBA(BlendColorR, BlendColorG, BlendColorB, BlendColorA); - matParams.TexEnvBufferColor = ConvertRGBA(BufferColorR, BufferColorG, BufferColorB, BufferColorA); - - if (CullMode == CullMode.BACK) - matParams.FaceCulling = PICAFaceCulling.BackFace; - else if (CullMode == CullMode.FRONT) - matParams.FaceCulling = PICAFaceCulling.FrontFace; - else - matParams.FaceCulling = PICAFaceCulling.Never; - - matParams.AlphaTest.Enabled = AlphaTestEnable; - matParams.AlphaTest.Function = ConvertAlphaFunction(AlphaTestFunction); - matParams.AlphaTest.Reference = (byte)(AlphaTestReference / 0xff); - matParams.BlendFunction.ColorSrcFunc = ConvertBlendFunc(BlendingFactorSrcRGB); - matParams.BlendFunction.ColorDstFunc = ConvertBlendFunc(BlendingFactorDestRGB); - matParams.BlendFunction.AlphaSrcFunc = ConvertBlendFunc(BlendingFactorSrcAlpha); - matParams.BlendFunction.AlphaDstFunc = ConvertBlendFunc(BlendingFactorDestAlpha); - - for (int i = 0; i < TextureCombiners.Count; i++) - { - var combiner = TextureCombiners[i]; - var h3dStage = new PICATexEnvStage(); - /* h3dStage.Source.Color[0] = ConvertCombinerSrc[combiner.source0RGB]; - h3dStage.Source.Color[1] = ConvertCombinerSrc[combiner.source1RGB]; - h3dStage.Source.Color[2] = ConvertCombinerSrc[combiner.source2RGB]; - h3dStage.Source.Alpha[0] = ConvertCombinerSrc[combiner.source0Alpha]; - h3dStage.Source.Alpha[1] = ConvertCombinerSrc[combiner.source1Alpha]; - h3dStage.Source.Alpha[2] = ConvertCombinerSrc[combiner.source2Alpha]; - h3dStage.Operand.Alpha[0] = ConvertConvertCombinerAlphaOp[combiner.op0Alpha]; - h3dStage.Operand.Alpha[1] = ConvertConvertCombinerAlphaOp[combiner.op1Alpha]; - h3dStage.Operand.Alpha[2] = ConvertConvertCombinerAlphaOp[combiner.op2Alpha]; - h3dStage.Operand.Color[0] = ConvertConvertCombinerColorOp[combiner.op0RGB]; - h3dStage.Operand.Color[1] = ConvertConvertCombinerColorOp[combiner.op1RGB]; - h3dStage.Scale.Color = ConvertScale[combiner.scaleRGB]; - h3dStage.Scale.Alpha = ConvertScale[combiner.scaleAlpha]; - h3dStage.Combiner.Alpha = ConvertConvertCombiner[combiner.combineAlpha]; - h3dStage.Combiner.Color = ConvertConvertCombiner[combiner.combineRGB];*/ - - matParams.TexEnvStages[i] = h3dStage; - } - - matParams.LUTInputAbsolute.Dist0 = LUTTable.reflectance0SamplerIsAbs; - matParams.LUTInputAbsolute.Dist1 = LUTTable.reflectance1SamplerIsAbs; - matParams.LUTInputAbsolute.ReflecR = LUTTable.reflectanceRSamplerIsAbs; - matParams.LUTInputAbsolute.ReflecG = LUTTable.reflectanceGSamplerIsAbs; - matParams.LUTInputAbsolute.ReflecB = LUTTable.reflectanceBSamplerIsAbs; - matParams.LUTInputAbsolute.Fresnel = LUTTable.fresnelSamplerIsAbs; - - return h3dMaterial; - } - - private Dictionary ConvertConvertCombiner = - new Dictionary() - { - { CombineResultOpDMP.ADD, PICATextureCombinerMode.Add }, - { CombineResultOpDMP.ADD_MULT, PICATextureCombinerMode.AddMult }, - { CombineResultOpDMP.ADD_SIGNED, PICATextureCombinerMode.AddSigned }, - { CombineResultOpDMP.DOT3_RGB, PICATextureCombinerMode.DotProduct3Rgb }, - { CombineResultOpDMP.DOT3_RGBA, PICATextureCombinerMode.DotProduct3Rgba }, - { CombineResultOpDMP.INTERPOLATE, PICATextureCombinerMode.Interpolate }, - { CombineResultOpDMP.MODULATE, PICATextureCombinerMode.Modulate }, - { CombineResultOpDMP.MULT_ADD, PICATextureCombinerMode.MultAdd }, - { CombineResultOpDMP.REPLACE, PICATextureCombinerMode.Replace }, - { CombineResultOpDMP.SUBTRACT, PICATextureCombinerMode.Subtract }, - }; - - private Dictionary ConvertCombinerSrc = - new Dictionary() - { - { CombineSourceDMP.CONSTANT, PICATextureCombinerSource.Constant }, - { CombineSourceDMP.FRAGMENT_PRIMARY_COLOR, PICATextureCombinerSource.FragmentPrimaryColor }, - { CombineSourceDMP.FRAGMENT_SECONDARY_COLOR, PICATextureCombinerSource.FragmentSecondaryColor }, - { CombineSourceDMP.PREVIOUS, PICATextureCombinerSource.Previous }, - { CombineSourceDMP.PREVIOUS_BUFFER, PICATextureCombinerSource.PreviousBuffer }, - { CombineSourceDMP.PRIMARY_COLOR, PICATextureCombinerSource.PrimaryColor }, - { CombineSourceDMP.TEXTURE0, PICATextureCombinerSource.Texture0 }, - { CombineSourceDMP.TEXTURE1, PICATextureCombinerSource.Texture1 }, - { CombineSourceDMP.TEXTURE2, PICATextureCombinerSource.Texture2 }, - { CombineSourceDMP.TEXTURE3, PICATextureCombinerSource.Texture3 }, - }; - - private Dictionary ConvertConvertCombinerAlphaOp = - new Dictionary() - { - { CombineOpDMP.ONE_MINUS_SRC_COLOR, PICATextureCombinerAlphaOp.OneMinusAlpha }, - { CombineOpDMP.ONE_MINUS_SRC_ALPHA, PICATextureCombinerAlphaOp.OneMinusAlpha }, - { CombineOpDMP.ONE_MINUS_SRC_R, PICATextureCombinerAlphaOp.OneMinusRed }, - { CombineOpDMP.ONE_MINUS_SRC_G, PICATextureCombinerAlphaOp.OneMinusGreen }, - { CombineOpDMP.ONE_MINUS_SRC_B, PICATextureCombinerAlphaOp.OneMinusBlue }, - { CombineOpDMP.SRC_ALPHA, PICATextureCombinerAlphaOp.Alpha }, - { CombineOpDMP.SRC_COLOR, PICATextureCombinerAlphaOp.Alpha }, - { CombineOpDMP.SRC_R, PICATextureCombinerAlphaOp.Red }, - { CombineOpDMP.SRC_B, PICATextureCombinerAlphaOp.Blue }, - { CombineOpDMP.SRC_G, PICATextureCombinerAlphaOp.Green }, - }; - - private Dictionary ConvertConvertCombinerColorOp = - new Dictionary() - { - { CombineOpDMP.ONE_MINUS_SRC_COLOR, PICATextureCombinerColorOp.OneMinusColor }, - { CombineOpDMP.ONE_MINUS_SRC_ALPHA, PICATextureCombinerColorOp.OneMinusAlpha }, - { CombineOpDMP.ONE_MINUS_SRC_R, PICATextureCombinerColorOp.OneMinusRed }, - { CombineOpDMP.ONE_MINUS_SRC_G, PICATextureCombinerColorOp.OneMinusGreen }, - { CombineOpDMP.ONE_MINUS_SRC_B, PICATextureCombinerColorOp.OneMinusBlue }, - { CombineOpDMP.SRC_ALPHA, PICATextureCombinerColorOp.Alpha }, - { CombineOpDMP.SRC_COLOR, PICATextureCombinerColorOp.Color }, - { CombineOpDMP.SRC_R, PICATextureCombinerColorOp.Red }, - { CombineOpDMP.SRC_B, PICATextureCombinerColorOp.Blue }, - { CombineOpDMP.SRC_G, PICATextureCombinerColorOp.Green }, - }; - - private Dictionary ConvertScale = - new Dictionary() - { - { CombineScaleDMP._1, PICATextureCombinerScale.One }, - { CombineScaleDMP._2, PICATextureCombinerScale.Two }, - { CombineScaleDMP._4, PICATextureCombinerScale.Four }, - }; - - - private PICABlendEquation ConvertEquation() - { - return PICABlendEquation.FuncAdd; - } - - private PICABlendFunc ConvertBlendFunc(BlendingFactor factor) - { - switch (factor) - { - case BlendingFactor.ConstantAlpha: return PICABlendFunc.ConstantAlpha; - case BlendingFactor.ConstantColor: return PICABlendFunc.ConstantColor; - case BlendingFactor.DstAlpha: return PICABlendFunc.DestinationAlpha; - case BlendingFactor.DstColor: return PICABlendFunc.DestinationColor; - case BlendingFactor.One: return PICABlendFunc.One; - case BlendingFactor.OneMinusConstantAlpha: return PICABlendFunc.OneMinusConstantAlpha; - case BlendingFactor.OneMinusConstantColor: return PICABlendFunc.OneMinusConstantColor; - case BlendingFactor.OneMinusDstAlpha: return PICABlendFunc.OneMinusDestinationAlpha; - case BlendingFactor.OneMinusDstColor: return PICABlendFunc.OneMinusDestinationColor; - case BlendingFactor.OneMinusSrcAlpha: return PICABlendFunc.OneMinusSourceAlpha; - case BlendingFactor.OneMinusSrcColor: return PICABlendFunc.OneMinusSourceColor; - case BlendingFactor.Src1Alpha: return PICABlendFunc.SourceAlpha; - case BlendingFactor.Src1Color: return PICABlendFunc.SourceColor; - case BlendingFactor.SrcAlpha: return PICABlendFunc.SourceColor; - case BlendingFactor.SrcColor: return PICABlendFunc.SourceColor; - case BlendingFactor.SrcAlphaSaturate: return PICABlendFunc.SourceAlphaSaturate; - case BlendingFactor.Zero: return PICABlendFunc.Zero; - default: return PICABlendFunc.Zero; - } - } - - private PICATestFunc ConvertAlphaFunction(AlphaFunction func) - { - switch (func) - { - case AlphaFunction.Always: return PICATestFunc.Always; - case AlphaFunction.Equal: return PICATestFunc.Equal; - case AlphaFunction.Gequal: return PICATestFunc.Gequal; - case AlphaFunction.Greater: return PICATestFunc.Greater; - case AlphaFunction.Lequal: return PICATestFunc.Lequal ; - case AlphaFunction.Less: return PICATestFunc.Less; - case AlphaFunction.Never: return PICATestFunc.Never; - case AlphaFunction.Notequal: return PICATestFunc.Notequal; - default: return PICATestFunc.Always; - } - } - - private SPICA.Math3D.RGBA ConvertRGBA(STColor8 color) - { - return new SPICA.Math3D.RGBA(color.R, color.G, color.B, color.A); - } - - private SPICA.Math3D.RGBA ConvertRGBA(float R, float G, float B, float A = 255) - { - return new SPICA.Math3D.RGBA((byte)Utils.FloatToIntClamp(R), - (byte)Utils.FloatToIntClamp(G), - (byte)Utils.FloatToIntClamp(B), - (byte)Utils.FloatToIntClamp(A)); - } - - private H3DTextureMagFilter ConvertTexMagFilter(TextureFilter filterMode) - { - switch (filterMode) - { - case TextureFilter.LINEAR: return H3DTextureMagFilter.Linear; - case TextureFilter.NEAREST: return H3DTextureMagFilter.Nearest; - default: return H3DTextureMagFilter.Linear; - - } - } - - private H3DTextureMinFilter ConvertTexMinFilter(TextureFilter filterMode) - { - switch (filterMode) - { - case TextureFilter.LINEAR: return H3DTextureMinFilter.Linear; - case TextureFilter.LINEAR_MIPMAP_LINEAR: return H3DTextureMinFilter.LinearMipmapLinear; - case TextureFilter.LINEAR_MIPMAP_NEAREST: return H3DTextureMinFilter.LinearMipmapNearest; - case TextureFilter.NEAREST: return H3DTextureMinFilter.Nearest; - case TextureFilter.NEAREST_MIPMAP_LINEAR: return H3DTextureMinFilter.NearestMipmapLinear; - case TextureFilter.NEAREST_MIPMAP_NEAREST: return H3DTextureMinFilter.NearestMipmapNearest; - default: return H3DTextureMinFilter.Linear; - - } - } - - private PICATextureWrap ConvertWrapMode(CMBTextureWrapMode wrapMode) - { - switch (wrapMode) - { - case CMBTextureWrapMode.CLAMP: return PICATextureWrap.ClampToBorder; - case CMBTextureWrapMode.CLAMP_TO_EDGE: return PICATextureWrap.ClampToEdge; - case CMBTextureWrapMode.MIRRORED_REPEAT: return PICATextureWrap.Mirror; - case CMBTextureWrapMode.REPEAT: return PICATextureWrap.Repeat; - default: return PICATextureWrap.Repeat; - } - } - - private string GetTextureName(int index) - { - if (index != -1 && index < CMBHeader.SectionData.TextureChunk?.Textures?.Count) - return CMBHeader.SectionData.TextureChunk.Textures[index].Name; - else - return ""; - } - - public LightTable LUTTable; - - public struct LightTable - { - public bool reflectanceRSamplerIsAbs; - public sbyte reflectanceRSamplerIndex; - public LUTInput reflectanceRSamplerInput; - public float reflectanceRSamplerScale; - - public bool reflectanceGSamplerIsAbs; - public sbyte reflectanceGSamplerIndex; - public LUTInput reflectanceGSamplerInput; - public float reflectanceGSamplerScale; - - public bool reflectanceBSamplerIsAbs; - public sbyte reflectanceBSamplerIndex; - public LUTInput reflectanceBSamplerInput; - public float reflectanceBSamplerScale; - - public bool reflectance0SamplerIsAbs; - public sbyte reflectance0SamplerIndex; - public LUTInput reflectance0SamplerInput; - public float reflectance0SamplerScale; - - public bool reflectance1SamplerIsAbs; - public sbyte reflectance1SamplerIndex; - public LUTInput reflectance1SamplerInput; - public float reflectance1SamplerScale; - - public bool fresnelSamplerIsAbs; - public sbyte fresnelSamplerIndex; - public LUTInput fresnelSamplerInput; - public float fresnelSamplerScale; - } - - public void Read(FileReader reader, Header header, MaterialChunk materialChunkParent) - { - CMBHeader = header; - - TextureMaps = new TextureMap[3]; - TextureMaticies = new TextureMatrix[3]; - TextureCombiners = new List(); - - long pos = reader.Position; - - IsFragmentLightingEnabled = reader.ReadBoolean(); - IsVertexLightingEnabled = reader.ReadBoolean(); - IsHemiSphereLightingEnabled = reader.ReadBoolean(); - - //Tip: IsHemiSphereOcclusionEnabled cannot be enabled unless "IsHemiSphereOcclusionEnabled" is enabled first - IsHemiSphereOcclusionEnabled = reader.ReadBoolean(); - - CullMode = reader.ReadEnum(true); //byte - IsPolygonOffsetEnabled = reader.ReadBoolean(); //byte - PolygonOffset = reader.ReadUInt16(); - PolygonOffset = IsPolygonOffsetEnabled ? (ushort)((int)PolygonOffset / 0x10000) : (ushort)0; - TotalUsedTextures = reader.ReadUInt32(); - TotalUsedTextureCoords = reader.ReadUInt32(); - - //Texture bind data - for (int j = 0; j < 3; j++) - { - TextureMaps[j] = new TextureMap(); - TextureMaps[j].TextureIndex = reader.ReadInt16(); - reader.ReadInt16(); //padding - TextureMaps[j].MinFiler = (TextureFilter)reader.ReadUInt16(); - TextureMaps[j].MagFiler = (TextureFilter)reader.ReadUInt16(); - TextureMaps[j].WrapS = (CMBTextureWrapMode)reader.ReadUInt16(); - TextureMaps[j].WrapT = (CMBTextureWrapMode)reader.ReadUInt16(); - TextureMaps[j].MinLOD = reader.ReadSingle(); - TextureMaps[j].LodBias = reader.ReadSingle(); - TextureMaps[j].borderColorR = reader.ReadByte(); - TextureMaps[j].borderColorG = reader.ReadByte(); - TextureMaps[j].borderColorB = reader.ReadByte(); - TextureMaps[j].borderColorA = reader.ReadByte(); - } - - for (int j = 0; j < 3; j++) - { - TextureMaticies[j] = new TextureMatrix(); - TextureMaticies[j].MatrixMode = reader.ReadByte(); - TextureMaticies[j].ReferenceCamera = reader.ReadByte(); - TextureMaticies[j].MappingMethod = reader.ReadByte(); - TextureMaticies[j].CoordinateIndex = reader.ReadByte(); - TextureMaticies[j].Scale = reader.ReadVec2SY(); - TextureMaticies[j].Rotate = reader.ReadSingle(); - TextureMaticies[j].Translate = reader.ReadVec2SY(); - } - - EmissionColor = STColor8.FromBytes(reader.ReadBytes(4)); - AmbientColor = STColor8.FromBytes(reader.ReadBytes(4)); - Diffuse = STColor8.FromBytes(reader.ReadBytes(4)); - Specular0 = STColor8.FromBytes(reader.ReadBytes(4)); - Specular1 = STColor8.FromBytes(reader.ReadBytes(4)); - - ConstantColors = new STColor8[6]; - ConstantColors[0] = STColor8.FromBytes(reader.ReadBytes(4)); - ConstantColors[1] = STColor8.FromBytes(reader.ReadBytes(4)); - ConstantColors[2] = STColor8.FromBytes(reader.ReadBytes(4)); - ConstantColors[3] = STColor8.FromBytes(reader.ReadBytes(4)); - ConstantColors[4] = STColor8.FromBytes(reader.ReadBytes(4)); - ConstantColors[5] = STColor8.FromBytes(reader.ReadBytes(4)); - - BufferColorR = reader.ReadSingle(); - BufferColorG = reader.ReadSingle(); - BufferColorB = reader.ReadSingle(); - BufferColorA = reader.ReadSingle(); - - BumpMapIndex = (TextureUnit)reader.ReadUInt16(); - BumpMapMode = (BumpMode)reader.ReadUInt16(); - IsBumpRenormalize = reader.ReadInt16(); - reader.ReadInt16(); //padding - LayerConfig = (LayerConfig)reader.ReadUInt16(); - reader.ReadInt16(); //padding - FresnelSelector = (FresnelSelector)reader.ReadUInt16(); - IsClampHighLight = reader.ReadBoolean(); - IsDistribution0Enabled = reader.ReadBoolean(); - IsDistribution1Enabled = reader.ReadBoolean(); - IsGeometricFactor0Enabled = reader.ReadBoolean(); - IsGeometricFactor1Enabled = reader.ReadBoolean(); - IsReflectionEnabled = reader.ReadBoolean(); - - // Fragment lighting table. - LUTTable.reflectanceRSamplerIsAbs = reader.ReadBoolean(); - LUTTable.reflectanceRSamplerIndex = reader.ReadSByte(); - LUTTable.reflectanceRSamplerInput = (LUTInput)reader.ReadUInt16(); - LUTTable.reflectanceRSamplerScale = reader.ReadSingle(); - - LUTTable.reflectanceGSamplerIsAbs = reader.ReadBoolean(); - LUTTable.reflectanceGSamplerIndex = reader.ReadSByte(); - LUTTable.reflectanceGSamplerInput = (LUTInput)reader.ReadUInt16(); - LUTTable.reflectanceGSamplerScale = reader.ReadSingle(); - - LUTTable.reflectanceBSamplerIsAbs = reader.ReadBoolean(); - LUTTable.reflectanceBSamplerIndex = reader.ReadSByte(); - LUTTable.reflectanceBSamplerInput = (LUTInput)reader.ReadUInt16(); - LUTTable.reflectanceBSamplerScale = reader.ReadSingle(); - - LUTTable.reflectance0SamplerIsAbs = reader.ReadBoolean(); - LUTTable.reflectance0SamplerIndex = reader.ReadSByte(); - LUTTable.reflectance0SamplerInput = (LUTInput)reader.ReadUInt16(); - LUTTable.reflectance0SamplerScale = reader.ReadSingle(); - - LUTTable.reflectance1SamplerIsAbs = reader.ReadBoolean(); - LUTTable.reflectance1SamplerIndex = reader.ReadSByte(); - LUTTable.reflectance1SamplerInput = (LUTInput)reader.ReadUInt16(); - LUTTable.reflectance1SamplerScale = reader.ReadSingle(); - - LUTTable.fresnelSamplerIsAbs = reader.ReadBoolean(); - LUTTable.fresnelSamplerIndex = reader.ReadSByte(); - LUTTable.fresnelSamplerInput = (LUTInput)reader.ReadUInt16(); - LUTTable.fresnelSamplerScale = reader.ReadSingle(); - - reader.SeekBegin(pos + 0x120); - uint textureCombinerTableCount = reader.ReadUInt32(); - var skip = reader.Position; - int textureCombinerTableIdx = (int)pos + 0x124; - for (int i = 0; i < textureCombinerTableCount; i++) - { - reader.SeekBegin(textureCombinerTableIdx + 0x00); - ushort textureCombinerIndex = reader.ReadUInt16(); - - reader.SeekBegin(materialChunkParent.textureCombinerSettingsTableOffs + textureCombinerIndex * 0x28); - TextureCombiner combner = new TextureCombiner(); - combner.combineRGB = reader.ReadEnum(false); - combner.combineAlpha = reader.ReadEnum(false); - combner.scaleRGB = reader.ReadEnum(false); - combner.scaleAlpha = reader.ReadEnum(false); - combner.bufferInputRGB = reader.ReadEnum(false); - combner.bufferInputAlpha = reader.ReadEnum(false); - combner.source0RGB = reader.ReadEnum(false); - combner.source1RGB = reader.ReadEnum(false); - combner.source2RGB = reader.ReadEnum(false); - combner.op0RGB = reader.ReadEnum(false); - combner.op1RGB = reader.ReadEnum(false); - combner.op2RGB = reader.ReadEnum(false); - combner.source0Alpha = reader.ReadEnum(false); - combner.source1Alpha = reader.ReadEnum(false); - combner.source2Alpha = reader.ReadEnum(false); - combner.op0Alpha = reader.ReadEnum(false); - combner.op1Alpha = reader.ReadEnum(false); - combner.op2Alpha = reader.ReadEnum(false); - combner.constantIndex = reader.ReadUInt32(); - TextureCombiners.Add(combner); - - textureCombinerTableIdx += 0x2; - } - - //Skip TexEnvStages indices. (always 0x6) - reader.SeekBegin(skip + 0x0C); - - AlphaTestEnable = reader.ReadBoolean(); - AlphaTestReference = reader.ReadByte() / 0xFF; - AlphaTestFunction = (AlphaFunction)reader.ReadUInt16(); - - DepthTestEnable = reader.ReadBoolean(); - DepthWriteEnable = reader.ReadBoolean(); - DepthTestFunction = (DepthFunction)reader.ReadUInt16(); - - if (!AlphaTestEnable) - AlphaTestFunction = AlphaFunction.Always; - - if (!DepthTestEnable) - DepthTestFunction = DepthFunction.Always; - - BlendEnaled = reader.ReadBoolean(); - - //Unknown. - reader.ReadByte(); - reader.ReadByte(); - reader.ReadByte(); - - BlendingFactorSrcAlpha = (BlendingFactor)reader.ReadUInt16(); - BlendingFactorDestAlpha = (BlendingFactor)reader.ReadUInt16(); - BlendingEquationAlpha = (BlendEquationMode)reader.ReadUInt32(); - - BlendingFactorSrcRGB = (BlendingFactor)reader.ReadUInt16(); - BlendingFactorDestRGB = (BlendingFactor)reader.ReadUInt16(); - BlendingEquationRGB = (BlendEquationMode)reader.ReadUInt32(); - - BlendColorR = reader.ReadSingle(); - BlendColorG = reader.ReadSingle(); - BlendColorB = reader.ReadSingle(); - BlendColorA = reader.ReadSingle(); - - IsTransparent = BlendEnaled; - - if (header.Version > CMBVersion.OOT3DS) - { - byte StencilEnabled = reader.ReadByte(); - byte StencilReferenceValue = reader.ReadByte(); - byte BufferMask = reader.ReadByte(); - byte Buffer = reader.ReadByte(); - ushort StencilFunc = reader.ReadUInt16(); - ushort FailOP = reader.ReadUInt16(); - ushort ZFailOP = reader.ReadUInt16(); - ushort ZPassOP = reader.ReadUInt16(); - ushort unk6 = reader.ReadUInt16(); - ushort unk7 = reader.ReadUInt16(); - } - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.Write(IsFragmentLightingEnabled); - writer.Write(IsVertexLightingEnabled); - writer.Write(IsHemiSphereLightingEnabled); - writer.Write(IsHemiSphereOcclusionEnabled); - writer.Write(CullMode, true); - writer.Write(IsPolygonOffsetEnabled); - writer.Write(PolygonOffset); - writer.Write(TotalUsedTextures); - writer.Write(TotalUsedTextureCoords); - - for (int j = 0; j < 3; j++) - { - writer.Write(TextureMaps[j].TextureIndex); - writer.Write((ushort)0); - writer.Write((ushort)TextureMaps[j].MinFiler); - writer.Write((ushort)TextureMaps[j].MagFiler); - writer.Write((ushort)TextureMaps[j].WrapS); - writer.Write((ushort)TextureMaps[j].WrapT); - writer.Write(TextureMaps[j].MinLOD); - writer.Write(TextureMaps[j].LodBias); - writer.Write(TextureMaps[j].borderColorR); - writer.Write(TextureMaps[j].borderColorG); - writer.Write(TextureMaps[j].borderColorB); - writer.Write(TextureMaps[j].borderColorA); - } - - for (int j = 0; j < 3; j++) - { - writer.Write(TextureMaticies[j].Scale); - writer.Write(TextureMaticies[j].Rotate); - writer.Write(TextureMaticies[j].Translate); - writer.Write(TextureMaticies[j].MatrixMode); - writer.Write(TextureMaticies[j].ReferenceCamera); - writer.Write(TextureMaticies[j].MappingMethod); - writer.Write(TextureMaticies[j].CoordinateIndex); - } - - writer.Write(data); - } - - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append($"----------------------------------------------------\n"); - sb.Append($"AlphaTest {AlphaTestEnable} {AlphaTestFunction} {AlphaTestReference}\n"); - sb.Append($"DepthTest {DepthTestEnable} {DepthTestFunction} DepthWrite {DepthTestFunction}\n"); - - sb.Append($"BlendingFactorSrcRGB {BlendingFactorSrcRGB}\n"); - sb.Append($"BlendingFactorDestRGB {BlendingFactorDestRGB}\n"); - sb.Append($"BlendingFactorSrcAlpha {BlendingFactorSrcAlpha}\n"); - sb.Append($"BlendingFactorDestAlpha {BlendingFactorDestAlpha}\n"); - sb.Append($"BlendEnaled {BlendEnaled}\n"); - sb.Append($"----------------------------------------------------\n"); - - sb.AppendLine(); - - return sb.ToString(); - } - } - - public class TextureCombiner - { - public CombineResultOpDMP combineRGB; - public CombineResultOpDMP combineAlpha; - public CombineScaleDMP scaleRGB; - public CombineScaleDMP scaleAlpha; - public CombineBufferInputDMP bufferInputRGB; - public CombineBufferInputDMP bufferInputAlpha; - public CombineSourceDMP source0RGB; - public CombineSourceDMP source1RGB; - public CombineSourceDMP source2RGB; - public CombineOpDMP op0RGB; - public CombineOpDMP op1RGB; - public CombineOpDMP op2RGB; - public CombineSourceDMP source0Alpha; - public CombineSourceDMP source1Alpha; - public CombineSourceDMP source2Alpha; - - public CombineOpDMP op0Alpha; - public CombineOpDMP op1Alpha; - public CombineOpDMP op2Alpha; - public uint constantIndex; - - } - - public class TextureMatrix - { - public Syroot.Maths.Vector2F Scale { get; set; } - public Syroot.Maths.Vector2F Translate { get; set; } - public float Rotate { get; set; } - - public byte MatrixMode { get; set; } - public byte ReferenceCamera { get; set; } - public byte MappingMethod { get; set; } - public byte CoordinateIndex { get; set; } - } - - public class TextureMap - { - public short TextureIndex { get; set; } - public TextureFilter MinFiler { get; set; } - public TextureFilter MagFiler { get; set; } - public CMBTextureWrapMode WrapS { get; set; } - public CMBTextureWrapMode WrapT { get; set; } - public float MinLOD { get; set; } - public float LodBias { get; set; } - public byte borderColorR { get; set; } - public byte borderColorG { get; set; } - public byte borderColorB { get; set; } - public byte borderColorA { get; set; } - } - - public class TextureChunk : IChunkCommon - { - private const string Magic = "tex "; - - public List Textures = new List(); - - public void Read(FileReader reader, Header header) - { - reader.ReadSignature(4, Magic); - uint sectionSize = reader.ReadUInt32(); - uint TextureCount = reader.ReadUInt32(); - for (int i = 0; i < TextureCount; i++) - Textures.Add(new CTXB.Texture(reader)); - } - - public void Write(FileWriter writer, Header header) - { - long pos = writer.Position; - - writer.WriteSignature(Magic); - writer.Write(uint.MaxValue);//SectionSize - writer.Write(Textures.Count); - - for (int i = 0; i < Textures.Count; i++) - Textures[i].Write(writer); - - //Write the total file size - writer.WriteSectionSizeU32(pos + 4, pos, writer.Position); - } - } - - public static T ReadChunkSection(FileReader reader, Header header, long startPos = 0) - where T : IChunkCommon, new() - { - long pos = reader.Position; - - //Read offset and seek it - uint offset = reader.ReadUInt32(); - reader.SeekBegin(startPos + offset); - - //Create chunk instance - T chunk = new T(); - chunk.Read(reader, header); - - //Seek back and shift 4 from reading offset - reader.SeekBegin(pos + 0x4); - return chunk; - } - - public interface IChunkCommon - { - void Read(FileReader reader, Header header); - void Write(FileWriter writer, Header header); + if (index != -1 && index < cmb.TexturesChunk?.Textures?.Count) + return cmb.TexturesChunk.Textures[index].Name; + else + return ""; } } } diff --git a/File_Format_Library/FileFormats/Grezzo/CMB_Enums.cs b/File_Format_Library/FileFormats/Grezzo/CMB_Enums.cs deleted file mode 100644 index 7fa9477f..00000000 --- a/File_Format_Library/FileFormats/Grezzo/CMB_Enums.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Grezzo.CmbEnums -{ - //All enums from - //https://github.com/magcius/noclip.website/blob/master/src/oot3d/cmb.ts - public enum TextureFilter - { - NEAREST = 0x2600, - LINEAR = 0x2601, - NEAREST_MIPMAP_NEAREST = 0x2700, - LINEAR_MIPMAP_NEAREST = 0x2701, - NEAREST_MIPMAP_LINEAR = 0x2702, - LINEAR_MIPMAP_LINEAR = 0x2703, - } - - public enum SepdVertexAttribMode : ushort - { - ARRAY = 0, - CONSTANT = 1, - } - - public enum CmbDataType : ushort - { - Byte = 0x1400, - UByte = 0x1401, - Short = 0x1402, - UShort = 0x1403, - Int = 0x1404, - UInt = 0x1405, - Float = 0x1406, - } - - public enum CullMode : byte - { - NONE, - BACK, - FRONT, - FRONT_AND_BACK, - } - - public enum SkinningMode : ushort - { - SINGLE_BONE = 0x00, - RIGID_SKINNING = 0x01, - SMOOTH_SKINNING = 0x02, - } - - public enum CMBTextureWrapMode - { - CLAMP = 0x2900, - REPEAT = 0x2901, - CLAMP_TO_EDGE = 0x812F, - MIRRORED_REPEAT = 0x8370, - } - - public enum CombineResultOpDMP : ushort - { - REPLACE = 0x1E01, - MODULATE = 0x2100, - ADD = 0x0104, - ADD_SIGNED = 0x8574, - INTERPOLATE = 0x8575, - SUBTRACT = 0x84E7, - DOT3_RGB = 0x86AE, - DOT3_RGBA = 0x86AF, - MULT_ADD = 0x6401, - ADD_MULT = 0x6402, - }; - - public enum CombineScaleDMP : ushort - { - _1 = 0x01, - _2 = 0x02, - _4 = 0x04, - }; - - public enum CombineBufferInputDMP : ushort - { - PREVIOUS = 0x8578, - PREVIOUS_BUFFER = 0x8579, - }; - - public enum CombineSourceDMP : ushort - { - TEXTURE0 = 0x84C0, - TEXTURE1 = 0x84C1, - TEXTURE2 = 0x84C2, - TEXTURE3 = 0x84C3, - CONSTANT = 0x8576, - PRIMARY_COLOR = 0x8577, - PREVIOUS = 0x8578, - PREVIOUS_BUFFER = 0x8579, - FRAGMENT_PRIMARY_COLOR = 0x6210, - FRAGMENT_SECONDARY_COLOR = 0x6211, - }; - - public enum CombineOpDMP : ushort - { - SRC_COLOR = 0x0300, - ONE_MINUS_SRC_COLOR = 0x0301, - SRC_ALPHA = 0x0302, - ONE_MINUS_SRC_ALPHA = 0x0303, - SRC_R = 0x8580, - SRC_G = 0x8581, - SRC_B = 0x8582, - ONE_MINUS_SRC_R = 0x8583, - ONE_MINUS_SRC_G = 0x8584, - ONE_MINUS_SRC_B = 0x8585, - }; - - public enum FresnelSelector : ushort - { - No = 25280, - Pri = 25281, - Sec = 25282, - PriSec = 25283 - }; - - public enum LayerConfig - { - LayerConfig0 = 25264, - LayerConfig1 = 25265, - LayerConfig2 = 25266, - LayerConfig3 = 25267, - LayerConfig4 = 25268, - LayerConfig5 = 25269, - LayerConfig6 = 25270, - LayerConfig7 = 25271, - }; - - public enum LUTInput : ushort - { - CosNormalHalf = 25248, - CosViewHalf = 25249, - CosNormalView = 25250, - CosLightNormal = 25251, - CosLightSpot = 25252, - CosPhi = 25253 - } - - public enum StencilOp - { - Keep = 7680, - Zero = 0, - Replace = 7681, - Increment = 7682, - Decrement = 7683, - Invert = 5386, - IncrementWrap = 34055, - DecrementWrap = 34055 - } - - public enum BumpMode - { - NotUsed = 25288, - AsBump = 25289, - AsTangent = 25290//Doesn't exist in OoT3D - } -} diff --git a/File_Format_Library/FileFormats/Grezzo/CTXB.cs b/File_Format_Library/FileFormats/Grezzo/CTXB.cs index 11ea7ac3..fb6a4d78 100644 --- a/File_Format_Library/FileFormats/Grezzo/CTXB.cs +++ b/File_Format_Library/FileFormats/Grezzo/CTXB.cs @@ -299,7 +299,7 @@ namespace FirstPlugin writer.WriteString(Name, 16); } - private static Dictionary FormatList = + public static Dictionary FormatList = new Dictionary() { { TextureFormat.A8, CTR_3DS.PICASurfaceFormat.A8 }, diff --git a/File_Format_Library/FileFormats/HyruleWarriors/G1M/G1M.cs b/File_Format_Library/FileFormats/HyruleWarriors/G1M/G1M.cs index 6b65f2ea..f4e04cef 100644 --- a/File_Format_Library/FileFormats/HyruleWarriors/G1M/G1M.cs +++ b/File_Format_Library/FileFormats/HyruleWarriors/G1M/G1M.cs @@ -209,7 +209,7 @@ namespace HyruleWarriors.G1M { foreach (var mesh in Model.GenericMeshes) { - bool isSingleBind = false;; + bool isSingleBind = false; if (isSingleBind) { diff --git a/File_Format_Library/GL/CMB_Renderer.cs b/File_Format_Library/GL/CMB_Renderer.cs index 6532f2f3..d2db1b8f 100644 --- a/File_Format_Library/GL/CMB_Renderer.cs +++ b/File_Format_Library/GL/CMB_Renderer.cs @@ -9,7 +9,6 @@ using GL_EditorFramework.Interfaces; using OpenTK; using OpenTK.Graphics.OpenGL; using Toolbox.Library; -using Grezzo.CmbEnums; namespace FirstPlugin { @@ -67,7 +66,7 @@ namespace FirstPlugin for (int m = 0; m < Meshes.Count; m++) { - if (((CMB.CMBMaterialWrapper)Meshes[m].GetMaterial()).CMBMaterial.IsTransparent) + if (((CMB.CMBMaterialWrapper)Meshes[m].GetMaterial()).CMBMaterial.AlphaTest.Enabled) transparent.Add(Meshes[m]); else opaque.Add(Meshes[m]); @@ -91,35 +90,81 @@ namespace FirstPlugin var cmbMaterial = ((CMB.CMBMaterialWrapper)mat).CMBMaterial; var cmbMesh = ((CMB.CmbMeshWrapper)m); - bool HasNoNormals = cmbMesh.Shape.Normal.VertexData == null || cmbMesh.Shape.Normal.VertexData.Length == 0; + bool HasNoNormals = cmbMesh.Mesh.HasNormal == false; shader.SetBoolToInt("HasNoNormals", HasNoNormals); - shader.SetBoolToInt("isTransparent", cmbMaterial.BlendEnaled); + shader.SetBoolToInt("isTransparent", cmbMaterial.BlendEnabled); SetGLCullMode(cmbMaterial.CullMode); - GL.Enable(EnableCap.Blend); - GL.BlendFunc(cmbMaterial.BlendingFactorSrcAlpha, cmbMaterial.BlendingFactorDestAlpha); - GL.BlendColor(1.0f, 1.0f, 1.0f, cmbMaterial.BlendColorA); - if (cmbMaterial.AlphaTestEnable) + if (cmbMaterial.BlendEnabled) + { + GL.Enable(EnableCap.Blend); + GL.BlendColor(cmbMaterial.BlendColor.R / 255, cmbMaterial.BlendColor.G / 255, cmbMaterial.BlendColor.B / 255, cmbMaterial.BlendColor.A / 255); + GL.BlendFunc(ConvertBlendFunc(cmbMaterial.BlendFunction.AlphaSrcFunc), ConvertBlendFunc(cmbMaterial.BlendFunction.AlphaDstFunc)); + } + else + GL.Disable(EnableCap.Blend); + + if (cmbMaterial.AlphaTest.Enabled) + { GL.Enable(EnableCap.AlphaTest); + GL.AlphaFunc(ConvertTestFunction(cmbMaterial.AlphaTest.Function), cmbMaterial.AlphaTest.Reference / 255f); + } else GL.Disable(EnableCap.AlphaTest); - - GL.AlphaFunc(cmbMaterial.AlphaTestFunction, cmbMaterial.AlphaTestReference); } - private void SetGLCullMode(CullMode CullMode) + private AlphaFunction ConvertTestFunction(ZeldaLib.CtrModelBinary.Types.TestFunc func) + { + switch (func) + { + case ZeldaLib.CtrModelBinary.Types.TestFunc.Always: return AlphaFunction.Always; + case ZeldaLib.CtrModelBinary.Types.TestFunc.Equal: return AlphaFunction.Equal; + case ZeldaLib.CtrModelBinary.Types.TestFunc.Gequal: return AlphaFunction.Gequal; + case ZeldaLib.CtrModelBinary.Types.TestFunc.Greater: return AlphaFunction.Greater; + case ZeldaLib.CtrModelBinary.Types.TestFunc.Lequal: return AlphaFunction.Lequal; + case ZeldaLib.CtrModelBinary.Types.TestFunc.Less: return AlphaFunction.Less; + case ZeldaLib.CtrModelBinary.Types.TestFunc.Never: return AlphaFunction.Never; + case ZeldaLib.CtrModelBinary.Types.TestFunc.Notequal: return AlphaFunction.Notequal; + default: return AlphaFunction.Always; + } + } + + private BlendingFactor ConvertBlendFunc(ZeldaLib.CtrModelBinary.Types.BlendFunc factor) + { + switch (factor) + { + case ZeldaLib.CtrModelBinary.Types.BlendFunc.ConstantAlpha: return BlendingFactor.ConstantAlpha; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.ConstantColor: return BlendingFactor.ConstantColor; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.DestinationAlpha: return BlendingFactor.DstAlpha; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.DestinationColor: return BlendingFactor.DstColor; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.One: return BlendingFactor.One; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.OneMinusConstantAlpha: return BlendingFactor.OneMinusConstantAlpha; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.OneMinusConstantColor: return BlendingFactor.OneMinusConstantColor; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.OneMinusDestinationAlpha: return BlendingFactor.OneMinusDstAlpha; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.OneMinusDestinationColor: return BlendingFactor.OneMinusDstColor; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.OneMinusSourceAlpha: return BlendingFactor.OneMinusSrcAlpha; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.OneMinusSourceColor: return BlendingFactor.OneMinusSrcColor; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.SourceAlpha: return BlendingFactor.SrcAlpha; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.SourceColor: return BlendingFactor.SrcColor; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.SourceAlphaSaturate: return BlendingFactor.SrcAlphaSaturate; + case ZeldaLib.CtrModelBinary.Types.BlendFunc.Zero: return BlendingFactor.Zero; + default: return BlendingFactor.Zero; + } + } + + private void SetGLCullMode(ZeldaLib.CtrModelBinary.Types.CullMode CullMode) { GL.Enable(EnableCap.CullFace); - if (CullMode == CullMode.BACK) + if (CullMode == ZeldaLib.CtrModelBinary.Types.CullMode.Back) GL.CullFace(CullFaceMode.Back); - if (CullMode == CullMode.FRONT) + if (CullMode == ZeldaLib.CtrModelBinary.Types.CullMode.Front) GL.CullFace(CullFaceMode.Front); - if (CullMode == CullMode.FRONT_AND_BACK) + if (CullMode == ZeldaLib.CtrModelBinary.Types.CullMode.Both) GL.CullFace(CullFaceMode.FrontAndBack); - if (CullMode == CullMode.NONE) + if (CullMode == ZeldaLib.CtrModelBinary.Types.CullMode.None) GL.Disable(EnableCap.CullFace); }