Add MKAGPDX model viewing and exporting
This commit is contained in:
parent
a076fc6f92
commit
54c4bac8bc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -27,6 +27,9 @@ namespace Bfres.Structs
|
||||
public List<FSHP> shapes = new List<FSHP>();
|
||||
public List<FSHP> depthSortedMeshes = new List<FSHP>();
|
||||
|
||||
public override IEnumerable<STGenericObject> Objects => shapes;
|
||||
public override IEnumerable<STGenericMaterial> Materials => materials.Values.ToList();
|
||||
|
||||
public Dictionary<string, FMAT> materials = new Dictionary<string, FMAT>();
|
||||
public Model Model;
|
||||
public ResU.Model ModelU;
|
||||
|
@ -1,13 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Switch_Toolbox;
|
||||
using System.Windows.Forms;
|
||||
using Switch_Toolbox.Library;
|
||||
using Switch_Toolbox.Library.IO;
|
||||
using Switch_Toolbox.Library.Forms;
|
||||
using Switch_Toolbox.Library.Rendering;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using GL_EditorFramework.Interfaces;
|
||||
using GL_EditorFramework.GL_Core;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
@ -17,7 +22,7 @@ namespace FirstPlugin
|
||||
|
||||
public bool CanSave { get; set; }
|
||||
public string[] Description { get; set; } = new string[] { "Mario Kart Arcade GP DX" };
|
||||
public string[] Extension { get; set; } = new string[] { "*.bin" };
|
||||
public string[] Extension { get; set; } = new string[] { "*.bin", "*.mot" };
|
||||
public string FileName { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
public IFileInfo IFileInfo { get; set; }
|
||||
@ -41,11 +46,41 @@ namespace FirstPlugin
|
||||
|
||||
Header header;
|
||||
|
||||
public DrawableContainer DrawableContainer = new DrawableContainer();
|
||||
|
||||
public void Load(System.IO.Stream stream)
|
||||
{
|
||||
DrawableContainer.Name = FileName;
|
||||
|
||||
Text = FileName;
|
||||
header = new Header();
|
||||
header.Read(new FileReader(stream), this);
|
||||
|
||||
ContextMenuStrip = new STContextMenuStrip();
|
||||
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Export Model", null, ExportModel, Keys.Control | Keys.E));
|
||||
}
|
||||
|
||||
private void ExportModel(object sender, EventArgs args)
|
||||
{
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.Filter = "Supported Formats|*.dae;";
|
||||
if (sfd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
AssimpSaver assimp = new AssimpSaver();
|
||||
ExportModelSettings settings = new ExportModelSettings();
|
||||
|
||||
List<STGenericMaterial> Materials = new List<STGenericMaterial>();
|
||||
foreach (STGenericMaterial mat in Nodes[0].Nodes)
|
||||
Materials.Add(mat);
|
||||
|
||||
var model = new STGenericModel();
|
||||
model.Materials = Materials;
|
||||
model.Objects = ((Renderer)DrawableContainer.Drawables[1]).Meshes;
|
||||
|
||||
assimp.SaveFromModel(model, sfd.FileName, new List<STGenericTexture>(), ((STSkeleton)DrawableContainer.Drawables[0]));
|
||||
}
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
|
||||
@ -55,6 +90,340 @@ namespace FirstPlugin
|
||||
return null;
|
||||
}
|
||||
|
||||
public struct DisplayVertex
|
||||
{
|
||||
// Used for rendering.
|
||||
public Vector3 pos;
|
||||
public Vector3 nrm;
|
||||
public Vector3 tan;
|
||||
public Vector2 uv;
|
||||
public Vector4 col;
|
||||
public Vector4 node;
|
||||
public Vector4 weight;
|
||||
public Vector2 uv2;
|
||||
public Vector2 uv3;
|
||||
|
||||
public static int Size = 4 * (3 + 3 + 3 + 2 + 4 + 4 + 4 + 2 + 2);
|
||||
}
|
||||
|
||||
|
||||
public class MeshWrapper : STGenericObject
|
||||
{
|
||||
public int[] display;
|
||||
public int DisplayId;
|
||||
|
||||
public List<DisplayVertex> CreateDisplayVertices()
|
||||
{
|
||||
display = lodMeshes[DisplayLODIndex].getDisplayFace().ToArray();
|
||||
|
||||
List<DisplayVertex> displayVertList = new List<DisplayVertex>();
|
||||
|
||||
if (lodMeshes[DisplayLODIndex].faces.Count <= 3)
|
||||
return displayVertList;
|
||||
|
||||
foreach (Vertex v in vertices)
|
||||
{
|
||||
DisplayVertex displayVert = new DisplayVertex()
|
||||
{
|
||||
pos = v.pos,
|
||||
nrm = v.nrm,
|
||||
tan = v.tan.Xyz,
|
||||
col = v.col,
|
||||
uv = v.uv0,
|
||||
uv2 = v.uv1,
|
||||
uv3 = v.uv2,
|
||||
node = new Vector4(
|
||||
v.boneIds.Count > 0 ? v.boneIds[0] : -1,
|
||||
v.boneIds.Count > 1 ? v.boneIds[1] : -1,
|
||||
v.boneIds.Count > 2 ? v.boneIds[2] : -1,
|
||||
v.boneIds.Count > 3 ? v.boneIds[3] : -1),
|
||||
weight = new Vector4(
|
||||
v.boneWeights.Count > 0 ? v.boneWeights[0] : 0,
|
||||
v.boneWeights.Count > 1 ? v.boneWeights[1] : 0,
|
||||
v.boneWeights.Count > 2 ? v.boneWeights[2] : 0,
|
||||
v.boneWeights.Count > 3 ? v.boneWeights[3] : 0),
|
||||
};
|
||||
|
||||
displayVertList.Add(displayVert);
|
||||
|
||||
/* Console.WriteLine($"---------------------------------------------------------------------------------------");
|
||||
Console.WriteLine($"Position {displayVert.pos.X} {displayVert.pos.Y} {displayVert.pos.Z}");
|
||||
Console.WriteLine($"Normal {displayVert.nrm.X} {displayVert.nrm.Y} {displayVert.nrm.Z}");
|
||||
Console.WriteLine($"Tanget {displayVert.tan.X} {displayVert.tan.Y} {displayVert.tan.Z}");
|
||||
Console.WriteLine($"Color {displayVert.col.X} {displayVert.col.Y} {displayVert.col.Z} {displayVert.col.W}");
|
||||
Console.WriteLine($"UV Layer 1 {displayVert.uv.X} {displayVert.uv.Y}");
|
||||
Console.WriteLine($"UV Layer 2 {displayVert.uv2.X} {displayVert.uv2.Y}");
|
||||
Console.WriteLine($"UV Layer 3 {displayVert.uv3.X} {displayVert.uv3.Y}");
|
||||
Console.WriteLine($"Bone Index {displayVert.node.X} {displayVert.node.Y} {displayVert.node.Z} {displayVert.node.W}");
|
||||
Console.WriteLine($"Weights {displayVert.weight.X} {displayVert.weight.Y} {displayVert.weight.Z} {displayVert.weight.W}");
|
||||
Console.WriteLine($"---------------------------------------------------------------------------------------");*/
|
||||
}
|
||||
|
||||
return displayVertList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class Renderer : AbstractGlDrawable
|
||||
{
|
||||
public Vector3 Max = new Vector3(0);
|
||||
public Vector3 Min = new Vector3(0);
|
||||
|
||||
public List<ushort> SelectedTypes = new List<ushort>();
|
||||
|
||||
public Vector3 position = new Vector3(0, 0, 0);
|
||||
|
||||
protected bool Selected = false;
|
||||
protected bool Hovered = false;
|
||||
|
||||
// public override bool IsSelected() => Selected;
|
||||
// public override bool IsSelected(int partIndex) => Selected;
|
||||
|
||||
public bool IsHovered() => Selected;
|
||||
|
||||
// gl buffer objects
|
||||
int vbo_position;
|
||||
int ibo_elements;
|
||||
|
||||
public List<MeshWrapper> Meshes = new List<MeshWrapper>();
|
||||
|
||||
private void GenerateBuffers()
|
||||
{
|
||||
GL.GenBuffers(1, out vbo_position);
|
||||
GL.GenBuffers(1, out ibo_elements);
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
GL.DeleteBuffer(vbo_position);
|
||||
GL.DeleteBuffer(ibo_elements);
|
||||
}
|
||||
|
||||
public void UpdateVertexData()
|
||||
{
|
||||
if (!Runtime.OpenTKInitialized)
|
||||
return;
|
||||
|
||||
DisplayVertex[] Vertices;
|
||||
int[] Faces;
|
||||
|
||||
int poffset = 0;
|
||||
int voffset = 0;
|
||||
List<DisplayVertex> Vs = new List<DisplayVertex>();
|
||||
List<int> Ds = new List<int>();
|
||||
foreach (var m in Meshes)
|
||||
{
|
||||
m.Offset = poffset * 4;
|
||||
List<DisplayVertex> pv = m.CreateDisplayVertices();
|
||||
Vs.AddRange(pv);
|
||||
|
||||
for (int i = 0; i < m.lodMeshes[m.DisplayLODIndex].displayFaceSize; i++)
|
||||
{
|
||||
Ds.Add(m.display[i] + voffset);
|
||||
}
|
||||
poffset += m.lodMeshes[m.DisplayLODIndex].displayFaceSize;
|
||||
voffset += pv.Count;
|
||||
}
|
||||
|
||||
// Binds
|
||||
Vertices = Vs.ToArray();
|
||||
Faces = Ds.ToArray();
|
||||
|
||||
// Bind only once!
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
|
||||
GL.BufferData<DisplayVertex>(BufferTarget.ArrayBuffer, (IntPtr)(Vertices.Length * DisplayVertex.Size), Vertices, BufferUsageHint.StaticDraw);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
|
||||
GL.BufferData<int>(BufferTarget.ElementArrayBuffer, (IntPtr)(Faces.Length * sizeof(int)), Faces, BufferUsageHint.StaticDraw);
|
||||
|
||||
LibraryGUI.Instance.UpdateViewport();
|
||||
}
|
||||
|
||||
public ShaderProgram defaultShaderProgram;
|
||||
|
||||
public override void Prepare(GL_ControlModern control)
|
||||
{
|
||||
string pathFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "MKAGPDX") + "\\MKAGPDX_Model.frag";
|
||||
string pathVert = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "MKAGPDX") + "\\MKAGPDX_Model.vert";
|
||||
|
||||
var defaultFrag = new FragmentShader(File.ReadAllText(pathFrag));
|
||||
var defaultVert = new VertexShader(File.ReadAllText(pathVert));
|
||||
|
||||
defaultShaderProgram = new ShaderProgram(defaultFrag, defaultVert);
|
||||
}
|
||||
|
||||
public override void Prepare(GL_ControlLegacy control)
|
||||
{
|
||||
}
|
||||
|
||||
private void CheckBuffers()
|
||||
{
|
||||
if (!Runtime.OpenTKInitialized)
|
||||
return;
|
||||
|
||||
bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0;
|
||||
if (!buffersWereInitialized)
|
||||
{
|
||||
GenerateBuffers();
|
||||
UpdateVertexData();
|
||||
}
|
||||
}
|
||||
public override void Draw(GL_ControlLegacy control, Pass pass)
|
||||
{
|
||||
CheckBuffers();
|
||||
|
||||
if (!Runtime.OpenTKInitialized)
|
||||
return;
|
||||
}
|
||||
|
||||
public override void Draw(GL_ControlModern control, Pass pass)
|
||||
{
|
||||
CheckBuffers();
|
||||
|
||||
if (!Runtime.OpenTKInitialized)
|
||||
return;
|
||||
|
||||
control.CurrentShader = defaultShaderProgram;
|
||||
SetRenderSettings(defaultShaderProgram);
|
||||
|
||||
Matrix4 camMat = control.ModelMatrix * control.CameraMatrix * control.ProjectionMatrix;
|
||||
|
||||
GL.Disable(EnableCap.CullFace);
|
||||
|
||||
GL.Uniform3(defaultShaderProgram["difLightDirection"], Vector3.TransformNormal(new Vector3(0f, 0f, -1f), camMat.Inverted()).Normalized());
|
||||
GL.Uniform3(defaultShaderProgram["difLightColor"], new Vector3(1));
|
||||
GL.Uniform3(defaultShaderProgram["ambLightColor"], new Vector3(1));
|
||||
|
||||
defaultShaderProgram.EnableVertexAttributes();
|
||||
|
||||
foreach (var mdl in Meshes)
|
||||
{
|
||||
DrawModel(mdl, defaultShaderProgram);
|
||||
}
|
||||
|
||||
defaultShaderProgram.DisableVertexAttributes();
|
||||
|
||||
GL.UseProgram(0);
|
||||
GL.Disable(EnableCap.DepthTest);
|
||||
GL.Enable(EnableCap.DepthTest);
|
||||
GL.Enable(EnableCap.CullFace);
|
||||
}
|
||||
private void SetRenderSettings(ShaderProgram shader)
|
||||
{
|
||||
shader.SetBoolToInt("renderVertColor", Runtime.renderVertColor);
|
||||
GL.Uniform1(defaultShaderProgram["renderType"], (int)Runtime.viewportShading);
|
||||
|
||||
}
|
||||
private void DrawModel(MeshWrapper m, ShaderProgram shader, bool drawSelection = false)
|
||||
{
|
||||
if (m.lodMeshes[m.DisplayLODIndex].faces.Count <= 3)
|
||||
return;
|
||||
|
||||
SetVertexAttributes(m, shader);
|
||||
|
||||
if (m.Checked)
|
||||
{
|
||||
if ((m.IsSelected))
|
||||
{
|
||||
DrawModelSelection(m, shader);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Runtime.RenderModelWireframe)
|
||||
{
|
||||
DrawModelWireframe(m, shader);
|
||||
}
|
||||
|
||||
if (Runtime.RenderModels)
|
||||
{
|
||||
GL.DrawElements(PrimitiveType.Triangles, m.lodMeshes[m.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, m.Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void DrawModelSelection(MeshWrapper p, ShaderProgram shader)
|
||||
{
|
||||
//This part needs to be reworked for proper outline. Currently would make model disappear
|
||||
|
||||
GL.DrawElements(PrimitiveType.Triangles, p.lodMeshes[p.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
|
||||
|
||||
GL.Enable(EnableCap.StencilTest);
|
||||
// use vertex color for wireframe color
|
||||
GL.Uniform1(shader["colorOverride"], 1);
|
||||
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
|
||||
GL.Enable(EnableCap.LineSmooth);
|
||||
GL.LineWidth(1.5f);
|
||||
GL.DrawElements(PrimitiveType.Triangles, p.lodMeshes[p.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
|
||||
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
|
||||
GL.Uniform1(shader["colorOverride"], 0);
|
||||
|
||||
GL.Enable(EnableCap.DepthTest);
|
||||
}
|
||||
private void SetVertexAttributes(MeshWrapper m, ShaderProgram shader)
|
||||
{
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
|
||||
GL.VertexAttribPointer(shader.GetAttribute("vPosition"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 0); //+12
|
||||
GL.VertexAttribPointer(shader.GetAttribute("vNormal"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 12); //+12
|
||||
GL.VertexAttribPointer(shader.GetAttribute("vTangent"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 24); //+12
|
||||
GL.VertexAttribPointer(shader.GetAttribute("vUV0"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 36); //+8
|
||||
GL.VertexAttribPointer(shader.GetAttribute("vColor"), 4, VertexAttribPointerType.Float, false, DisplayVertex.Size, 44); //+16
|
||||
GL.VertexAttribIPointer(shader.GetAttribute("vBone"), 4, VertexAttribIntegerType.Int, DisplayVertex.Size, new IntPtr(60)); //+16
|
||||
GL.VertexAttribPointer(shader.GetAttribute("vWeight"), 4, VertexAttribPointerType.Float, false, DisplayVertex.Size, 76);//+16
|
||||
GL.VertexAttribPointer(shader.GetAttribute("vUV1"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 92);//+8
|
||||
GL.VertexAttribPointer(shader.GetAttribute("vUV2"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 100);//+8
|
||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
|
||||
}
|
||||
private static void DrawModelWireframe(MeshWrapper p, ShaderProgram shader)
|
||||
{
|
||||
// use vertex color for wireframe color
|
||||
GL.Uniform1(shader["colorOverride"], 1);
|
||||
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
|
||||
GL.Enable(EnableCap.LineSmooth);
|
||||
GL.LineWidth(1.5f);
|
||||
GL.DrawElements(PrimitiveType.Triangles, p.lodMeshes[p.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
|
||||
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
|
||||
GL.Uniform1(shader["colorOverride"], 0);
|
||||
}
|
||||
}
|
||||
|
||||
Viewport viewport
|
||||
{
|
||||
get
|
||||
{
|
||||
var editor = LibraryGUI.Instance.GetObjectEditor();
|
||||
return editor.GetViewport();
|
||||
}
|
||||
set
|
||||
{
|
||||
var editor = LibraryGUI.Instance.GetObjectEditor();
|
||||
editor.LoadViewport(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawablesLoaded = false;
|
||||
public override void OnClick(TreeView treeView)
|
||||
{
|
||||
if (Runtime.UseOpenGL)
|
||||
{
|
||||
if (viewport == null)
|
||||
{
|
||||
viewport = new Viewport(ObjectEditor.GetDrawableContainers());
|
||||
viewport.Dock = DockStyle.Fill;
|
||||
}
|
||||
|
||||
if (!DrawablesLoaded)
|
||||
{
|
||||
ObjectEditor.AddContainer(DrawableContainer);
|
||||
DrawablesLoaded = true;
|
||||
}
|
||||
|
||||
viewport.ReloadDrawables(DrawableContainer);
|
||||
LibraryGUI.Instance.LoadEditor(viewport);
|
||||
|
||||
viewport.Text = Text;
|
||||
}
|
||||
}
|
||||
|
||||
public class Header
|
||||
{
|
||||
public uint Version { get; set; }
|
||||
@ -68,10 +437,33 @@ namespace FirstPlugin
|
||||
public Tuple<Node, Node> LinkNodes; //Links two nodes for some reason
|
||||
public List<Node> LowerNodes = new List<Node>();
|
||||
|
||||
public void Read(FileReader reader, TreeNode root)
|
||||
public STSkeleton Skeleton { get; set; }
|
||||
Renderer DrawableRenderer { get; set; }
|
||||
|
||||
public void Read(FileReader reader, MKAGPDX_Model root)
|
||||
{
|
||||
Skeleton = new STSkeleton();
|
||||
DrawableRenderer = new Renderer();
|
||||
root.DrawableContainer.Drawables.Add(Skeleton);
|
||||
root.DrawableContainer.Drawables.Add(DrawableRenderer);
|
||||
|
||||
reader.ReadSignature(4, "BIKE");
|
||||
Version = reader.ReadUInt32();
|
||||
ushort Type = reader.ReadUInt16();
|
||||
ushort Unknown = reader.ReadUInt16();
|
||||
|
||||
if (Type == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if ((Type == 1))
|
||||
{
|
||||
throw new Exception("Animation files not supported yet!");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unknown type found! " + Type);
|
||||
}
|
||||
|
||||
Alignment = reader.ReadUInt32();
|
||||
uint Padding = reader.ReadUInt32();
|
||||
uint MaterialCount = reader.ReadUInt32();
|
||||
@ -90,12 +482,9 @@ namespace FirstPlugin
|
||||
uint Padding2 = reader.ReadUInt32();
|
||||
uint[] Unknowns = reader.ReadUInt32s(10);
|
||||
|
||||
for (int i = 0; i < MaterialCount; i++)
|
||||
{
|
||||
Material mat = new Material();
|
||||
mat.Read(reader);
|
||||
Materials.Add(mat);
|
||||
}
|
||||
root.Nodes.Add("Materials");
|
||||
|
||||
long pos = reader.Position;
|
||||
|
||||
if (TextureMapsOffset != 0)
|
||||
{
|
||||
@ -104,52 +493,176 @@ namespace FirstPlugin
|
||||
{
|
||||
TextureMaps.Add(reader.ReadNameOffset(false, typeof(uint)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Console.WriteLine($"MiddleLevelNodeCount {UpperLevelNodeCount}");
|
||||
Console.WriteLine($"MiddleLevelNodeOffset {UpperLevelNodeOffset}");
|
||||
reader.SeekBegin(pos);
|
||||
for (int i = 0; i < MaterialCount; i++)
|
||||
{
|
||||
Material mat = new Material();
|
||||
mat.Read(reader);
|
||||
Materials.Add(mat);
|
||||
|
||||
if (UpperLevelNodeCount != 0)
|
||||
var genericMat = new STGenericMaterial();
|
||||
genericMat.Text = $"Material {i}";
|
||||
|
||||
for (int t = 0; t < mat.TextureIndices.Length; t++)
|
||||
{
|
||||
for (int i = 0; i < UpperLevelNodeCount; i++)
|
||||
if(mat.TextureIndices[t] != -1)
|
||||
{
|
||||
reader.SeekBegin(UpperLevelNodeOffset + (i * 8));
|
||||
Console.WriteLine("TextureIndices " + mat.TextureIndices[t]);
|
||||
string Texture = TextureMaps[mat.TextureIndices[t]];
|
||||
|
||||
var textureMap = new STGenericMatTexture();
|
||||
textureMap.Name = Texture;
|
||||
genericMat.TextureMaps.Add(textureMap);
|
||||
|
||||
if (Texture.EndsWith("col.dds"))
|
||||
textureMap.Type = STGenericMatTexture.TextureType.Diffuse;
|
||||
if (Texture.EndsWith("col.mot"))
|
||||
textureMap.Type = STGenericMatTexture.TextureType.Diffuse;
|
||||
}
|
||||
}
|
||||
|
||||
root.Nodes[0].Nodes.Add(genericMat);
|
||||
}
|
||||
|
||||
if (LowerLevelNodeCount != 0)
|
||||
{
|
||||
for (int i = 0; i < LowerLevelNodeCount; i++)
|
||||
{
|
||||
reader.SeekBegin(LowerLevelNodeOffset + (i * 8));
|
||||
|
||||
string NodeName = reader.ReadNameOffset(false, typeof(uint));
|
||||
uint Offset = reader.ReadUInt32();
|
||||
Console.WriteLine($"NodeName {NodeName} Offset {Offset}");
|
||||
|
||||
if (Offset != 0)
|
||||
{
|
||||
reader.SeekBegin(Offset);
|
||||
Node node = new Node();
|
||||
node.Text = NodeName;
|
||||
node.Name = NodeName;
|
||||
node.Read(reader);
|
||||
UpperNodes.Add(node);
|
||||
LowerNodes.Add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var node in UpperNodes)
|
||||
LoadChildern(UpperNodes, node, root);
|
||||
if (FirstNodeOffset != 0)
|
||||
{
|
||||
reader.SeekBegin(FirstNodeOffset);
|
||||
uint NodeOffset = reader.ReadUInt32();
|
||||
reader.SeekBegin(NodeOffset);
|
||||
Node node = new Node();
|
||||
node.Name = GetNodeName(LowerNodes, node);
|
||||
node.Read(reader);
|
||||
|
||||
LoadChildern(LowerNodes, node, root);
|
||||
}
|
||||
|
||||
Skeleton.update();
|
||||
Skeleton.reset();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void LoadChildern(List<Node> NodeLookup, Node Node, TreeNode root)
|
||||
{
|
||||
if (Node.ChildNode != null)
|
||||
{
|
||||
if (NodeLookup.Contains(Node.ChildNode))
|
||||
{
|
||||
int index = NodeLookup.IndexOf(Node.ChildNode);
|
||||
Node.ChildNode.Text = NodeLookup[index].Text;
|
||||
var NewNode = SetWrapperNode(Node);
|
||||
root.Nodes.Add(NewNode);
|
||||
|
||||
Node.Nodes.Add(Node.ChildNode);
|
||||
LoadChildern(NodeLookup, Node.ChildNode, Node.ChildNode);
|
||||
for (int i = 0; i < Node.Children.Count; i++)
|
||||
{
|
||||
Node.Children[i].Name = GetNodeName(NodeLookup, Node.Children[i]);
|
||||
|
||||
var newChild = SetWrapperNode(Node.Children[i]);
|
||||
NewNode.Nodes.Add(newChild);
|
||||
|
||||
LoadChildern(NodeLookup, Node.Children[i], newChild);
|
||||
}
|
||||
}
|
||||
|
||||
root.Nodes.Add(Node);
|
||||
private TreeNode SetWrapperNode(Node Node)
|
||||
{
|
||||
if (Node.IsBone)
|
||||
{
|
||||
STBone boneNode = new STBone(Skeleton);
|
||||
boneNode.RotationType = STBone.BoneRotationType.Euler;
|
||||
boneNode.Checked = true;
|
||||
boneNode.Text = Node.Name;
|
||||
boneNode.position = new float[3];
|
||||
boneNode.scale = new float[3];
|
||||
boneNode.rotation = new float[4];
|
||||
boneNode.position[0] = Node.Translation.X;
|
||||
boneNode.position[1] = Node.Translation.Y;
|
||||
boneNode.position[2] = Node.Translation.Z;
|
||||
boneNode.rotation[0] = Node.Rotation.X;
|
||||
boneNode.rotation[1] = Node.Rotation.Y;
|
||||
boneNode.rotation[2] = Node.Rotation.Z;
|
||||
boneNode.scale[0] = Node.Scale.X;
|
||||
boneNode.scale[1] = Node.Scale.Y;
|
||||
boneNode.scale[2] = Node.Scale.Z;
|
||||
|
||||
if (Node.IsBone)
|
||||
Skeleton.bones.Add(boneNode);
|
||||
|
||||
return boneNode;
|
||||
}
|
||||
else if (Node.IsMesh)
|
||||
{
|
||||
MeshWrapper meshNode = new MeshWrapper();
|
||||
meshNode.ImageKey = "mesh";
|
||||
meshNode.SelectedImageKey = "mesh";
|
||||
|
||||
int i = 0;
|
||||
meshNode.lodMeshes = new List<MeshWrapper.LOD_Mesh>();
|
||||
var msh = new MeshWrapper.LOD_Mesh();
|
||||
msh.PrimitiveType = STPolygonType.Triangle;
|
||||
msh.FirstVertex = 0;
|
||||
msh.faces = Node.SubMeshes[0].Faces;
|
||||
meshNode.vertices = Node.SubMeshes[0].Vertices;
|
||||
|
||||
meshNode.lodMeshes.Add(msh);
|
||||
|
||||
foreach (SubMesh subMesh in Node.SubMeshes)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
MeshWrapper subMeshNode = new MeshWrapper();
|
||||
subMeshNode.ImageKey = "mesh";
|
||||
subMeshNode.SelectedImageKey = "mesh";
|
||||
|
||||
subMeshNode.lodMeshes = new List<MeshWrapper.LOD_Mesh>();
|
||||
var submsh = new MeshWrapper.LOD_Mesh();
|
||||
submsh.PrimitiveType = STPolygonType.Triangle;
|
||||
submsh.FirstVertex = 0;
|
||||
submsh.faces = subMesh.Faces;
|
||||
subMeshNode.lodMeshes.Add(submsh);
|
||||
|
||||
subMeshNode.vertices = subMesh.Vertices;
|
||||
DrawableRenderer.Meshes.Add(subMeshNode);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
meshNode.Checked = true;
|
||||
meshNode.Text = Node.Name;
|
||||
DrawableRenderer.Meshes.Add(meshNode);
|
||||
|
||||
return meshNode;
|
||||
}
|
||||
else
|
||||
return new TreeNode(Node.Name);
|
||||
}
|
||||
|
||||
private static string GetNodeName(List<Node> NodeLookup, Node node)
|
||||
{
|
||||
for (int i = 0; i < NodeLookup.Count; i++)
|
||||
{
|
||||
if (NodeLookup[i].Position == node.Position)
|
||||
return NodeLookup[i].Name;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,6 +671,7 @@ namespace FirstPlugin
|
||||
public Vector4 Ambient;
|
||||
public Vector4 Diffuse;
|
||||
public Vector4 Specular;
|
||||
public Vector4 Ambience;
|
||||
public float Shiny;
|
||||
public Vector4 Transparency;
|
||||
public float TransGlossy;
|
||||
@ -176,6 +690,7 @@ namespace FirstPlugin
|
||||
Ambient = new Vector4(0.3f, 0.3f, 0.3f,1.0f);
|
||||
Diffuse = new Vector4(0.7f, 0.7f, 0.7f, 1.0f);
|
||||
Specular = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Ambience = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Shiny = 50;
|
||||
Transparency = new Vector4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
TextureIndices = new short[10];
|
||||
@ -186,6 +701,8 @@ namespace FirstPlugin
|
||||
Ambient = reader.ReadVec4();
|
||||
Diffuse = reader.ReadVec4();
|
||||
Specular = reader.ReadVec4();
|
||||
Ambience = reader.ReadVec4();
|
||||
|
||||
Shiny = reader.ReadSingle();
|
||||
Transparency = reader.ReadVec4();
|
||||
TransGlossy = reader.ReadSingle();
|
||||
@ -196,36 +713,195 @@ namespace FirstPlugin
|
||||
IndexRefreaction = reader.ReadSingle();
|
||||
Translucency = reader.ReadSingle();
|
||||
Unknown = reader.ReadSingle();
|
||||
TextureIndices = reader.ReadInt16s(10);
|
||||
TextureIndices = reader.ReadInt16s(6);
|
||||
Unknowns = reader.ReadUInt32s(10);
|
||||
}
|
||||
}
|
||||
|
||||
public class Node : TreeNode
|
||||
public class SubMesh
|
||||
{
|
||||
public Node ParentNode { get; set; }
|
||||
public Material Material { get; set; }
|
||||
|
||||
public List<Vertex> Vertices = new List<Vertex>();
|
||||
public List<int> Faces = new List<int>();
|
||||
|
||||
public SubMesh(Node parentNode)
|
||||
{
|
||||
ParentNode = parentNode;
|
||||
}
|
||||
|
||||
public void Read(FileReader reader)
|
||||
{
|
||||
uint Padding = reader.ReadUInt32();
|
||||
uint FaceCount = reader.ReadUInt32();
|
||||
uint[] Unknowns = reader.ReadUInt32s(5);
|
||||
uint VertexCount = reader.ReadUInt32();
|
||||
uint VertexPositionOffset = reader.ReadUInt32();
|
||||
uint VertexNormalOffset = reader.ReadUInt32();
|
||||
uint UnknownOffset = reader.ReadUInt32();
|
||||
uint TexCoord0Offset = reader.ReadUInt32();
|
||||
uint TexCoord1Offset = reader.ReadUInt32();
|
||||
uint Unknown1Offset = reader.ReadUInt32();
|
||||
uint Unknown2Offset = reader.ReadUInt32();
|
||||
uint FaceOffset = reader.ReadUInt32();
|
||||
uint SkinCount = reader.ReadUInt32(); //Unsure
|
||||
uint Unknown = reader.ReadUInt32(); //Something related to count
|
||||
uint WeightOffset = reader.ReadUInt32();
|
||||
uint Unknown2 = reader.ReadUInt32();
|
||||
|
||||
for (int i = 0; i < VertexCount; i++)
|
||||
{
|
||||
Vertex vertex = new Vertex();
|
||||
Vertices.Add(vertex);
|
||||
|
||||
if (VertexPositionOffset != 0)
|
||||
{
|
||||
reader.SeekBegin(VertexPositionOffset + (i * 12));
|
||||
vertex.pos = reader.ReadVec3();
|
||||
vertex.pos = Vector3.TransformPosition(vertex.pos, ParentNode.Transform);
|
||||
}
|
||||
if (VertexNormalOffset != 0)
|
||||
{
|
||||
reader.SeekBegin(VertexNormalOffset + (i * 12));
|
||||
vertex.nrm = reader.ReadVec3();
|
||||
vertex.nrm = Vector3.TransformNormal(vertex.nrm, ParentNode.Transform);
|
||||
}
|
||||
if (TexCoord0Offset != 0)
|
||||
{
|
||||
reader.SeekBegin(TexCoord0Offset + (i * 8));
|
||||
vertex.uv0 = reader.ReadVec2();
|
||||
}
|
||||
}
|
||||
|
||||
reader.SeekBegin(FaceOffset);
|
||||
for (int i = 0; i < FaceCount * 3; i++)
|
||||
{
|
||||
Faces.Add(reader.ReadUInt16());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Node
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public bool Visible { get; set; }
|
||||
|
||||
public Vector3 Scale { get; set; }
|
||||
public Vector3 Rotation { get; set; }
|
||||
public Vector3 Translation { get; set; }
|
||||
public byte[] Unknowns;
|
||||
public Node ChildNode { get; set; }
|
||||
public List<Node> Children = new List<Node>();
|
||||
public List<SubMesh> SubMeshes = new List<SubMesh>();
|
||||
|
||||
internal long Position;
|
||||
|
||||
public bool IsBone
|
||||
{
|
||||
get { return Name.Contains("jnt") || Name.Contains("center"); }
|
||||
}
|
||||
|
||||
public bool IsMesh
|
||||
{
|
||||
get { return SubMeshes.Count > 0; }
|
||||
}
|
||||
|
||||
public Matrix4 Transform { get; set; }
|
||||
|
||||
public void Read(FileReader reader)
|
||||
{
|
||||
Position = reader.Position;
|
||||
|
||||
Visible = reader.ReadUInt32() == 1;
|
||||
Scale = reader.ReadVec3();
|
||||
Rotation = reader.ReadVec3();
|
||||
Translation = reader.ReadVec3();
|
||||
Unknowns = reader.ReadBytes(16);
|
||||
uint BufferArrayOffset = reader.ReadUInt32();
|
||||
uint ChildNodeOffset = reader.ReadUInt32();
|
||||
uint SubMeshArrayOffsetPtr = reader.ReadUInt32();
|
||||
uint ChildNodeOffsetPtr = reader.ReadUInt32();
|
||||
|
||||
if (ChildNodeOffset != 0)
|
||||
Matrix4 TranslateMat = Matrix4.CreateTranslation(Translation);
|
||||
Matrix4 RotXMat = Matrix4.CreateRotationX(Rotation.X);
|
||||
Matrix4 RotYMat = Matrix4.CreateRotationY(Rotation.Y);
|
||||
Matrix4 RotZMat = Matrix4.CreateRotationZ(Rotation.Z);
|
||||
Matrix4 ScaleMat = Matrix4.CreateTranslation(Scale);
|
||||
Transform = ScaleMat * (RotXMat * RotYMat * RotZMat) * TranslateMat;
|
||||
|
||||
if (SubMeshArrayOffsetPtr != 0)
|
||||
{
|
||||
reader.SeekBegin(ChildNodeOffset);
|
||||
ChildNode = new Node();
|
||||
//4 possible sub meshes
|
||||
reader.SeekBegin(SubMeshArrayOffsetPtr);
|
||||
uint SubMeshArrayOffset1 = reader.ReadUInt32();
|
||||
uint SubMeshArrayOffset2 = reader.ReadUInt32();
|
||||
uint SubMeshArrayOffset3 = reader.ReadUInt32();
|
||||
uint SubMeshArrayOffset4 = reader.ReadUInt32();
|
||||
if (SubMeshArrayOffset1 != 0)
|
||||
{
|
||||
reader.SeekBegin(SubMeshArrayOffset1);
|
||||
SubMesh subMesh = new SubMesh(this);
|
||||
subMesh.Read(reader);
|
||||
SubMeshes.Add(subMesh);
|
||||
}
|
||||
if (SubMeshArrayOffset2 != 0)
|
||||
{
|
||||
reader.SeekBegin(SubMeshArrayOffset2);
|
||||
SubMesh subMesh = new SubMesh(this);
|
||||
subMesh.Read(reader);
|
||||
SubMeshes.Add(subMesh);
|
||||
}
|
||||
if (SubMeshArrayOffset3 != 0)
|
||||
{
|
||||
reader.SeekBegin(SubMeshArrayOffset3);
|
||||
SubMesh subMesh = new SubMesh(this);
|
||||
subMesh.Read(reader);
|
||||
SubMeshes.Add(subMesh);
|
||||
}
|
||||
if (SubMeshArrayOffset4 != 0)
|
||||
{
|
||||
reader.SeekBegin(SubMeshArrayOffset4);
|
||||
SubMesh subMesh = new SubMesh(this);
|
||||
subMesh.Read(reader);
|
||||
SubMeshes.Add(subMesh);
|
||||
}
|
||||
}
|
||||
|
||||
if (ChildNodeOffsetPtr != 0)
|
||||
{
|
||||
//4 possible children
|
||||
reader.SeekBegin(ChildNodeOffsetPtr);
|
||||
uint ChildNodeOffset1 = reader.ReadUInt32();
|
||||
uint ChildNodeOffset2 = reader.ReadUInt32();
|
||||
uint ChildNodeOffset3 = reader.ReadUInt32();
|
||||
uint ChildNodeOffset4 = reader.ReadUInt32();
|
||||
if (ChildNodeOffset1 != 0)
|
||||
{
|
||||
reader.SeekBegin(ChildNodeOffset1);
|
||||
Node ChildNode = new Node();
|
||||
ChildNode.Read(reader);
|
||||
Children.Add(ChildNode);
|
||||
}
|
||||
if (ChildNodeOffset2 != 0)
|
||||
{
|
||||
reader.SeekBegin(ChildNodeOffset2);
|
||||
Node ChildNode = new Node();
|
||||
ChildNode.Read(reader);
|
||||
Children.Add(ChildNode);
|
||||
}
|
||||
if (ChildNodeOffset3 != 0)
|
||||
{
|
||||
reader.SeekBegin(ChildNodeOffset3);
|
||||
Node ChildNode = new Node();
|
||||
ChildNode.Read(reader);
|
||||
Children.Add(ChildNode);
|
||||
}
|
||||
if (ChildNodeOffset4 != 0)
|
||||
{
|
||||
reader.SeekBegin(ChildNodeOffset4);
|
||||
Node ChildNode = new Node();
|
||||
ChildNode.Read(reader);
|
||||
Children.Add(ChildNode);
|
||||
}
|
||||
}
|
||||
|
||||
//After repeats a fairly similar structure, with SRT values
|
||||
|
Binary file not shown.
Binary file not shown.
@ -18,7 +18,11 @@ namespace Switch_Toolbox.Library
|
||||
|
||||
STProgressBar progressBar;
|
||||
|
||||
public void SaveFromModel(STGenericModel model, string FileName, List<STGenericTexture> Textures, STSkeleton skeleton = null, List<int> NodeArray = null)
|
||||
public void SaveFromModel(STGenericModel model, string FileName, List<STGenericTexture> Textures, STSkeleton skeleton = null, List<int> NodeArray = null) {
|
||||
SaveFromModel(model.Objects.ToList(), model.Materials.ToList(), FileName, Textures, skeleton, NodeArray);
|
||||
}
|
||||
|
||||
public void SaveFromModel(List<STGenericObject> Meshes, List<STGenericMaterial> Materials, string FileName, List<STGenericTexture> Textures, STSkeleton skeleton = null, List<int> NodeArray = null)
|
||||
{
|
||||
ExtractedTextures.Clear();
|
||||
|
||||
@ -33,17 +37,17 @@ namespace Switch_Toolbox.Library
|
||||
progressBar.Refresh();
|
||||
|
||||
SaveSkeleton(skeleton, scene.RootNode);
|
||||
SaveMaterials(scene, model, FileName, Textures);
|
||||
SaveMaterials(scene, Materials, FileName, Textures);
|
||||
|
||||
progressBar.Task = "Exorting Meshes...";
|
||||
progressBar.Value = 50;
|
||||
|
||||
SaveMeshes(scene, model, skeleton, FileName, NodeArray);
|
||||
SaveMeshes(scene, Meshes, skeleton, FileName, NodeArray);
|
||||
|
||||
progressBar.Task = "Saving File...";
|
||||
progressBar.Value = 80;
|
||||
|
||||
SaveScene(FileName, scene, model.GetObjects());
|
||||
SaveScene(FileName, scene, Meshes);
|
||||
|
||||
progressBar.Value = 100;
|
||||
progressBar.Close();
|
||||
@ -78,10 +82,10 @@ namespace Switch_Toolbox.Library
|
||||
|
||||
}
|
||||
|
||||
private void SaveMeshes(Scene scene, STGenericModel model, STSkeleton skeleton, string FileName, List<int> NodeArray)
|
||||
private void SaveMeshes(Scene scene, List<STGenericObject> Meshes, STSkeleton skeleton, string FileName, List<int> NodeArray)
|
||||
{
|
||||
int MeshIndex = 0;
|
||||
foreach (var obj in model.Nodes[0].Nodes)
|
||||
foreach (var obj in Meshes)
|
||||
{
|
||||
var mesh = SaveMesh((STGenericObject)obj, MeshIndex, skeleton, NodeArray);
|
||||
scene.Meshes.Add(mesh);
|
||||
@ -126,9 +130,15 @@ namespace Switch_Toolbox.Library
|
||||
for (int j = 0; j < v.boneIds.Count; j++)
|
||||
{
|
||||
if (j < genericObj.VertexSkinCount)
|
||||
{
|
||||
STBone STbone = null;
|
||||
if (NodeArray != null)
|
||||
{
|
||||
//Get the bone via the node array and bone index from the vertex
|
||||
STBone STbone = skeleton.bones[NodeArray[v.boneIds[j]]];
|
||||
STbone = skeleton.bones[NodeArray[v.boneIds[j]]];
|
||||
}
|
||||
else
|
||||
STbone = skeleton.bones[v.boneIds[j]];
|
||||
|
||||
//Find the index of a bone. If it doesn't exist then we add it
|
||||
int boneInd = mesh.Bones.FindIndex(x => x.Name == STbone.Text);
|
||||
@ -478,7 +488,7 @@ namespace Switch_Toolbox.Library
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
private void SaveMaterials(Scene scene, STGenericModel model, string FileName, List<STGenericTexture> Textures)
|
||||
private void SaveMaterials(Scene scene, List<STGenericMaterial> Materials, string FileName, List<STGenericTexture> Textures)
|
||||
{
|
||||
string TextureExtension = ".png";
|
||||
string TexturePath = System.IO.Path.GetDirectoryName(FileName);
|
||||
@ -503,7 +513,7 @@ namespace Switch_Toolbox.Library
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var mat in model.Nodes[1].Nodes)
|
||||
foreach (var mat in Materials)
|
||||
{
|
||||
var genericMat = (STGenericMaterial)mat;
|
||||
|
||||
|
@ -20,23 +20,31 @@ namespace Switch_Toolbox.Library
|
||||
|
||||
}
|
||||
|
||||
public List<STGenericObject> GetObjects()
|
||||
{
|
||||
List<STGenericObject> objects = new List<STGenericObject>();
|
||||
foreach (TreeNode node in Nodes)
|
||||
{
|
||||
if (node is STGenericObject)
|
||||
objects.Add(node as STGenericObject);
|
||||
private IEnumerable<STGenericMaterial> _materials;
|
||||
private IEnumerable<STGenericObject> _objects;
|
||||
|
||||
if (node.Nodes.Count > 0)
|
||||
public virtual IEnumerable<STGenericMaterial> Materials
|
||||
{
|
||||
foreach (TreeNode childNode in node.Nodes)
|
||||
if (childNode is STGenericObject)
|
||||
objects.Add(childNode as STGenericObject);
|
||||
get
|
||||
{
|
||||
return _materials;
|
||||
}
|
||||
set
|
||||
{
|
||||
_materials = value;
|
||||
}
|
||||
}
|
||||
|
||||
return objects;
|
||||
public virtual IEnumerable<STGenericObject> Objects
|
||||
{
|
||||
get
|
||||
{
|
||||
return _objects;
|
||||
}
|
||||
set
|
||||
{
|
||||
_objects = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
36
Toolbox/Shader/MKAGPDX/MKAGPDX_Model.frag
Normal file
36
Toolbox/Shader/MKAGPDX/MKAGPDX_Model.frag
Normal file
@ -0,0 +1,36 @@
|
||||
#version 330
|
||||
in vec3 normal;
|
||||
in vec3 position;
|
||||
|
||||
in vec2 f_texcoord0;
|
||||
in vec2 f_texcoord1;
|
||||
in vec2 f_texcoord2;
|
||||
in vec2 f_texcoord3;
|
||||
in vec4 vertexColor;
|
||||
in vec3 tangent;
|
||||
|
||||
in vec3 boneWeightsColored;
|
||||
|
||||
uniform vec3 difLightDirection;
|
||||
uniform vec3 difLightColor;
|
||||
uniform vec3 ambLightColor;
|
||||
|
||||
|
||||
uniform int colorOverride;
|
||||
uniform int renderType;
|
||||
uniform int renderVertColor;
|
||||
uniform mat4 modelview;
|
||||
|
||||
uniform int HasDiffuse;
|
||||
|
||||
uniform sampler2D DiffuseMap;
|
||||
uniform sampler2D UVTestPattern;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
vec3 displayNormal = (normal.xyz * 0.5) + 0.5;
|
||||
FragColor = vec4(displayNormal.rgb,1);
|
||||
}
|
132
Toolbox/Shader/MKAGPDX/MKAGPDX_Model.vert
Normal file
132
Toolbox/Shader/MKAGPDX/MKAGPDX_Model.vert
Normal file
@ -0,0 +1,132 @@
|
||||
#version 330
|
||||
|
||||
const int MY_ARRAY_SIZE = 200;
|
||||
|
||||
in vec3 vPosition;
|
||||
in vec3 vNormal;
|
||||
in vec3 vTangent;
|
||||
in vec2 vUV0;
|
||||
in vec4 vColor;
|
||||
in vec4 vBone;
|
||||
in vec4 vWeight;
|
||||
in vec2 vUV1;
|
||||
in vec2 vUV2;
|
||||
|
||||
out vec2 f_texcoord0;
|
||||
out vec2 f_texcoord1;
|
||||
out vec2 f_texcoord2;
|
||||
out vec2 f_texcoord3;
|
||||
|
||||
out vec3 normal;
|
||||
out vec4 vertexColor;
|
||||
out vec3 position;
|
||||
out vec3 tangent;
|
||||
|
||||
out vec3 boneWeightsColored;
|
||||
|
||||
uniform int boneIds[190];
|
||||
|
||||
// Skinning uniforms
|
||||
uniform mat4 bones[190];
|
||||
|
||||
uniform mat4 mtxCam;
|
||||
uniform mat4 mtxMdl;
|
||||
uniform mat4 previewScale;
|
||||
|
||||
// Bone Weight Display
|
||||
uniform sampler2D weightRamp1;
|
||||
uniform sampler2D weightRamp2;
|
||||
uniform int selectedBoneIndex;
|
||||
uniform int debugOption;
|
||||
|
||||
uniform int NoSkinning;
|
||||
uniform int RigidSkinning;
|
||||
uniform int SingleBoneIndex;
|
||||
|
||||
vec2 ST0_Translate;
|
||||
float ST0_Rotate;
|
||||
vec2 ST0_Scale;
|
||||
|
||||
vec4 skin(vec3 pos, ivec4 index)
|
||||
{
|
||||
vec4 newPosition = vec4(pos.xyz, 1.0);
|
||||
|
||||
newPosition = bones[index.x] * vec4(pos, 1.0) * vWeight.x;
|
||||
newPosition += bones[index.y] * vec4(pos, 1.0) * vWeight.y;
|
||||
newPosition += bones[index.z] * vec4(pos, 1.0) * vWeight.z;
|
||||
if (vWeight.w < 1) //Necessary. Bones may scale weirdly without
|
||||
newPosition += bones[index.w] * vec4(pos, 1.0) * vWeight.w;
|
||||
|
||||
return newPosition;
|
||||
}
|
||||
|
||||
vec3 skinNRM(vec3 nr, ivec4 index)
|
||||
{
|
||||
vec3 newNormal = vec3(0);
|
||||
|
||||
newNormal = mat3(bones[index.x]) * nr * vWeight.x;
|
||||
newNormal += mat3(bones[index.y]) * nr * vWeight.y;
|
||||
newNormal += mat3(bones[index.z]) * nr * vWeight.z;
|
||||
newNormal += mat3(bones[index.w]) * nr * vWeight.w;
|
||||
|
||||
return newNormal;
|
||||
}
|
||||
|
||||
vec3 BoneWeightColor(float weights)
|
||||
{
|
||||
float rampInputLuminance = weights;
|
||||
rampInputLuminance = clamp((rampInputLuminance), 0.001, 0.999);
|
||||
if (debugOption == 1) // Greyscale
|
||||
return vec3(weights);
|
||||
else if (debugOption == 2) // Color 1
|
||||
return texture(weightRamp1, vec2(1 - rampInputLuminance, 0.50)).rgb;
|
||||
else // Color 2
|
||||
return texture(weightRamp2, vec2(1 - rampInputLuminance, 0.50)).rgb;
|
||||
}
|
||||
|
||||
float BoneWeightDisplay(ivec4 index)
|
||||
{
|
||||
float weight = 0;
|
||||
if (selectedBoneIndex == boneIds[index.x])
|
||||
weight += vWeight.x;
|
||||
if (selectedBoneIndex == boneIds[index.y])
|
||||
weight += vWeight.y;
|
||||
if (selectedBoneIndex == boneIds[index.z])
|
||||
weight += vWeight.z;
|
||||
if (selectedBoneIndex == boneIds[index.w])
|
||||
weight += vWeight.w;
|
||||
|
||||
if (selectedBoneIndex == boneIds[index.x] && RigidSkinning == 1)
|
||||
weight = 1;
|
||||
if (selectedBoneIndex == SingleBoneIndex && NoSkinning == 1)
|
||||
weight = 1;
|
||||
|
||||
return weight;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec4 index = ivec4(vBone);
|
||||
|
||||
vec4 objPos = vec4(vPosition.xyz, 1.0);
|
||||
if (vBone.x != -1.0)
|
||||
objPos = skin(vPosition, index);
|
||||
if(vBone.x != -1.0)
|
||||
normal = normalize((skinNRM(vNormal.xyz, index)).xyz);
|
||||
|
||||
vec4 position = mtxCam * mtxMdl * vec4(objPos.xyz, 1.0);
|
||||
|
||||
normal = vNormal;
|
||||
vertexColor = vColor;
|
||||
position = objPos;
|
||||
f_texcoord0 = vUV0;
|
||||
f_texcoord1 = vUV1;
|
||||
f_texcoord2 = vUV2;
|
||||
tangent = vTangent;
|
||||
|
||||
gl_Position = mtxCam * mtxMdl * vec4(vPosition.xyz, 1.0);
|
||||
|
||||
float totalWeight = BoneWeightDisplay(index);
|
||||
boneWeightsColored = BoneWeightColor(totalWeight).rgb;
|
||||
|
||||
}
|
@ -237,6 +237,12 @@
|
||||
<None Include="Shader\Legacy\KCL.vert">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Shader\MKAGPDX\MKAGPDX_Model.frag">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Shader\MKAGPDX\MKAGPDX_Model.vert">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Shader\PBR\brdf.frag">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
Loading…
Reference in New Issue
Block a user