Switch-Toolbox/File_Format_Library/FileFormats/Grezzo/CMB.cs

842 lines
40 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Toolbox.Library.Forms;
using Toolbox.Library;
using Toolbox.Library.IO;
using Toolbox.Library.Rendering;
using FirstPlugin.Forms;
using ZeldaLib.CtrModelBinary.Types;
using SPICA.Formats.CtrH3D.Model.Material;
using SPICA.PICA.Commands;
namespace FirstPlugin
{
public class CMB : TreeNodeFile, IFileFormat, IContextMenuNode, IExportableModel
{
public FileType FileType { get; set; } = FileType.Layout;
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "*CTR Model Binary" };
public string[] Extension { get; set; } = new string[] { "*.cmb" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new FileReader(stream, true))
{
return reader.CheckSignature(4, "cmb ");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public IEnumerable<STGenericObject> ExportableMeshes => Renderer.Meshes;
public IEnumerable<STGenericMaterial> ExportableMaterials => Materials;
public IEnumerable<STGenericTexture> ExportableTextures => Renderer.TextureList;
public STSkeleton ExportableSkeleton => Skeleton;
public ToolStripItem[] GetContextMenuItems()
{
List<ToolStripItem> Items = new List<ToolStripItem>();
Items.Add(new ToolStripMenuItem("Save", null, SaveAction, Keys.Control | Keys.S));
return Items.ToArray();
}
private void SaveAction(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = Utils.GetAllFilters(this);
sfd.FileName = FileName;
if (sfd.ShowDialog() == DialogResult.OK)
{
STFileSaver.SaveFileFormat(this, sfd.FileName);
}
}
bool DrawablesLoaded = false;
public override void OnClick(TreeView treeView)
{
LoadEditor<STPropertyGrid>();
}
public T LoadEditor<T>() where T : UserControl, new()
{
ViewportEditor editor = (ViewportEditor)LibraryGUI.GetActiveContent(typeof(ViewportEditor));
if (editor == null)
{
editor = new ViewportEditor(true);
editor.Dock = DockStyle.Fill;
LibraryGUI.LoadEditor(editor);
}
if (!DrawablesLoaded)
{
ObjectEditor.AddContainer(DrawableContainer);
DrawablesLoaded = true;
}
if (Runtime.UseOpenGL)
editor.LoadViewport(DrawableContainer);
foreach (var subControl in editor.GetEditorPanel().Controls)
if (subControl.GetType() == typeof(T))
return subControl as T;
T control = new T();
control.Dock = DockStyle.Fill;
editor.LoadEditor(control);
return control;
}
public CMB_Renderer Renderer;
public DrawableContainer DrawableContainer = new DrawableContainer();
List<STGenericMaterial> Materials = new List<STGenericMaterial>();
public ZeldaLib.CtrModelBinary.CMB cmb = new ZeldaLib.CtrModelBinary.CMB();
STTextureFolder texFolder;
public STSkeleton Skeleton;
public void Load(System.IO.Stream stream)
{
CanSave = false;
Renderer = new CMB_Renderer();
DrawableContainer.Drawables.Add(Renderer);
Skeleton = new STSkeleton();
//These models/skeletons come out massive so scale them with an overridden scale
Skeleton.PreviewScale = Renderer.PreviewScale;
Skeleton.BonePointScale = 40;
Renderer.Skeleton = Skeleton;
DrawableContainer.Drawables.Add(Skeleton);
cmb.ReadCMB(stream);
Text = cmb.Header.Name;
DrawableContainer.Name = Text;
//Load textures
if (cmb.TexturesChunk != null)
{
texFolder = new TextureFolder("Texture");
TreeNode meshFolder = new TreeNode("Meshes");
TreeNode materialFolder = new TreeNode("Materials");
TreeNode skeletonFolder = new TreeNode("Skeleton");
bool HasTextures = cmb.TexturesChunk.Textures != null &&
cmb.TexturesChunk.Textures.Count != 0;
bool HasMeshes = cmb.MeshesChunk.SHP.SEPDs != null &&
cmb.MeshesChunk.SHP.SEPDs.Count != 0;
bool HasSkeleton = cmb.SkeletonChunk != null &&
cmb.SkeletonChunk.Bones.Count != 0;
bool HasMaterials = cmb.MaterialsChunk != null &&
cmb.MaterialsChunk.Materials.Count != 0;
if (HasSkeleton)
{
var bonesOrdered = cmb.SkeletonChunk.Bones.OrderBy(x => x.ID).ToList();
foreach (var bone in bonesOrdered)
{
STBone genericBone = new STBone(Skeleton);
genericBone.parentIndex = bone.ParentID;
genericBone.Checked = true;
genericBone.Text = $"Bone {bone.ID}";
genericBone.RotationType = STBone.BoneRotationType.Euler;
genericBone.Position = new OpenTK.Vector3(
bone.Translation.X,
bone.Translation.Y,
bone.Translation.Z
);
genericBone.EulerRotation = new OpenTK.Vector3(
bone.Rotation.X,
bone.Rotation.Y,
bone.Rotation.Z
);
genericBone.Scale = new OpenTK.Vector3(
bone.Scale.X,
bone.Scale.Y,
bone.Scale.Z
);
Skeleton.bones.Add(genericBone);
}
foreach (var bone in Skeleton.bones)
{
if (bone.Parent == null)
skeletonFolder.Nodes.Add(bone);
}
Skeleton.reset();
Skeleton.update();
}
if (HasTextures)
{
int texIndex = 0;
foreach (var tex in cmb.TexturesChunk.Textures)
{
var texWrapper = new CTXB.TextureWrapper(new CTXB.Texture());
texWrapper.Text = $"Texture {texIndex++}";
texWrapper.ImageKey = "texture";
texWrapper.SelectedImageKey = texWrapper.ImageKey;
if (tex.Name != string.Empty)
texWrapper.Text = tex.Name;
texWrapper.Width = tex.Width;
texWrapper.Height = tex.Height;
CTXB.Texture.TextureFormat Format = (CTXB.Texture.TextureFormat)((tex.DataType << 16) | tex.ImageFormat);
texWrapper.Format = CTR_3DS.ConvertPICAToGenericFormat(CTXB.Texture.FormatList[Format]);
texWrapper.ImageData = tex.ImageData;
texFolder.Nodes.Add(texWrapper);
Renderer.TextureList.Add(texWrapper);
}
}
if (HasMaterials)
{
int materialIndex = 0;
foreach (var mat in cmb.MaterialsChunk.Materials)
{
H3DMaterial H3D = ToH3DMaterial(mat);
CMBMaterialWrapper material = new CMBMaterialWrapper(mat, this, H3D);
material.Text = $"Material {materialIndex++}";
materialFolder.Nodes.Add(material);
Materials.Add(material);
bool HasDiffuse = false;
foreach (var tex in mat.TextureMappers)
{
if (tex.TextureID != -1)
{
CMBTextureMapWrapper matTexture = new CMBTextureMapWrapper(tex, this);
matTexture.TextureIndex = tex.TextureID;
material.TextureMaps.Add(matTexture);
if (tex.TextureID < Renderer.TextureList.Count && tex.TextureID >= 0)
{
matTexture.Name = Renderer.TextureList[tex.TextureID].Text;
material.Nodes.Add(matTexture.Name);
}
if (!HasDiffuse && matTexture.Name != "bg_syadowmap") //Quick hack till i do texture env stuff
{
matTexture.Type = STGenericMatTexture.TextureType.Diffuse;
HasDiffuse = true;
}
}
}
}
}
if (HasMeshes)
{
int MeshIndex = 0;
foreach (var mesh in cmb.MeshesChunk.MSHS.Meshes)
{
STGenericMaterial mat = Materials[mesh.MaterialIndex];
CmbMeshWrapper genericMesh = new CmbMeshWrapper(mat);
genericMesh.Text = $"Mesh_{MeshIndex++}_ID_{mesh.VisIndex}";
genericMesh.MaterialIndex = mesh.MaterialIndex;
var shape = cmb.MeshesChunk.SHP.SEPDs[mesh.SEPDIndex];
genericMesh.Mesh = shape;
List<ushort> SkinnedBoneTable = new List<ushort>();
foreach (var prim in shape.PRMS)
{
if (prim.BoneIndices != null) {
SkinnedBoneTable.AddRange(prim.BoneIndices);
}
}
//Now load the vertex and face data
foreach (var prm in shape.PRMS)
{
if (shape.HasPosition)
{
int VertexCount = prm.VertexCount;
for (int v = 0; v < VertexCount; v++)
{
Vertex vert = new Vertex();
vert.pos = new OpenTK.Vector3(
prm.Vertices.Position[v].X,
prm.Vertices.Position[v].Y,
prm.Vertices.Position[v].Z);
if(shape.HasNormal)
{
vert.nrm = new OpenTK.Vector3(
prm.Vertices.Normal[v].X,
prm.Vertices.Normal[v].Y,
prm.Vertices.Normal[v].Z).Normalized();
}
if (shape.HasColor)
{
vert.col = new OpenTK.Vector4(
prm.Vertices.Color[v].X,
prm.Vertices.Color[v].Y,
prm.Vertices.Color[v].Z,
prm.Vertices.Color[v].W).Normalized();
}
if (shape.HasUV0){
vert.uv0 = new OpenTK.Vector2(prm.Vertices.UV0[v].X, -prm.Vertices.UV0[v].Y + 1);
}
if (shape.HasUV1){
vert.uv1 = new OpenTK.Vector2(prm.Vertices.UV1[v].X, -prm.Vertices.UV1[v].Y + 1);
}
if (shape.HasUV2){
vert.uv2 = new OpenTK.Vector2(prm.Vertices.UV2[v].X, -prm.Vertices.UV2[v].Y + 1);
}
if (prm.SkinningMode == SkinningMode.Smooth)
{
//Indices
if (shape.HasIndices)
{
if (shape.BoneDimensionCount >= 1)
vert.boneIds.Add((int)prm.Vertices.BoneIndices[v].X);
if (shape.BoneDimensionCount >= 2)
vert.boneIds.Add((int)prm.Vertices.BoneIndices[v].Y);
if (shape.BoneDimensionCount >= 3)
vert.boneIds.Add((int)prm.Vertices.BoneIndices[v].Z);
if (shape.BoneDimensionCount >= 4)
vert.boneIds.Add((int)prm.Vertices.BoneIndices[v].W);
}
//Weights
if(shape.HasWeights)
{
if (shape.BoneDimensionCount >= 1)
vert.boneWeights.Add(prm.Vertices.BoneWeights[v].X);
if (shape.BoneDimensionCount >= 2)
vert.boneWeights.Add(prm.Vertices.BoneWeights[v].Y);
if (shape.BoneDimensionCount >= 3)
vert.boneWeights.Add(prm.Vertices.BoneWeights[v].Z);
if (shape.BoneDimensionCount >= 4)
vert.boneWeights.Add(prm.Vertices.BoneWeights[v].W);
}
}
if (prm.SkinningMode == SkinningMode.Rigid)
{
int boneId = (int)prm.Vertices.BoneIndices[v].X;
vert.boneIds.Add(boneId);
vert.boneWeights.Add(1);
vert.pos = OpenTK.Vector3.TransformPosition(vert.pos, Skeleton.bones[boneId].Transform);
if(shape.HasNormal)
vert.nrm = OpenTK.Vector3.TransformNormal(vert.nrm, Skeleton.bones[boneId].Transform);
}
if (prm.SkinningMode == SkinningMode.Mixed)
{
int boneId = prm.BoneIndices[0];
vert.boneIds.Add(boneId);
vert.boneWeights.Add(1);
vert.pos = OpenTK.Vector3.TransformPosition(vert.pos, Skeleton.bones[boneId].Transform);
if (shape.HasNormal)
vert.nrm = OpenTK.Vector3.TransformNormal(vert.nrm, Skeleton.bones[boneId].Transform);
}
genericMesh.vertices.Add(vert);
}
}
STGenericPolygonGroup group = new STGenericPolygonGroup();
genericMesh.PolygonGroups.Add(group);
for (int i = 0; i < prm.FaceIndices.Count; i++)
{
group.faces.Add((int)prm.FaceIndices[i].X);
group.faces.Add((int)prm.FaceIndices[i].Y);
group.faces.Add((int)prm.FaceIndices[i].Z);
}
}
Renderer.Meshes.Add(genericMesh);
meshFolder.Nodes.Add(genericMesh);
}
}
if (meshFolder.Nodes.Count > 0)
Nodes.Add(meshFolder);
if (skeletonFolder.Nodes.Count > 0)
Nodes.Add(skeletonFolder);
if (materialFolder.Nodes.Count > 0)
Nodes.Add(materialFolder);
if (texFolder.Nodes.Count > 0)
Nodes.Add(texFolder);
}
}
public void Unload()
{
}
public void Save(System.IO.Stream stream)
{
var f = new FileWriter(stream);
f.Write(cmb.WriteFile("", cmb, false).ToArray());
}
public enum CMBVersion
{
OOT3DS,
MM3DS,
LM3DS,
}
public class CMBMaterialWrapper : CtrLibrary.H3DMaterialWrapper
{
private CMB ParentCMB;
public Material CMBMaterial { get; set; }
public override List<STGenericObject> FindMappedMeshes()
{
List<STGenericObject> meshes = new List<STGenericObject>();
foreach (var mesh in ParentCMB.Renderer.Meshes)
if (mesh.GetMaterial() == this)
meshes.Add(mesh);
return meshes;
}
public CMBMaterialWrapper(Material material, CMB cmb, H3DMaterial h3D) : base(h3D)
{
ParentCMB = cmb;
CMBMaterial = material;
}
public override void OnClick(TreeView treeView)
{
var editor = ParentCMB.LoadEditor<CtrLibrary.Forms.BCHMaterialEditor>();
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);*/
}
}
public class CMBTextureMapWrapper : STGenericMatTexture
{
public CMB CMBParent;
public int TextureIndex { get; set; }
public TextureMapper TextureMapData;
public override STGenericTexture GetTexture()
{
foreach (var tex in CMBParent.Renderer.TextureList)
if (tex.Text == this.Name)
return tex;
return null;
}
public CMBTextureMapWrapper(TextureMapper texMap, CMB cmb)
{
CMBParent = cmb;
TextureMapData = texMap;
this.WrapModeS = ConvertWrapMode(TextureMapData.WrapU);
this.WrapModeT = ConvertWrapMode(TextureMapData.WrapV);
this.MinFilter = ConvertMinFilterMode(TextureMapData.TextureMinFilter);
this.MagFilter = ConvertMagFilterMode(TextureMapData.TextureMagFilter);
}
private STTextureMinFilter ConvertMinFilterMode(ZeldaLib.CtrModelBinary.Types.TextureMinFilter PicaFilterMode)
{
switch (PicaFilterMode)
{
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(ZeldaLib.CtrModelBinary.Types.TextureMagFilter PicaFilterMode)
{
switch (PicaFilterMode)
{
case ZeldaLib.CtrModelBinary.Types.TextureMagFilter.Linear: return STTextureMagFilter.Linear;
case ZeldaLib.CtrModelBinary.Types.TextureMagFilter.Nearest: return STTextureMagFilter.Nearest;
default: return 0;
}
}
private STTextureWrapMode ConvertWrapMode(TextureWrap PicaWrapMode)
{
switch (PicaWrapMode)
{
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;
}
}
}
public class CmbMeshWrapper : GenericRenderedObject
{
public ZeldaLib.CtrModelBinary.CMB_SEPD Mesh { get; set; }
STGenericMaterial material;
public CmbMeshWrapper(STGenericMaterial mat) {
material = mat;
}
public override STGenericMaterial GetMaterial()
{
return material;
}
}
private class TextureFolder : STTextureFolder, ITextureContainer
{
public bool DisplayIcons => true;
public List<STGenericTexture> TextureList
{
get
{
List<STGenericTexture> textures = new List<STGenericTexture>();
foreach (STGenericTexture node in Nodes)
textures.Add(node);
return textures;
}
set { }
}
public TextureFolder(string text) : base(text)
{
}
}
public H3DMaterial ToH3DMaterial(Material mat)
{
H3DMaterial h3dMaterial = new H3DMaterial();
var matParams = h3dMaterial.MaterialParams;
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;
switch (mat.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 < mat.TextureMappers?.Count; i++)
{
string texture = GetTextureName(mat.TextureMappers[i].TextureID);
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(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<TextureCombinerMode, PICATextureCombinerMode> ConvertConvertCombiner =
new Dictionary<TextureCombinerMode, PICATextureCombinerMode>()
{
{ 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<TextureCombinerSource, PICATextureCombinerSource> ConvertCombinerSrc =
new Dictionary<TextureCombinerSource, PICATextureCombinerSource>()
{
{ 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<TextureCombinerAlphaOp, PICATextureCombinerAlphaOp> ConvertConvertCombinerAlphaOp =
new Dictionary<TextureCombinerAlphaOp, PICATextureCombinerAlphaOp>()
{
{ 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<TextureCombinerColorOp, PICATextureCombinerColorOp> ConvertConvertCombinerColorOp =
new Dictionary<TextureCombinerColorOp, PICATextureCombinerColorOp>()
{
{ 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<TextureCombinerScale, PICATextureCombinerScale> ConvertScale =
new Dictionary<TextureCombinerScale, PICATextureCombinerScale>()
{
{ 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;
}
}
private PICATestFunc ConvertTestFunction(TestFunc func)
{
switch (func)
{
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;
}
}
private SPICA.Math3D.RGBA ConvertRGBA(RGBA color)
{
return new SPICA.Math3D.RGBA(color.R, color.G, color.B, color.A);
}
private H3DTextureMagFilter ConvertTexMagFilter(ZeldaLib.CtrModelBinary.Types.TextureMagFilter filterMode)
{
switch (filterMode)
{
case ZeldaLib.CtrModelBinary.Types.TextureMagFilter.Linear: return H3DTextureMagFilter.Linear;
case ZeldaLib.CtrModelBinary.Types.TextureMagFilter.Nearest: return H3DTextureMagFilter.Nearest;
default: return H3DTextureMagFilter.Linear;
}
}
private H3DTextureMinFilter ConvertTexMinFilter(ZeldaLib.CtrModelBinary.Types.TextureMinFilter filterMode)
{
switch (filterMode)
{
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;
}
}
private PICATextureWrap ConvertWrapMode(TextureWrap wrapMode)
{
switch (wrapMode)
{
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;
}
}
private string GetTextureName(int index)
{
if (index != -1 && index < cmb.TexturesChunk?.Textures?.Count)
return cmb.TexturesChunk.Textures[index].Name;
else
return "";
}
}
}