From 25842949a93de5ed73035ab5951884e426213043 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Tue, 17 Mar 2020 15:56:14 -0700 Subject: [PATCH 01/11] Initial MP2 fixes --- DataSpec/DNACommon/CMDL.cpp | 5 +- DataSpec/DNAMP1/CMDLMaterials.cpp | 716 +++++++++++++++++++----------- DataSpec/DNAMP2/CINF.cpp | 117 +++++ DataSpec/DNAMP2/CINF.hpp | 17 + DataSpec/DNAMP2/DNAMP2.cpp | 3 + DataSpec/DNAMP2/DeafBabe.cpp | 7 +- 6 files changed, 596 insertions(+), 269 deletions(-) diff --git a/DataSpec/DNACommon/CMDL.cpp b/DataSpec/DNACommon/CMDL.cpp index 394d437fe..b20cc4067 100644 --- a/DataSpec/DNACommon/CMDL.cpp +++ b/DataSpec/DNACommon/CMDL.cpp @@ -521,7 +521,10 @@ void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int " use_vert_dict = vert_dict[0]\n" " merge_verts = [use_vert_dict[fv[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] for fv in " "face.verts]\n" - " if bm.faces.get(merge_verts) is not None:\n" + " try:\n" + " if bm.faces.get(merge_verts) is not None:\n" + " continue\n" + " except:\n" " continue\n" " merge_face = bm.faces.new(merge_verts)\n" " for i in range(len(face.loops)):\n" diff --git a/DataSpec/DNAMP1/CMDLMaterials.cpp b/DataSpec/DNAMP1/CMDLMaterials.cpp index 1d7543c3f..61aac9a43 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.cpp +++ b/DataSpec/DNAMP1/CMDLMaterials.cpp @@ -34,12 +34,11 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t else texLabel = "Texture"; - out.format(fmt( - "# Texture\n" - "tex_node = new_nodetree.nodes.new('ShaderNodeTexImage')\n" - "tex_node.label = '{} {}'\n" - "texture_nodes.append(tex_node)\n"), - texLabel, texIdx); + out.format(fmt("# Texture\n" + "tex_node = new_nodetree.nodes.new('ShaderNodeTexImage')\n" + "tex_node.label = '{} {}'\n" + "texture_nodes.append(tex_node)\n"), + texLabel, texIdx); if (texIdx != 0xff) out.format(fmt("tex_node.image = tex_maps[{}]\n"), texIdx); @@ -52,11 +51,10 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Normal'], tex_node.inputs['Vector']))\n"; else if (type >= GX::TG_TEX0 && type <= GX::TG_TEX7) { uint8_t texIdx = type - GX::TG_TEX0; - out.format(fmt( - "tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n" - "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" - "tex_uv_node.uv_map = 'UV_{}'\n"), - texIdx); + out.format(fmt("tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" + "tex_uv_node.uv_map = 'UV_{}'\n"), + texIdx); } out.format(fmt("tex_uv_node.label = '{}'\n"), mtxLabel); @@ -72,171 +70,162 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx, const float* vals) { switch (type) { case UVAnimation::Mode::MvInvNoTranslation: - out.format(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode0NodeN']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), - idx); + out.format(fmt("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode0NodeN']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), + idx); break; case UVAnimation::Mode::MvInv: - out.format(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode1NodeN']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), - idx); + out.format(fmt("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode1NodeN']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), + idx); break; case UVAnimation::Mode::Scroll: - out.format(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode2Node']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = ({},{},0)\n" - " node.inputs[2].default_value = ({},{},0)\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), - idx, vals[0], vals[1], vals[2], vals[3]); + out.format(fmt("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode2Node']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = ({},{},0)\n" + " node.inputs[2].default_value = ({},{},0)\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), + idx, vals[0], vals[1], vals[2], vals[3]); break; case UVAnimation::Mode::Rotation: - out.format(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode3Node']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = {}\n" - " node.inputs[2].default_value = {}\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), - idx, vals[0], vals[1]); + out.format(fmt("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode3Node']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = {}\n" + " node.inputs[2].default_value = {}\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), + idx, vals[0], vals[1]); break; case UVAnimation::Mode::HStrip: - out.format(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode4Node']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = {}\n" - " node.inputs[2].default_value = {}\n" - " node.inputs[3].default_value = {}\n" - " node.inputs[4].default_value = {}\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), - idx, vals[0], vals[1], vals[2], vals[3]); + out.format(fmt("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode4Node']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = {}\n" + " node.inputs[2].default_value = {}\n" + " node.inputs[3].default_value = {}\n" + " node.inputs[4].default_value = {}\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), + idx, vals[0], vals[1], vals[2], vals[3]); break; case UVAnimation::Mode::VStrip: - out.format(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode5Node']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = {}\n" - " node.inputs[2].default_value = {}\n" - " node.inputs[3].default_value = {}\n" - " node.inputs[4].default_value = {}\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), - idx, vals[0], vals[1], vals[2], vals[3]); + out.format(fmt("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode5Node']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = {}\n" + " node.inputs[2].default_value = {}\n" + " node.inputs[3].default_value = {}\n" + " node.inputs[4].default_value = {}\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), + idx, vals[0], vals[1], vals[2], vals[3]); break; case UVAnimation::Mode::Model: - out.format(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode6NodeN']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), - idx); + out.format(fmt("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode6NodeN']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), + idx); break; case UVAnimation::Mode::CylinderEnvironment: - out.format(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode7NodeN']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = {}\n" - " node.inputs[2].default_value = {}\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), - idx, vals[0], vals[1]); + out.format(fmt("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode7NodeN']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = {}\n" + " node.inputs[2].default_value = {}\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), + idx, vals[0], vals[1]); break; case UVAnimation::Mode::Eight: - out.format(fmt( - "for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_{}':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode8Node']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = {}\n" - " node.inputs[2].default_value = {}\n" - " node.inputs[3].default_value = {}\n" - " node.inputs[4].default_value = {}\n" - " node.inputs[5].default_value = {}\n" - " node.inputs[6].default_value = {}\n" - " node.inputs[7].default_value = {}\n" - " node.inputs[8].default_value = {}\n" - " node.inputs[9].default_value = {}\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), - idx, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8]); + out.format(fmt("for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_{}':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode8Node']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = {}\n" + " node.inputs[2].default_value = {}\n" + " node.inputs[3].default_value = {}\n" + " node.inputs[4].default_value = {}\n" + " node.inputs[5].default_value = {}\n" + " node.inputs[6].default_value = {}\n" + " node.inputs[7].default_value = {}\n" + " node.inputs[8].default_value = {}\n" + " node.inputs[9].default_value = {}\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n"), + idx, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8]); break; default: break; @@ -244,12 +233,12 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx, } void Material::AddKcolor(Stream& out, const GX::Color& col, unsigned idx) { - out.format(fmt( - "kcolors[{}] = ({}, {}, {}, {})\n" - "kalphas[{}] = {}\n" - "\n"), - idx, (float)col.color[0] / (float)0xff, (float)col.color[1] / (float)0xff, (float)col.color[2] / (float)0xff, - (float)col.color[3] / (float)0xff, idx, (float)col.color[3] / (float)0xff); + out.format(fmt("kcolors[{}] = ({}, {}, {}, {})\n" + "kalphas[{}] = {}\n" + "\n"), + idx, (float)col.color[0] / (float)0xff, (float)col.color[1] / (float)0xff, + (float)col.color[2] / (float)0xff, (float)col.color[3] / (float)0xff, idx, + (float)col.color[3] / (float)0xff); } template @@ -354,11 +343,10 @@ template static void _DescribeTEV(const MAT& mat) { for (uint32_t i = 0; i < mat.tevStageCount; ++i) { const auto& stage = mat.tevStages[i]; - fmt::print(stderr, fmt("A:{} B:{} C:{} D:{} -> {} | A:{} B:{} C:{} D:{} -> {}\n"), - ToString(stage.colorInA()), ToString(stage.colorInB()), - ToString(stage.colorInC()), ToString(stage.colorInD()), ToString(stage.colorOpOutReg()), - ToString(stage.alphaInA()), ToString(stage.alphaInB()), - ToString(stage.alphaInC()), ToString(stage.alphaInD()), ToString(stage.alphaOpOutReg())); + fmt::print(stderr, fmt("A:{} B:{} C:{} D:{} -> {} | A:{} B:{} C:{} D:{} -> {}\n"), ToString(stage.colorInA()), + ToString(stage.colorInB()), ToString(stage.colorInC()), ToString(stage.colorInD()), + ToString(stage.colorOpOutReg()), ToString(stage.alphaInA()), ToString(stage.alphaInB()), + ToString(stage.alphaInC()), ToString(stage.alphaInD()), ToString(stage.alphaOpOutReg())); } bool hasInd = mat.flags.samusReflectionIndirectTexture(); bool hasLm = mat.flags.lightmap(); @@ -388,12 +376,10 @@ struct KColLink { struct WhiteColorLink { const char* shaderInput; - explicit WhiteColorLink(const char* shaderInput) - : shaderInput(shaderInput) {} + explicit WhiteColorLink(const char* shaderInput) : shaderInput(shaderInput) {} }; -static void _GenerateRootShader(Stream& out, int) { - /* End of shader links */ +static void _GenerateRootShader(Stream& out, int) { /* End of shader links */ } template @@ -401,8 +387,8 @@ static void _GenerateRootShader(Stream& out, int tidx, TexLink tex, Targs... arg int texIdx = tex.texidx == -1 ? tidx : tex.texidx; out << "texture_nodes[" << texIdx << "].name = '" << tex.shaderInput << "'\n"; out << "texture_nodes[" << texIdx << "].label = '" << tex.shaderInput << "'\n"; - out << "new_nodetree.links.new(texture_nodes[" << texIdx << "].outputs['" << - (tex.alpha ? "Alpha" : "Color") << "'], node.inputs['" << tex.shaderInput << "'])\n"; + out << "new_nodetree.links.new(texture_nodes[" << texIdx << "].outputs['" << (tex.alpha ? "Alpha" : "Color") + << "'], node.inputs['" << tex.shaderInput << "'])\n"; if (tex.texidx == -1) ++tidx; _GenerateRootShader(out, tidx, args...); @@ -422,8 +408,8 @@ static void _GenerateRootShader(Stream& out, int tidx, ExtendedSpecularLink tex, template static void _GenerateRootShader(Stream& out, int tidx, KColLink kcol, Targs... args) { - out << "node.inputs['" << kcol.shaderInput << "'].default_value = " << - (kcol.alpha ? "kalphas[" : "kcolors[") << kcol.kcidx << "]\n"; + out << "node.inputs['" << kcol.shaderInput << "'].default_value = " << (kcol.alpha ? "kalphas[" : "kcolors[") + << kcol.kcidx << "]\n"; _GenerateRootShader(out, tidx, args...); } @@ -437,16 +423,18 @@ template static void _GenerateRootShader(Stream& out, const char* type, Targs... args) { out << "node = new_nodetree.nodes.new('ShaderNodeGroup')\n" "node.name = 'Output'\n" - "node.node_tree = bpy.data.node_groups['" << type << "']\n" + "node.node_tree = bpy.data.node_groups['" + << type + << "']\n" "gridder.place_node(node, 1)\n" "new_nodetree.links.new(node.outputs['Surface'], blend_node.inputs['Surface'])\n"; _GenerateRootShader(out, 0, args...); } -static TexLink operator "" _tex(const char* str, size_t) { return TexLink(str); } -static TexLink operator "" _texa(const char* str, size_t) { return TexLink(str, -1, true); } -static KColLink operator "" _kcol(const char* str, size_t) { return KColLink(str); } -static KColLink operator "" _kcola(const char* str, size_t) { return KColLink(str, 0, true); } +static TexLink operator"" _tex(const char* str, size_t) { return TexLink(str); } +static TexLink operator"" _texa(const char* str, size_t) { return TexLink(str, -1, true); } +static KColLink operator"" _kcol(const char* str, size_t) { return KColLink(str); } +static KColLink operator"" _kcola(const char* str, size_t) { return KColLink(str, 0, true); } template static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupIdx, unsigned matIdx) { @@ -470,22 +458,21 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI "\n"; /* Material Flags */ - out.format(fmt( - "new_material.retro_depth_sort = {}\n" - "new_material.retro_alpha_test = {}\n" - "new_material.retro_samus_reflection = {}\n" - "new_material.retro_depth_write = {}\n" - "new_material.retro_samus_reflection_persp = {}\n" - "new_material.retro_shadow_occluder = {}\n" - "new_material.retro_samus_reflection_indirect = {}\n" - "new_material.retro_lightmapped = {}\n" - "new_material.diffuse_color = (1, 1, 1, {})\n"), - material.flags.depthSorting() ? "True" : "False", material.flags.alphaTest() ? "True" : "False", - material.flags.samusReflection() ? "True" : "False", material.flags.depthWrite() ? "True" : "False", - material.flags.samusReflectionSurfaceEye() ? "True" : "False", - material.flags.shadowOccluderMesh() ? "True" : "False", - material.flags.samusReflectionIndirectTexture() ? "True" : "False", material.flags.lightmap() ? "True" : "False", - material.flags.shadowOccluderMesh() ? "0" : "1"); + out.format(fmt("new_material.retro_depth_sort = {}\n" + "new_material.retro_alpha_test = {}\n" + "new_material.retro_samus_reflection = {}\n" + "new_material.retro_depth_write = {}\n" + "new_material.retro_samus_reflection_persp = {}\n" + "new_material.retro_shadow_occluder = {}\n" + "new_material.retro_samus_reflection_indirect = {}\n" + "new_material.retro_lightmapped = {}\n" + "new_material.diffuse_color = (1, 1, 1, {})\n"), + material.flags.depthSorting() ? "True" : "False", material.flags.alphaTest() ? "True" : "False", + material.flags.samusReflection() ? "True" : "False", material.flags.depthWrite() ? "True" : "False", + material.flags.samusReflectionSurfaceEye() ? "True" : "False", + material.flags.shadowOccluderMesh() ? "True" : "False", + material.flags.samusReflectionIndirectTexture() ? "True" : "False", + material.flags.lightmap() ? "True" : "False", material.flags.shadowOccluderMesh() ? "0" : "1"); /* Texture Indices */ out << "tex_maps = []\n"; @@ -538,130 +525,329 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI uint32_t hash = _HashTextureConfig(material); switch (hash) { case 0x0473AE40: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); + break; case 0x072D2CB3: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), + "Reflection"_tex); + break; case 0x0879D346: /* RetroShader: KColorDiffuse, Alpha=Texture */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_tex); + break; case 0x0DA256BB: /* Lightmap, Diffuse, Specular, Reflection, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, + "Alpha"_kcola); + break; case 0x11C41DA4: /* RetroDynamicCharacterShader: Diffuse, DynamicMaskTex, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicCharacterShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroDynamicCharacterShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, + "Reflection"_tex); + break; case 0x1218F83E: /* RetroShader: ObjLightmap, Diffuse, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, + TexLink("Alpha", 1, true)); + break; case 0x129B8578: /* RetroShader: KColorDiffuse, Emissive, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola); + break; case 0x15A3E6E5: /* RetroShader: Diffuse, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); + break; case 0x1BEB3E15: /* RetroShader: Diffuse, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); + break; case 0x2261E0EB: /* RetroShader: Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); + break; case 0x239C7724: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); + break; case 0x240C4C84: /* RetroShader: Lightmap, KColorDiffuse, Specular, Reflection, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Specular"_tex, "Reflection"_tex, + "Alpha"_kcola); + break; case 0x2523A379: /* RetroDynamicShader: Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); + break; case 0x25E85017: /* RetroShader: Lightmap, KColorDiffuse, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); + break; case 0x27FD5C6C: /* RetroShader: ObjLightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, + TexLink("Alpha", 1, true)); + break; case 0x2AD9F535: /* RetroShader: Emissive, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); + break; case 0x2C9F5104: /* RetroShader: Diffuse, Specular, Reflection, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); + break; case 0x2D059429: /* RetroShader: Diffuse, Emissive, ExtendedSpecular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); + break; case 0x30AC64BB: /* RetroShader: Diffuse, Specular, Reflection, Alpha=KAlpha, IndirectTex */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, "Alpha"_kcola); break; - case 0x39BC4809: /* RetroDynamicShader: ObjLightmap*Dynamic, Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, + "Alpha"_kcola); + break; + case 0x39BC4809: /* RetroDynamicShader: ObjLightmap*Dynamic, Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection, + Alpha=1.0 */ + _GenerateRootShader(out, "RetroDynamicShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, + "Reflection"_tex); + break; case 0x3BF97299: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=KAlpha, IndirectTex */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, + "IndirectTex"_tex, "Alpha"_kcola); + break; case 0x47ECF3ED: /* RetroShader: Diffuse, Specular, Reflection, Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Emissive"_tex); + break; case 0x4BBDFFA6: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); + break; case 0x4D4127A3: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, + TexLink("Alpha", 1, true)); + break; case 0x54A92F25: /* RetroShader: ObjLightmap, KColorDiffuse, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); + break; + case 0x07AA75D7: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV + HasIndirect: false HasLightmap: false + */ + case 0x72BEDDAC: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 + A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_TEXC -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 + A:CC_ZERO B:CC_C2 C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV + HasIndirect: false HasLightmap: true + */ + case 0x03FEE002: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV + HasIndirect: false HasLightmap: false + */ + case 0xF4DA0A86: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_RASC C:CC_KONST D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV + HasIndirect: false HasLightmap: false + */ + case 0xF345C16E: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV + HasIndirect: false HasLightmap: false + */ + case 0x8C562AB1: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV + HasIndirect: false HasLightmap: false + */ + case 0xE92F1340: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_TEXA C:CA_APREV D:CA_ZERO -> TEVPREV + HasIndirect: false HasLightmap: false + */ + case 0xCE06F3F2: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_TEXA C:CA_APREV D:CA_ZERO -> TEVPREV + HasIndirect: false HasLightmap: false + */ + case 0xC0E3FF1F: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_RASC C:CC_KONST D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_TEXC -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 + A:CC_ZERO B:CC_C2 C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV + HasIndirect: false HasLightmap: false + */ + case 0xFC2761B8: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_RASC -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 + A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_TEXA C:CA_APREV D:CA_ZERO -> TEVPREV + HasIndirect: false HasLightmap: true + */ + case 0xE64D1085: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_RASC -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 + A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV + HasIndirect: false HasLightmap: true + */ + case 0xB26E9E2E: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_TEXC -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 + A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_C2 -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 + HasIndirect: false HasLightmap: false + */ + case 0x4184FBCA: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_RASC -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 + A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV + HasIndirect: false HasLightmap: true + */ + case 0x81106196: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + HasIndirect: false HasLightmap: false + */ + case 0x15A00948: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_TEXC -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 + A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_C2 -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 + A:CC_ZERO B:CC_C2 C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV + HasIndirect: false HasLightmap: false + */ + case 0xFFF3CEBB: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_RASC -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 + A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_TEXA C:CA_APREV D:CA_ZERO -> TEVPREV + HasIndirect: false HasLightmap: true + */ + case 0x58BAA415: + /* TODO: Properly implement TEV configuration: + A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_RASC -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 + A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV + A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV + A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_TEXC -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 + HasIndirect: false HasLightmap: true + */ case 0x54C6204C: - _GenerateRootShader(out, "RetroShader"); break; + _GenerateRootShader(out, "RetroShader"); + break; case 0x5A62D5F0: /* RetroShader: Lightmap, Diffuse, UnusedExtendedSpecular?, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; case 0x5CB59821: /* RetroShader: Diffuse, UnusedSpecular?, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); + break; case 0x5D0F0069: /* RetroShader: Diffuse, Emissive, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 0, true)); + break; case 0x5D80E53C: /* RetroShader: Emissive, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); + break; case 0x5F0AB0E9: /* RetroShader: Lightmap, Diffuse, UnusedSpecular?, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; case 0x5F189425: /* RetroShader: Lightmap, Diffuse, UnusedSpecular?, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); + break; case 0x6601D113: /* RetroShader: Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Emissive"_tex); + break; case 0x694287FA: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), + "Reflection"_tex); + break; case 0x6D98D689: /* RetroDynamicAlphaShader: Diffuse*Dynamic, Specular, Reflection, Alpha=KAlpha*Dynamic */ - _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); + break; case 0x7252CB90: /* RetroShader: Lightmap, Diffuse, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); + break; case 0x76BEA57E: /* RetroShader: Lightmap, Diffuse, Emissive, Specular, Reflection, Alpha=1.0, IndirectTex */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, + "Reflection"_tex, "IndirectTex"_tex); + break; case 0x7D6A4487: /* RetroShader: Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 0, true)); + break; case 0x84319328: /* RetroShader: Reflection, UnusedSpecular?, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", WhiteColorLink("Specular"), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", WhiteColorLink("Specular"), "Reflection"_tex); + break; case 0x846215DA: /* RetroShader: Diffuse, Specular, Reflection, Alpha=DiffuseAlpha, IndirectTex */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, + TexLink("Alpha", 0, true)); + break; case 0x8E916C01: /* RetroShader: NULL, all inputs 0 */ - _GenerateRootShader(out, "RetroShader"); break; + _GenerateRootShader(out, "RetroShader"); + break; case 0x957709F8: /* RetroShader: Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Emissive"_tex); + break; case 0x96ABB2D3: /* RetroShader: Lightmap, Diffuse, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; case 0x985A0B67: /* RetroShader: Diffuse, UnusedSpecular?, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); + break; case 0x9B4453A2: /* RetroShader: Diffuse, Emissive, ExtendedSpecular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); + break; case 0xA187C630: /* RetroShader: Diffuse, Emissive, UnusedReflection?, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); + break; case 0xC138DCFA: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); + break; case 0xC3C8B1C8: /* RetroShader: KColorDiffuse, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_kcola); + break; case 0xC689C8C6: /* RetroShader: Diffuse, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, + TexLink("Alpha", 0, true)); + break; case 0xC6B18B28: /* RetroShader: Diffuse, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); + break; case 0xCD92D4C5: /* RetroShader: Diffuse, Reflection, Alpha=KAlpha */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, WhiteColorLink("Specular"), "Reflection"_tex, "Alpha"_kcola); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, WhiteColorLink("Specular"), "Reflection"_tex, "Alpha"_kcola); + break; case 0xD73E7728: /* RetroShader: ObjLightmap, Diffuse, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; case 0xDB8F01AD: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, UnusedSpecular?, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); + break; case 0xE6784B10: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha, IndirectTex */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, + "IndirectTex"_tex, TexLink("Alpha", 1, true)); + break; case 0xE68FF182: /* RetroShader: Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); + break; case 0xEB4645CF: /* RetroDynamicAlphaShader: Diffuse*Dynamic, Alpha=DiffuseAlpha*Dynamic */ - _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; + _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); + break; case 0xECEF8D1F: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); + break; case 0xF1C26570: /* RetroShader: Lightmap, Diffuse, Specular, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "ExtendedSpecular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "ExtendedSpecular"_tex, + "Reflection"_tex, TexLink("Alpha", 1, true)); + break; case 0xF559DB08: /* RetroShader: Lightmap, Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, + "Reflection"_tex); + break; case 0xF9324367: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); + break; case 0xFD95D7FD: /* RetroShader: ObjLightmap, Diffuse, Alpha=DiffuseAlpha */ - _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; default: _DescribeTEV(material); - Log.report(logvisor::Fatal, fmt("Unable to resolve shader hash {:08X}\n"), hash); break; + Log.report(logvisor::Fatal, fmt("Unable to resolve shader hash {:08X}\n"), hash); + break; } /* Has Lightmap? */ @@ -682,8 +868,7 @@ void MaterialSet::ConstructMaterial(Stream& out, const MaterialSet::Material& ma _ConstructMaterial(out, material, groupIdx, matIdx); } -MaterialSet::Material::Material(const hecl::blender::Material& mat, - std::vector& texPathsOut, +MaterialSet::Material::Material(const hecl::blender::Material& mat, std::vector& texPathsOut, int colorCount, bool lightmapUVs, bool matrixSkinning) { /* TODO: Rewrite for new shader rep */ XXH32_state_t xxHash; @@ -1090,7 +1275,6 @@ void HMDLMaterialSet::Material::PASS::Enumerate(typename Op::StreamT& s) { AT_SPECIALIZE_DNA(HMDLMaterialSet::Material::PASS) - std::string_view HMDLMaterialSet::Material::PASS::DNAType() { return "DataSpec::DNAMP1::HMDLMaterialSet::Material::PASS"sv; } diff --git a/DataSpec/DNAMP2/CINF.cpp b/DataSpec/DNAMP2/CINF.cpp index ab7cb48ab..f0b5f39b7 100644 --- a/DataSpec/DNAMP2/CINF.cpp +++ b/DataSpec/DNAMP2/CINF.cpp @@ -79,4 +79,121 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return fmt::format(fmt("CINF_{}"), cinfId); } +int CINF::RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId, + std::unordered_map& idMap, + std::map& nameMap) { + int selId; + auto search = idMap.find(bone->name); + if (search == idMap.end()) { + selId = curId++; + idMap.emplace(std::make_pair(bone->name, selId)); + } else + selId = search->second; + + bones.emplace_back(); + Bone& boneOut = bones.back(); + nameMap[bone->name] = selId; + boneOut.id = selId; + boneOut.parentId = parent; + boneOut.origin = bone->origin; + boneOut.linkedCount = bone->children.size() + 1; + boneOut.linked.reserve(boneOut.linkedCount); + + const BlenderBone* child; + boneOut.linked.push_back(parent); + for (size_t i = 0; (child = armature.getChild(bone, i)); ++i) + boneOut.linked.push_back(RecursiveAddArmatureBone(armature, child, boneOut.id, curId, idMap, nameMap)); + + return boneOut.id; +} + +CINF::CINF(const Armature& armature, std::unordered_map& idMap) { + idMap.reserve(armature.bones.size()); + bones.reserve(armature.bones.size()); + + std::map nameMap; + + const BlenderBone* bone = armature.getRoot(); + if (bone) { + if (bone->children.size()) { + int curId = 4; + const BlenderBone* child; + for (size_t i = 0; (child = armature.getChild(bone, i)); ++i) + RecursiveAddArmatureBone(armature, child, 3, curId, idMap, nameMap); + } + + bones.emplace_back(); + Bone& boneOut = bones.back(); + nameMap[bone->name] = 3; + boneOut.id = 3; + boneOut.parentId = 2; + boneOut.origin = bone->origin; + idMap.emplace(std::make_pair(bone->name, 3)); + + if (bone->children.size()) { + boneOut.linkedCount = 2; + boneOut.linked = {2, 4}; + } else { + boneOut.linkedCount = 1; + boneOut.linked = {2}; + } + } + + boneCount = bones.size(); + + names.reserve(nameMap.size()); + nameCount = nameMap.size(); + for (const auto& name : nameMap) { + names.emplace_back(); + Name& nameOut = names.back(); + nameOut.name = name.first; + nameOut.boneId = name.second; + } + + boneIdCount = boneCount; + boneIds.reserve(boneIdCount); + for (auto it = bones.crbegin(); it != bones.crend(); ++it) + boneIds.push_back(it->id); +} + +bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + if (!force && outPath.isFile()) + return true; + + auto& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::Armature)) + return false; + auto os = conn.beginPythonOut(true); + + os.format(fmt("import bpy\n" + "from mathutils import Vector\n" + "bpy.context.scene.name = 'CINF_{}'\n" + "bpy.context.scene.hecl_arm_obj = bpy.context.scene.name\n" + "\n" + "# Clear Scene\n" + "if len(bpy.data.collections):\n" + " bpy.data.collections.remove(bpy.data.collections[0])\n" + "\n"), entry.id); + + CINF cinf; + cinf.read(rs); + cinf.sendCINFToBlender(os, entry.id); + os.centerView(); + os.close(); + return conn.saveBlend(); +} + +bool CINF::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const hecl::blender::Armature& armature) { + std::unordered_map boneIdMap; + CINF cinf(armature, boneIdMap); + + /* Write out CINF resource */ + athena::io::TransactionalFileWriter w(outPath.getAbsolutePath()); + cinf.write(w); + return true; +} + } // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/CINF.hpp b/DataSpec/DNAMP2/CINF.hpp index 6cebbd0c1..5f3637477 100644 --- a/DataSpec/DNAMP2/CINF.hpp +++ b/DataSpec/DNAMP2/CINF.hpp @@ -2,6 +2,7 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DataSpec/DNACommon/RigInverter.hpp" +#include "DNAMP2.hpp" namespace DataSpec::DNAMP2 { @@ -37,6 +38,22 @@ struct CINF : BigDNA { void sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const; void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const; static std::string GetCINFArmatureName(const UniqueID32& cinfId); + + CINF() = default; + using Armature = hecl::blender::Armature; + using BlenderBone = hecl::blender::Bone; + + int RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId, + std::unordered_map& idMap, std::map& nameMap); + + CINF(const Armature& armature, std::unordered_map& idMap); + + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged); + + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const hecl::blender::Armature& armature); }; } // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index 1f6027844..d95d84fe1 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -4,6 +4,7 @@ #include "MLVL.hpp" #include "CMDL.hpp" #include "ANCS.hpp" +#include "CINF.hpp" #include "MREA.hpp" #include "MAPA.hpp" #include "MAPU.hpp" @@ -234,6 +235,8 @@ ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, con return {SAVWCommon::ExtractSAVW, {_SYS_STR(".yaml")}}; case SBIG('CMDL'): return {CMDL::Extract, {_SYS_STR(".blend")}, 1}; + case SBIG('CINF'): + return {CINF::Extract, {_SYS_STR(".blend")}, 1}; case SBIG('ANCS'): return {ANCS::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; case SBIG('MLVL'): diff --git a/DataSpec/DNAMP2/DeafBabe.cpp b/DataSpec/DNAMP2/DeafBabe.cpp index 36a5e9b3c..e1c699914 100644 --- a/DataSpec/DNAMP2/DeafBabe.cpp +++ b/DataSpec/DNAMP2/DeafBabe.cpp @@ -26,12 +26,15 @@ void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) { " 'Rubber':(0.09, 0.02, 0.01)}\n" "\n" "# Diffuse Color Maker\n" + "from mathutils import Color\n" "def make_color(index, mat_type, name):\n" " new_mat = bpy.data.materials.new(name)\n" " if mat_type in TYPE_COLORS:\n" - " new_mat.diffuse_color = TYPE_COLORS[mat_type]\n" + " new_mat.diffuse_color = TYPE_COLORS[mat_type] + (1.0,)\n" " else:\n" - " new_mat.diffuse_color.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n" + " col = Color()\n" + " col.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n" + " new_mat.diffuse_color = tuple(col) + (1.0,)\n" " return new_mat\n" "\n" "bpy.types.Material.retro_unknown = bpy.props.BoolProperty(description='Retro: Unknown (U)')\n" From eb9efbf8c3058a8ee8faa7fbad3d60116a297b1e Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Tue, 17 Mar 2020 23:12:43 -0700 Subject: [PATCH 02/11] Initial PATH support for MP2 --- DataSpec/DNACommon/AROTBuilder.cpp | 8 +- DataSpec/DNACommon/AROTBuilder.hpp | 7 +- DataSpec/DNACommon/CMakeLists.txt | 2 + DataSpec/DNACommon/PATH.cpp | 222 ++++++++++++++++++++++++++++ DataSpec/DNACommon/PATH.hpp | 74 ++++++++++ DataSpec/DNAMP1/CMakeLists.txt | 1 - DataSpec/DNAMP1/PATH.cpp | 223 +---------------------------- DataSpec/DNAMP1/PATH.hpp | 76 +--------- DataSpec/DNAMP2/CMakeLists.txt | 1 + DataSpec/DNAMP2/DNAMP2.cpp | 27 ++++ DataSpec/DNAMP2/DNAMP2.hpp | 3 + DataSpec/DNAMP2/MREA.cpp | 17 +++ DataSpec/DNAMP2/MREA.hpp | 2 + DataSpec/DNAMP2/PATH.cpp | 26 ++++ DataSpec/DNAMP2/PATH.hpp | 14 ++ DataSpec/SpecMP1.cpp | 2 +- DataSpec/SpecMP2.cpp | 7 +- Runtime/MP1/MP1.hpp | 2 +- 18 files changed, 411 insertions(+), 303 deletions(-) create mode 100644 DataSpec/DNACommon/PATH.cpp create mode 100644 DataSpec/DNACommon/PATH.hpp create mode 100644 DataSpec/DNAMP2/PATH.cpp create mode 100644 DataSpec/DNAMP2/PATH.hpp diff --git a/DataSpec/DNACommon/AROTBuilder.cpp b/DataSpec/DNACommon/AROTBuilder.cpp index 52315572a..6cdc4a351 100644 --- a/DataSpec/DNACommon/AROTBuilder.cpp +++ b/DataSpec/DNACommon/AROTBuilder.cpp @@ -272,10 +272,10 @@ void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& look } } -void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB) { +void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB) { if (childNodes.empty()) { path.octree.emplace_back(); - DNAMP1::PATH::OctreeNode& n = path.octree.back(); + DNAPATH::PATH::OctreeNode& n = path.octree.back(); n.isLeaf = 1; n.aabb[0] = curAABB.min; n.aabb[1] = curAABB.max; @@ -401,12 +401,12 @@ std::pair, uint32_t> AROTBuilder::buildCol(const ColM return {std::move(ret), totalSize}; } -void AROTBuilder::buildPath(DNAMP1::PATH& path) { +void AROTBuilder::buildPath(DNAPATH::PATH& path) { /* Accumulate total AABB and gather region boxes */ std::vector regionBoxes; regionBoxes.reserve(path.regions.size()); zeus::CAABox fullAABB; - for (const DNAMP1::PATH::Region& r : path.regions) { + for (const DNAPATH::PATH::Region& r : path.regions) { regionBoxes.emplace_back(r.aabb[0], r.aabb[1]); fullAABB.accumulateBounds(regionBoxes.back()); } diff --git a/DataSpec/DNACommon/AROTBuilder.hpp b/DataSpec/DNACommon/AROTBuilder.hpp index 1ecabbce7..2ec6f4a57 100644 --- a/DataSpec/DNACommon/AROTBuilder.hpp +++ b/DataSpec/DNACommon/AROTBuilder.hpp @@ -7,10 +7,11 @@ #include namespace DataSpec { -namespace DNAMP1 { +namespace DNAPATH { struct PATH; } + struct AROTBuilder { using ColMesh = hecl::blender::ColMesh; @@ -42,13 +43,13 @@ struct AROTBuilder { void writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB); void pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount); - void pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB); + void pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); } rootNode; void build(std::vector>& secs, const zeus::CAABox& fullAabb, const std::vector& meshAabbs, const std::vector& meshes); std::pair, uint32_t> buildCol(const ColMesh& mesh, BspNodeType& rootOut); - void buildPath(DNAMP1::PATH& path); + void buildPath(DNAPATH::PATH& path); }; } // namespace DataSpec diff --git a/DataSpec/DNACommon/CMakeLists.txt b/DataSpec/DNACommon/CMakeLists.txt index 39a616532..4d77c84cf 100644 --- a/DataSpec/DNACommon/CMakeLists.txt +++ b/DataSpec/DNACommon/CMakeLists.txt @@ -4,6 +4,7 @@ make_dnalist(CMDL FSM2 MAPA MAPU + PATH MayaSpline EGMC SAVWCommon @@ -19,6 +20,7 @@ set(DNACOMMON_SOURCES CMDL.cpp MAPA.cpp MAPU.cpp + PATH.hpp PATH.cpp STRG.hpp STRG.cpp TXTR.hpp TXTR.cpp ANCS.hpp ANCS.cpp diff --git a/DataSpec/DNACommon/PATH.cpp b/DataSpec/DNACommon/PATH.cpp new file mode 100644 index 000000000..16a499d9e --- /dev/null +++ b/DataSpec/DNACommon/PATH.cpp @@ -0,0 +1,222 @@ +#include "PATH.hpp" +#include "hecl/Blender/Connection.hpp" +#include "zeus/CAABox.hpp" +#include "DataSpec/DNACommon/AROTBuilder.hpp" + +namespace DataSpec::DNAPATH { + +#define DUMP_OCTREE 0 + +#if DUMP_OCTREE +/* octree dumper */ +static void OutputOctreeNode(hecl::blender::PyOutStream& os, int idx, const zeus::CAABox& aabb) { + const zeus::CVector3f pos = aabb.center(); + const zeus::CVector3f extent = aabb.extents(); + os.format( + "obj = bpy.data.objects.new('Leaf_%d', None)\n" + "bpy.context.scene.collection.objects.link(obj)\n" + "obj.location = (%f,%f,%f)\n" + "obj.scale = (%f,%f,%f)\n" + "obj.empty_display_type = 'CUBE'\n" + "obj.layers[1] = True\n" + "obj.layers[0] = False\n", idx, + pos.x(), pos.y(), pos.z(), extent.x(), extent.y(), extent.z()); +} +#endif + +void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf, + const std::string& areaPath) { + /* Open Py Stream and read sections */ + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os << + "import bpy\n" + "import bmesh\n" + "from mathutils import Vector, Matrix\n" + "\n" + "bpy.types.Material.retro_path_idx_mask = bpy.props.IntProperty(name='Retro: Path Index Mask')\n" + "bpy.types.Material.retro_path_type_mask = bpy.props.IntProperty(name='Retro: Path Type Mask')\n" + "\n" + "material_dict = {}\n" + "material_index = []\n" + "def make_ground_material(idxMask):\n" + " mat = bpy.data.materials.new('Ground %X' % idxMask)\n" + " mat.diffuse_color = (0.8, 0.460, 0.194, 1.0)\n" + " return mat\n" + "def make_flyer_material(idxMask):\n" + " mat = bpy.data.materials.new('Flyer %X' % idxMask)\n" + " mat.diffuse_color = (0.016, 0.8, 0.8, 1.0)\n" + " return mat\n" + "def make_swimmer_material(idxMask):\n" + " mat = bpy.data.materials.new('Swimmer %X' % idxMask)\n" + " mat.diffuse_color = (0.074, 0.293, 0.8, 1.0)\n" + " return mat\n" + "def select_material(meshIdxMask, meshTypeMask):\n" + " key = (meshIdxMask, meshTypeMask)\n" + " if key in material_index:\n" + " return material_index.index(key)\n" + " elif key in material_dict:\n" + " material_index.append(key)\n" + " return len(material_index)-1\n" + " else:\n" + " if meshTypeMask == 0x2:\n" + " mat = make_flyer_material(meshIdxMask)\n" + " elif meshTypeMask == 0x4:\n" + " mat = make_swimmer_material(meshIdxMask)\n" + " else:\n" + " mat = make_ground_material(meshIdxMask)\n" + " mat.retro_path_idx_mask = meshIdxMask\n" + " mat.retro_path_type_mask = meshTypeMask\n" + " material_dict[key] = mat\n" + " material_index.append(key)\n" + " return len(material_index)-1\n" + "\n"; + os.format(fmt("bpy.context.scene.name = '{}'\n"), entryName); + os << + "# Clear Scene\n" + "if len(bpy.data.collections):\n" + " bpy.data.collections.remove(bpy.data.collections[0])\n" + "\n" + "bm = bmesh.new()\n" + "height_lay = bm.faces.layers.float.new('Height')\n"; + + for (const Node& n : nodes) { + zeus::simd_floats f(n.position.simd); + os.format(fmt("bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]); + } + + os << "bm.verts.ensure_lookup_table()\n"; + + for (const Region& r : regions) { + os << "tri_verts = []\n"; + for (atUint32 i = 0; i < r.nodeCount; ++i) + os.format(fmt("tri_verts.append(bm.verts[{}])\n"), r.nodeStart + i); + + os.format(fmt( + "face = bm.faces.get(tri_verts)\n" + "if face is None:\n" + " face = bm.faces.new(tri_verts)\n" + " face.normal_flip()\n" + "face.material_index = select_material(0x{:04X}, 0x{:04X})\n" + "face.smooth = False\n" + "face[height_lay] = {}\n" + "\n"), + r.meshIndexMask, r.meshTypeMask, r.height); + +#if 0 + const zeus::CVector3f center = xf->multiplyOneOverW(r.centroid); + zeus::CAABox aabb(xf->multiplyOneOverW(r.aabb[0]), xf->multiplyOneOverW(r.aabb[1])); + os.format(fmt("aabb = bpy.data.objects.new('AABB', None)\n") + "aabb.location = (%f,%f,%f)\n" + "aabb.scale = (%f,%f,%f)\n" + "aabb.empty_display_type = 'CUBE'\n" + "bpy.context.scene.collection.objects.link(aabb)\n" + "centr = bpy.data.objects.new('Center', None)\n" + "centr.location = (%f,%f,%f)\n" + "bpy.context.scene.collection.objects.link(centr)\n", + aabb.min[0] + (aabb.max[0] - aabb.min[0]) / 2.f, + aabb.min[1] + (aabb.max[1] - aabb.min[1]) / 2.f, + aabb.min[2] + (aabb.max[2] - aabb.min[2]) / 2.f, + (aabb.max[0] - aabb.min[0]) / 2.f, + (aabb.max[1] - aabb.min[1]) / 2.f, + (aabb.max[2] - aabb.min[2]) / 2.f, + center.x(), center.y(), center.z()); +#endif + } + +#if 0 + for (const Node& n : nodes) { + zeus::simd_floats f(n.position.simd); + zeus::simd_floats no(n.position.simd + n.normal.simd); + os.format(fmt("v = bm.verts.new((%f,%f,%f))\n") + "v2 = bm.verts.new((%f,%f,%f))\n" + "bm.edges.new((v, v2))\n", f[0], f[1], f[2], no[0], no[1], no[2]); + } +#endif + + os << "bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)\n" + "path_mesh = bpy.data.meshes.new('PATH')\n" + "bm.to_mesh(path_mesh)\n" + "path_mesh_obj = bpy.data.objects.new(path_mesh.name, path_mesh)\n" + "\n" + "for mat_name in material_index:\n" + " mat = material_dict[mat_name]\n" + " path_mesh.materials.append(mat)\n" + "\n" + "bpy.context.scene.collection.objects.link(path_mesh_obj)\n" + "path_mesh_obj.display_type = 'SOLID'\n" + "bpy.context.scene.hecl_path_obj = path_mesh_obj.name\n" + "\n"; + + if (xf) { + const zeus::CMatrix4f& w = *xf; + zeus::simd_floats xfMtxF[4]; + for (int i = 0; i < 4; ++i) + w.m[i].mSimd.copy_to(xfMtxF[i]); + os.format(fmt( + "mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "path_mesh_obj.rotation_mode = 'QUATERNION'\n" + "path_mesh_obj.location = mtxd[0]\n" + "path_mesh_obj.rotation_quaternion = mtxd[1]\n" + "path_mesh_obj.scale = mtxd[2]\n"), + xfMtxF[0][0], xfMtxF[1][0], xfMtxF[2][0], xfMtxF[3][0], xfMtxF[0][1], xfMtxF[1][1], xfMtxF[2][1], xfMtxF[3][1], + xfMtxF[0][2], xfMtxF[1][2], xfMtxF[2][2], xfMtxF[3][2]); + } + +#if DUMP_OCTREE + { + int idx = 0; + for (const auto& n : octree) { + if (n.isLeaf) + OutputOctreeNode(os, idx, zeus::CAABox(n.aabb[0], n.aabb[1])); + ++idx; + } + } +#endif + + os.linkBackground(fmt::format(fmt("//{}"), areaPath)); + os.centerView(); + os.close(); +} + +bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const PathMesh& mesh, hecl::blender::Token& btok) { + athena::io::MemoryReader r(mesh.data.data(), mesh.data.size()); + PATH path; + path.read(r); + if (!path.regions.empty()) { + AROTBuilder octreeBuilder; + octreeBuilder.buildPath(path); + } else { + path.octreeNodeCount = 1; + path.octree.emplace_back(); + OctreeNode& n = path.octree.back(); + n.isLeaf = 1; + n.aabb[0] = zeus::CVector3f{FLT_MAX, FLT_MAX, FLT_MAX}; + n.aabb[1] = zeus::CVector3f{-FLT_MAX, -FLT_MAX, -FLT_MAX}; + for (int i = 0; i < 8; ++i) + n.children[i] = 0xffffffff; + } + +#if DUMP_OCTREE + { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".octree.blend"), true), hecl::blender::BlendType::PathMesh)) + return false; + + zeus::CMatrix4f xf; + path.sendToBlender(conn, "PATH"sv, &xf); + conn.saveBlend(); + } +#endif + + athena::io::FileWriter w(outPath.getAbsolutePath()); + path.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; +} + +} // namespace DataSpec::DNAMP1 \ No newline at end of file diff --git a/DataSpec/DNACommon/PATH.hpp b/DataSpec/DNACommon/PATH.hpp new file mode 100644 index 000000000..67dc2e64d --- /dev/null +++ b/DataSpec/DNACommon/PATH.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include "DataSpec/DNACommon/DNACommon.hpp" +#include "DataSpec/DNACommon/PAK.hpp" + +namespace DataSpec::DNAPATH { +struct PATH : BigDNA { + using PathMesh = hecl::blender::PathMesh; + + AT_DECL_DNA + Value version; + + struct Node : BigDNA { + AT_DECL_DNA + Value position; + Value normal; + }; + Value nodeCount; + Vector nodes; + + struct Link : BigDNA { + AT_DECL_DNA + Value nodeIdx; + Value regionIdx; + Value width2d; + Value oneOverWidth2d; + }; + Value linkCount; + Vector links; + + struct Region : BigDNA { + AT_DECL_DNA + Value nodeCount; + Value nodeStart; + Value linkCount; + Value linkStart; + Value meshIndexMask; + Value meshTypeMask; + Value height; + Value normal; + Value regionIdx; + Value centroid; + Value aabb[2]; + Value regionIdxPtr; + }; + Value regionCount; + Vector regions; + + Vector bitmap1; + Vector bitmap2; + Vector bitmap3; + + Value octreeRegionLookupCount; + Vector octreeRegionLookup; + + struct OctreeNode : BigDNA { + AT_DECL_DNA + Value isLeaf; + Value aabb[2]; + Value centroid; + Value children[8]; + Value regionCount; + Value regionStart; + }; + Value octreeNodeCount; + Vector octree; + + void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf, + const std::string& areaPath); + + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const PathMesh& mesh, hecl::blender::Token& btok); +}; +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/CMakeLists.txt b/DataSpec/DNAMP1/CMakeLists.txt index 3520e76c4..12f703bbb 100644 --- a/DataSpec/DNAMP1/CMakeLists.txt +++ b/DataSpec/DNAMP1/CMakeLists.txt @@ -11,7 +11,6 @@ make_dnalist(PAK CINF CSKR EVNT - PATH CMDLMaterials MREA DeafBabe diff --git a/DataSpec/DNAMP1/PATH.cpp b/DataSpec/DNAMP1/PATH.cpp index 506995484..68dd16fdf 100644 --- a/DataSpec/DNAMP1/PATH.cpp +++ b/DataSpec/DNAMP1/PATH.cpp @@ -1,184 +1,8 @@ -#include "PATH.hpp" -#include "hecl/Blender/Connection.hpp" -#include "zeus/CAABox.hpp" +#include "DataSpec/DNAMP1/PATH.hpp" #include "DataSpec/DNACommon/AROTBuilder.hpp" +#include "hecl/Blender/Connection.hpp" namespace DataSpec::DNAMP1 { - -#define DUMP_OCTREE 0 - -#if DUMP_OCTREE -/* octree dumper */ -static void OutputOctreeNode(hecl::blender::PyOutStream& os, int idx, const zeus::CAABox& aabb) { - const zeus::CVector3f pos = aabb.center(); - const zeus::CVector3f extent = aabb.extents(); - os.format( - "obj = bpy.data.objects.new('Leaf_%d', None)\n" - "bpy.context.scene.collection.objects.link(obj)\n" - "obj.location = (%f,%f,%f)\n" - "obj.scale = (%f,%f,%f)\n" - "obj.empty_display_type = 'CUBE'\n" - "obj.layers[1] = True\n" - "obj.layers[0] = False\n", idx, - pos.x(), pos.y(), pos.z(), extent.x(), extent.y(), extent.z()); -} -#endif - -void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf, - const std::string& areaPath) { - /* Open Py Stream and read sections */ - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os << - "import bpy\n" - "import bmesh\n" - "from mathutils import Vector, Matrix\n" - "\n" - "bpy.types.Material.retro_path_idx_mask = bpy.props.IntProperty(name='Retro: Path Index Mask')\n" - "bpy.types.Material.retro_path_type_mask = bpy.props.IntProperty(name='Retro: Path Type Mask')\n" - "\n" - "material_dict = {}\n" - "material_index = []\n" - "def make_ground_material(idxMask):\n" - " mat = bpy.data.materials.new('Ground %X' % idxMask)\n" - " mat.diffuse_color = (0.8, 0.460, 0.194, 1.0)\n" - " return mat\n" - "def make_flyer_material(idxMask):\n" - " mat = bpy.data.materials.new('Flyer %X' % idxMask)\n" - " mat.diffuse_color = (0.016, 0.8, 0.8, 1.0)\n" - " return mat\n" - "def make_swimmer_material(idxMask):\n" - " mat = bpy.data.materials.new('Swimmer %X' % idxMask)\n" - " mat.diffuse_color = (0.074, 0.293, 0.8, 1.0)\n" - " return mat\n" - "def select_material(meshIdxMask, meshTypeMask):\n" - " key = (meshIdxMask, meshTypeMask)\n" - " if key in material_index:\n" - " return material_index.index(key)\n" - " elif key in material_dict:\n" - " material_index.append(key)\n" - " return len(material_index)-1\n" - " else:\n" - " if meshTypeMask == 0x2:\n" - " mat = make_flyer_material(meshIdxMask)\n" - " elif meshTypeMask == 0x4:\n" - " mat = make_swimmer_material(meshIdxMask)\n" - " else:\n" - " mat = make_ground_material(meshIdxMask)\n" - " mat.retro_path_idx_mask = meshIdxMask\n" - " mat.retro_path_type_mask = meshTypeMask\n" - " material_dict[key] = mat\n" - " material_index.append(key)\n" - " return len(material_index)-1\n" - "\n"; - os.format(fmt("bpy.context.scene.name = '{}'\n"), entryName); - os << - "# Clear Scene\n" - "if len(bpy.data.collections):\n" - " bpy.data.collections.remove(bpy.data.collections[0])\n" - "\n" - "bm = bmesh.new()\n" - "height_lay = bm.faces.layers.float.new('Height')\n"; - - for (const Node& n : nodes) { - zeus::simd_floats f(n.position.simd); - os.format(fmt("bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]); - } - - os << "bm.verts.ensure_lookup_table()\n"; - - for (const Region& r : regions) { - os << "tri_verts = []\n"; - for (atUint32 i = 0; i < r.nodeCount; ++i) - os.format(fmt("tri_verts.append(bm.verts[{}])\n"), r.nodeStart + i); - - os.format(fmt( - "face = bm.faces.get(tri_verts)\n" - "if face is None:\n" - " face = bm.faces.new(tri_verts)\n" - " face.normal_flip()\n" - "face.material_index = select_material(0x{:04X}, 0x{:04X})\n" - "face.smooth = False\n" - "face[height_lay] = {}\n" - "\n"), - r.meshIndexMask, r.meshTypeMask, r.height); - -#if 0 - const zeus::CVector3f center = xf->multiplyOneOverW(r.centroid); - zeus::CAABox aabb(xf->multiplyOneOverW(r.aabb[0]), xf->multiplyOneOverW(r.aabb[1])); - os.format(fmt("aabb = bpy.data.objects.new('AABB', None)\n") - "aabb.location = (%f,%f,%f)\n" - "aabb.scale = (%f,%f,%f)\n" - "aabb.empty_display_type = 'CUBE'\n" - "bpy.context.scene.collection.objects.link(aabb)\n" - "centr = bpy.data.objects.new('Center', None)\n" - "centr.location = (%f,%f,%f)\n" - "bpy.context.scene.collection.objects.link(centr)\n", - aabb.min[0] + (aabb.max[0] - aabb.min[0]) / 2.f, - aabb.min[1] + (aabb.max[1] - aabb.min[1]) / 2.f, - aabb.min[2] + (aabb.max[2] - aabb.min[2]) / 2.f, - (aabb.max[0] - aabb.min[0]) / 2.f, - (aabb.max[1] - aabb.min[1]) / 2.f, - (aabb.max[2] - aabb.min[2]) / 2.f, - center.x(), center.y(), center.z()); -#endif - } - -#if 0 - for (const Node& n : nodes) { - zeus::simd_floats f(n.position.simd); - zeus::simd_floats no(n.position.simd + n.normal.simd); - os.format(fmt("v = bm.verts.new((%f,%f,%f))\n") - "v2 = bm.verts.new((%f,%f,%f))\n" - "bm.edges.new((v, v2))\n", f[0], f[1], f[2], no[0], no[1], no[2]); - } -#endif - - os << "bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)\n" - "path_mesh = bpy.data.meshes.new('PATH')\n" - "bm.to_mesh(path_mesh)\n" - "path_mesh_obj = bpy.data.objects.new(path_mesh.name, path_mesh)\n" - "\n" - "for mat_name in material_index:\n" - " mat = material_dict[mat_name]\n" - " path_mesh.materials.append(mat)\n" - "\n" - "bpy.context.scene.collection.objects.link(path_mesh_obj)\n" - "path_mesh_obj.display_type = 'SOLID'\n" - "bpy.context.scene.hecl_path_obj = path_mesh_obj.name\n" - "\n"; - - if (xf) { - const zeus::CMatrix4f& w = *xf; - zeus::simd_floats xfMtxF[4]; - for (int i = 0; i < 4; ++i) - w.m[i].mSimd.copy_to(xfMtxF[i]); - os.format(fmt( - "mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "path_mesh_obj.rotation_mode = 'QUATERNION'\n" - "path_mesh_obj.location = mtxd[0]\n" - "path_mesh_obj.rotation_quaternion = mtxd[1]\n" - "path_mesh_obj.scale = mtxd[2]\n"), - xfMtxF[0][0], xfMtxF[1][0], xfMtxF[2][0], xfMtxF[3][0], xfMtxF[0][1], xfMtxF[1][1], xfMtxF[2][1], xfMtxF[3][1], - xfMtxF[0][2], xfMtxF[1][2], xfMtxF[2][2], xfMtxF[3][2]); - } - -#if DUMP_OCTREE - { - int idx = 0; - for (const auto& n : octree) { - if (n.isLeaf) - OutputOctreeNode(os, idx, zeus::CAABox(n.aabb[0], n.aabb[1])); - ++idx; - } - } -#endif - - os.linkBackground(fmt::format(fmt("//{}"), areaPath)); - os.centerView(); - os.close(); -} - bool PATH::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, std::function fileChanged) { @@ -200,45 +24,4 @@ bool PATH::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf, areaPath); return conn.saveBlend(); } - -bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, - const PathMesh& mesh, hecl::blender::Token& btok) { - athena::io::MemoryReader r(mesh.data.data(), mesh.data.size()); - PATH path; - path.read(r); - if (!path.regions.empty()) { - AROTBuilder octreeBuilder; - octreeBuilder.buildPath(path); - } else { - path.octreeNodeCount = 1; - path.octree.emplace_back(); - OctreeNode& n = path.octree.back(); - n.isLeaf = 1; - n.aabb[0] = zeus::CVector3f{FLT_MAX, FLT_MAX, FLT_MAX}; - n.aabb[1] = zeus::CVector3f{-FLT_MAX, -FLT_MAX, -FLT_MAX}; - for (int i = 0; i < 8; ++i) - n.children[i] = 0xffffffff; - } - -#if DUMP_OCTREE - { - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".octree.blend"), true), hecl::blender::BlendType::PathMesh)) - return false; - - zeus::CMatrix4f xf; - path.sendToBlender(conn, "PATH"sv, &xf); - conn.saveBlend(); - } -#endif - - athena::io::FileWriter w(outPath.getAbsolutePath()); - path.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i = 0; i < 32 - rem; ++i) - w.writeUByte(0xff); - return true; -} - -} // namespace DataSpec::DNAMP1 \ No newline at end of file +} \ No newline at end of file diff --git a/DataSpec/DNAMP1/PATH.hpp b/DataSpec/DNAMP1/PATH.hpp index 284a27fa0..5b954559b 100644 --- a/DataSpec/DNAMP1/PATH.hpp +++ b/DataSpec/DNAMP1/PATH.hpp @@ -1,79 +1,11 @@ #pragma once - -#include "DataSpec/DNACommon/DNACommon.hpp" -#include "DataSpec/DNACommon/PAK.hpp" -#include "DNAMP1.hpp" +#include "DataSpec/DNACommon/PATH.hpp" +#include "DataSpec/DNAMP1/DNAMP1.hpp" namespace DataSpec::DNAMP1 { -struct PATH : BigDNA { - using PathMesh = hecl::blender::PathMesh; - - AT_DECL_DNA - Value version; - - struct Node : BigDNA { - AT_DECL_DNA - Value position; - Value normal; - }; - Value nodeCount; - Vector nodes; - - struct Link : BigDNA { - AT_DECL_DNA - Value nodeIdx; - Value regionIdx; - Value width2d; - Value oneOverWidth2d; - }; - Value linkCount; - Vector links; - - struct Region : BigDNA { - AT_DECL_DNA - Value nodeCount; - Value nodeStart; - Value linkCount; - Value linkStart; - Value meshIndexMask; - Value meshTypeMask; - Value height; - Value normal; - Value regionIdx; - Value centroid; - Value aabb[2]; - Value regionIdxPtr; - }; - Value regionCount; - Vector regions; - - Vector bitmap1; - Vector bitmap2; - Vector bitmap3; - - Value octreeRegionLookupCount; - Vector octreeRegionLookup; - - struct OctreeNode : BigDNA { - AT_DECL_DNA - Value isLeaf; - Value aabb[2]; - Value centroid; - Value children[8]; - Value regionCount; - Value regionStart; - }; - Value octreeNodeCount; - Vector octree; - - void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf, - const std::string& areaPath); - +struct PATH : DNAPATH::PATH { static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, std::function fileChanged); - - static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, - const PathMesh& mesh, hecl::blender::Token& btok); }; -} // namespace DataSpec::DNAMP1 +} // namespace DataSpec::DNAMP1 \ No newline at end of file diff --git a/DataSpec/DNAMP2/CMakeLists.txt b/DataSpec/DNAMP2/CMakeLists.txt index 504d14541..84b43fe51 100644 --- a/DataSpec/DNAMP2/CMakeLists.txt +++ b/DataSpec/DNAMP2/CMakeLists.txt @@ -23,6 +23,7 @@ set(DNAMP2_SOURCES MREA.cpp MAPA.hpp MAPU.hpp + PATH.hpp PATH.cpp AFSM.hpp STRG.hpp STRG.cpp) diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index d95d84fe1..679a0e8cf 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -8,6 +8,7 @@ #include "MREA.hpp" #include "MAPA.hpp" #include "MAPU.hpp" +#include "PATH.hpp" #include "AFSM.hpp" #include "SAVW.hpp" #include "AGSC.hpp" @@ -171,6 +172,18 @@ void PAKBridge::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssoci } } +void PAKBridge::addPATHToMREA(PAKRouter& pakRouter, + std::unordered_map& pathToMrea) const { + for (const auto& [id, entry] : m_pak.m_entries) { + if (entry.type == FOURCC('MREA')) { + PAKEntryReadStream rs = entry.beginReadStream(m_node); + UniqueID32 pathID = MREA::GetPATHId(rs); + if (pathID.isValid()) + pathToMrea[pathID] = id; + } + } +} + static const atVec4f BottomRow = {{0.f, 0.f, 0.f, 1.f}}; void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, @@ -190,6 +203,18 @@ void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId)); for (const MLVL::Area& area : mlvl.areas) { +#if 0 + { + /* Get PATH transform */ + const nod::Node* areaNode; + const PAK::Entry* areaEntry = pakRouter.lookupEntry(area.areaMREAId, &areaNode); + PAKEntryReadStream rs = areaEntry->beginReadStream(*areaNode); + UniqueID32 pathId = MREA::GetPATHId(rs); + if (pathId.isValid()) + addTo[pathId] = zeus::CMatrix4f(area.transformMtx[0], area.transformMtx[1], area.transformMtx[2], BottomRow) + .transposed(); + } +#endif hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath(); if (area.areaNameId.isValid()) pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, @@ -247,6 +272,8 @@ ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, con return {MAPA::Extract, {_SYS_STR(".blend")}, 4}; case SBIG('MAPU'): return {MAPU::Extract, {_SYS_STR(".blend")}, 5}; +// case SBIG('PATH'): +// return {PATH::Extract, {_SYS_STR(".blend")}, 5}; case SBIG('FSM2'): return {DNAFSM2::ExtractFSM2, {_SYS_STR(".yaml")}}; case SBIG('FONT'): diff --git a/DataSpec/DNAMP2/DNAMP2.hpp b/DataSpec/DNAMP2/DNAMP2.hpp index 279bba2c3..ee62edc12 100644 --- a/DataSpec/DNAMP2/DNAMP2.hpp +++ b/DataSpec/DNAMP2/DNAMP2.hpp @@ -31,6 +31,9 @@ public: void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; + void addPATHToMREA(PAKRouter& pakRouter, + std::unordered_map& pathToMrea) const; + void addMAPATransforms(PAKRouter& pakRouter, std::unordered_map& addTo, std::unordered_map& pathOverrides) const; }; diff --git a/DataSpec/DNAMP2/MREA.cpp b/DataSpec/DNAMP2/MREA.cpp index ba2bd6adb..01c39e07a 100644 --- a/DataSpec/DNAMP2/MREA.cpp +++ b/DataSpec/DNAMP2/MREA.cpp @@ -296,5 +296,22 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: return conn.saveBlend(); } +UniqueID32 MREA::GetPATHId(PAKEntryReadStream& rs) { + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); + + /* Skip to PATH */ + atUint32 curSec = 0; + atUint64 secStart = rs.position(); + while (curSec != head.pathSecIdx) + secStart += head.secSizes[curSec++]; + if (!head.secSizes[curSec]) + return {}; + rs.seek(secStart, athena::SeekOrigin::Begin); + return {rs}; +} + } // namespace DNAMP2 } // namespace DataSpec diff --git a/DataSpec/DNAMP2/MREA.hpp b/DataSpec/DNAMP2/MREA.hpp index 5e678d5b7..6dd18b551 100644 --- a/DataSpec/DNAMP2/MREA.hpp +++ b/DataSpec/DNAMP2/MREA.hpp @@ -118,6 +118,8 @@ struct MREA { Value aabb[2]; }; + static UniqueID32 GetPATHId(PAKEntryReadStream& rs); + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, PAKRouter& pakRouter, const DNAMP2::PAK::Entry& entry, bool, hecl::blender::Token& btok, std::function); diff --git a/DataSpec/DNAMP2/PATH.cpp b/DataSpec/DNAMP2/PATH.cpp new file mode 100644 index 000000000..058fd5243 --- /dev/null +++ b/DataSpec/DNAMP2/PATH.cpp @@ -0,0 +1,26 @@ +#include "DataSpec/DNAMP2/PATH.hpp" +#include "hecl/Blender/Connection.hpp" + +namespace DataSpec::DNAMP2 { +bool PATH::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + PATH path; + path.read(rs); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::PathMesh)) + return false; + + std::string areaPath; + for (const auto& ent : hecl::DirectoryEnumerator(outPath.getParentPath().getAbsolutePath())) { + if (hecl::StringUtils::BeginsWith(ent.m_name, _SYS_STR("!area_"))) { + areaPath = hecl::SystemUTF8Conv(ent.m_name).str(); + break; + } + } + + const zeus::CMatrix4f* xf = pakRouter.lookupMAPATransform(entry.id); + path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf, areaPath); + return conn.saveBlend(); +} +} \ No newline at end of file diff --git a/DataSpec/DNAMP2/PATH.hpp b/DataSpec/DNAMP2/PATH.hpp new file mode 100644 index 000000000..fd8e0ab3e --- /dev/null +++ b/DataSpec/DNAMP2/PATH.hpp @@ -0,0 +1,14 @@ +#pragma once +#include "DataSpec/DNACommon/PATH.hpp" +#include "DataSpec/DNAMP2/DNAMP2.hpp" + +namespace DataSpec::DNAMP2 { +struct PATH : DNAPATH::PATH { + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged); + + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const PathMesh& mesh, hecl::blender::Token& btok); +}; +} \ No newline at end of file diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index ddf973351..4e0915763 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -661,7 +661,7 @@ struct SpecMP1 : SpecBase { hecl::blender::Token& btok, FCookProgress progress) override { PathMesh mesh = ds.compilePathMesh(); ds.close(); - DNAMP1::PATH::Cook(out, in, mesh, btok); + DNAPATH::PATH::Cook(out, in, mesh, btok); } void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, diff --git a/DataSpec/SpecMP2.cpp b/DataSpec/SpecMP2.cpp index 47a8e96cb..c6b76e313 100644 --- a/DataSpec/SpecMP2.cpp +++ b/DataSpec/SpecMP2.cpp @@ -9,6 +9,7 @@ #include "DNAMP2/MAPA.hpp" #include "DNAMP1/CSNG.hpp" #include "DNACommon/MAPU.hpp" +#include "DNACommon/PATH.hpp" #include "hecl/ClientProcess.hpp" #include "hecl/Blender/Connection.hpp" @@ -287,7 +288,11 @@ struct SpecMP2 : SpecBase { hecl::blender::Token& btok, FCookProgress progress) override {} void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, - hecl::blender::Token& btok, FCookProgress progress) override {} + hecl::blender::Token& btok, FCookProgress progress) override { + PathMesh mesh = ds.compilePathMesh(); + ds.close(); + DNAPATH::PATH::Cook(out, in, mesh, btok); + } void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, hecl::blender::Token& btok, FCookProgress progress) override {} diff --git a/Runtime/MP1/MP1.hpp b/Runtime/MP1/MP1.hpp index 397031000..cf25985ec 100644 --- a/Runtime/MP1/MP1.hpp +++ b/Runtime/MP1/MP1.hpp @@ -4,7 +4,7 @@ #define MP1_USE_BOO 0 #endif #ifndef MP1_VARIABLE_DELTA_TIME -#define MP1_VARIABLE_DELTA_TIME 0 +#define MP1_VARIABLE_DELTA_TIME 1 #endif #include "IMain.hpp" From 0c3d6c7f27bbb17ca6bedc3600e17ff96598824b Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Tue, 24 Mar 2020 23:13:31 -0700 Subject: [PATCH 03/11] Initiaal material imps --- DataSpec/DNAMP1/CMDLMaterials.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/DataSpec/DNAMP1/CMDLMaterials.cpp b/DataSpec/DNAMP1/CMDLMaterials.cpp index 61aac9a43..c6132182f 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.cpp +++ b/DataSpec/DNAMP1/CMDLMaterials.cpp @@ -568,6 +568,12 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0x2523A379: /* RetroDynamicShader: Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ _GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + case 0x07AA75D7: + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); + break; + case 0x03FEE002: + _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex); + break; case 0x25E85017: /* RetroShader: Lightmap, KColorDiffuse, Alpha=KAlpha */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break; @@ -610,12 +616,6 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0x54A92F25: /* RetroShader: ObjLightmap, KColorDiffuse, Alpha=KAlpha */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break; - case 0x07AA75D7: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV - HasIndirect: false HasLightmap: false - */ case 0x72BEDDAC: /* TODO: Properly implement TEV configuration: A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 @@ -625,13 +625,6 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI A:CC_ZERO B:CC_C2 C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV HasIndirect: false HasLightmap: true */ - case 0x03FEE002: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV - HasIndirect: false HasLightmap: false - */ case 0xF4DA0A86: /* TODO: Properly implement TEV configuration: A:CC_ZERO B:CC_RASC C:CC_KONST D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV From 5b0a4b5f606158466743bc5ebd7bae8192fe0345 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 8 Apr 2020 16:24:18 -1000 Subject: [PATCH 04/11] Implement MP2 shader extraction presets --- DataSpec/Blender/RetroMasterShader.py | 29 ++++- DataSpec/DNAMP1/CMDLMaterials.cpp | 169 +++++++++----------------- hecl | 2 +- 3 files changed, 83 insertions(+), 117 deletions(-) diff --git a/DataSpec/Blender/RetroMasterShader.py b/DataSpec/Blender/RetroMasterShader.py index 6e49ee676..3d13f9625 100644 --- a/DataSpec/Blender/RetroMasterShader.py +++ b/DataSpec/Blender/RetroMasterShader.py @@ -58,6 +58,8 @@ def make_retro_shader(): lightmap_input.default_value = (0.0, 0.0, 0.0, 0.0) diffuse_input = new_grp.inputs.new('NodeSocketColor', 'Diffuse') diffuse_input.default_value = (0.0, 0.0, 0.0, 0.0) + diffuse_mod_input = new_grp.inputs.new('NodeSocketColor', 'DiffuseMod') + diffuse_mod_input.default_value = (1.0, 1.0, 1.0, 1.0) emissive_input = new_grp.inputs.new('NodeSocketColor', 'Emissive') emissive_input.default_value = (0.0, 0.0, 0.0, 0.0) specular_input = new_grp.inputs.new('NodeSocketColor', 'Specular') @@ -72,6 +74,10 @@ def make_retro_shader(): alpha_input.default_value = 1.0 alpha_input.min_value = 0.0 alpha_input.max_value = 1.0 + alpha_mod_input = new_grp.inputs.new('NodeSocketFloatFactor', 'AlphaMod') + alpha_mod_input.default_value = 1.0 + alpha_mod_input.min_value = 0.0 + alpha_mod_input.max_value = 1.0 new_grp.use_fake_user = True # Group inputs @@ -108,6 +114,17 @@ def make_retro_shader(): new_shader_model_mix1 = new_grp.nodes.new('ShaderNodeMixShader') new_shader_model_mix1.location = (-760, 340) + # Multiply (Multiples diffuse with diffusemod) + diffuse_mult = new_grp.nodes.new('ShaderNodeMixRGB') + diffuse_mult.location = (-1094, 122) + diffuse_mult.blend_type = 'MULTIPLY' + diffuse_mult.inputs['Fac'].default_value = 1.0 + + # Multiply (Multiples alpha with alphamod) + alpha_mult = new_grp.nodes.new('ShaderNodeMath') + alpha_mult.location = (-1094, -178) + alpha_mult.operation = 'MULTIPLY' + # Multiply (Multiplies static lightmap with diffuse) lightmap_mult = new_grp.nodes.new('ShaderNodeMixRGB') lightmap_mult.location = (-944, 122) @@ -164,17 +181,21 @@ def make_retro_shader(): mat_out.location = (150, -88) # Links + new_grp.links.new(grp_in.outputs['Diffuse'], diffuse_mult.inputs['Color1']) + new_grp.links.new(grp_in.outputs['DiffuseMod'], diffuse_mult.inputs['Color2']) + new_grp.links.new(grp_in.outputs['Alpha'], alpha_mult.inputs[0]) + new_grp.links.new(grp_in.outputs['AlphaMod'], alpha_mult.inputs[1]) new_grp.links.new(grp_in.outputs['Lightmap'], lightmap_mult.inputs['Color1']) - new_grp.links.new(grp_in.outputs['Diffuse'], lightmap_mult.inputs['Color2']) - new_grp.links.new(grp_in.outputs['Diffuse'], diffuse_bdsf.inputs['Color']) - new_grp.links.new(grp_in.outputs['Diffuse'], principled_bsdf.inputs['Base Color']) + new_grp.links.new(diffuse_mult.outputs['Color'], lightmap_mult.inputs['Color2']) + new_grp.links.new(diffuse_mult.outputs['Color'], diffuse_bdsf.inputs['Color']) + new_grp.links.new(diffuse_mult.outputs['Color'], principled_bsdf.inputs['Base Color']) new_grp.links.new(grp_in.outputs['Emissive'], emissive_add_shader.inputs[0]) new_grp.links.new(grp_in.outputs['Specular'], specular_mult.inputs['Color1']) new_grp.links.new(grp_in.outputs['Specular'], principled_bsdf.inputs['Specular']) new_grp.links.new(grp_in.outputs['ExtendedSpecular'], extended_specular_mult.inputs['Color1']) new_grp.links.new(grp_in.outputs['Reflection'], specular_mult.inputs['Color2']) new_grp.links.new(grp_in.outputs['Reflection'], extended_specular_mult.inputs['Color2']) - new_grp.links.new(grp_in.outputs['Alpha'], alpha_mix.inputs['Fac']) + new_grp.links.new(alpha_mult.outputs[0], alpha_mix.inputs['Fac']) new_grp.links.new(new_shader_model.outputs['Value'], new_shader_model_mix1.inputs[0]) new_grp.links.new(diffuse_bdsf.outputs['BSDF'], new_shader_model_mix1.inputs[1]) new_grp.links.new(grp_in.outputs['Specular'], invert.inputs['Color']) diff --git a/DataSpec/DNAMP1/CMDLMaterials.cpp b/DataSpec/DNAMP1/CMDLMaterials.cpp index c6132182f..3e51255b6 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.cpp +++ b/DataSpec/DNAMP1/CMDLMaterials.cpp @@ -524,6 +524,9 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI /* Select appropriate root shader and link textures */ uint32_t hash = _HashTextureConfig(material); switch (hash) { + case 0x03FEE002: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Reflection"_tex); + break; case 0x0473AE40: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); break; @@ -531,6 +534,9 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break; + case 0x07AA75D7: /* RetroShader: Diffuse, Emissive, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 0, true)); + break; case 0x0879D346: /* RetroShader: KColorDiffuse, Alpha=Texture */ _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_tex); break; @@ -549,6 +555,10 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0x129B8578: /* RetroShader: KColorDiffuse, Emissive, Alpha=KAlpha */ _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola); break; + case 0x15A00948: /* RetroShader: Diffuse, Emissive, Specular, ExtendedSpecular, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "ExtendedSpecular"_tex, + "Reflection"_tex); + break; case 0x15A3E6E5: /* RetroShader: Diffuse, Alpha=KAlpha */ _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); break; @@ -568,12 +578,6 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0x2523A379: /* RetroDynamicShader: Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */ _GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; - case 0x07AA75D7: - _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); - break; - case 0x03FEE002: - _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex); - break; case 0x25E85017: /* RetroShader: Lightmap, KColorDiffuse, Alpha=KAlpha */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break; @@ -603,6 +607,9 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, "Alpha"_kcola); break; + case 0x4184FBCA: /* RetroShader: Lightmap, Diffuse, Emissive, DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 1, true)); + break; case 0x47ECF3ED: /* RetroShader: Diffuse, Specular, Reflection, Emissive, Alpha=1.0 */ _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Emissive"_tex); break; @@ -616,112 +623,10 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0x54A92F25: /* RetroShader: ObjLightmap, KColorDiffuse, Alpha=KAlpha */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break; - case 0x72BEDDAC: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 - A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_TEXC -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 - A:CC_ZERO B:CC_C2 C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV - HasIndirect: false HasLightmap: true - */ - case 0xF4DA0A86: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_RASC C:CC_KONST D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV - HasIndirect: false HasLightmap: false - */ - case 0xF345C16E: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV - HasIndirect: false HasLightmap: false - */ - case 0x8C562AB1: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV - HasIndirect: false HasLightmap: false - */ - case 0xE92F1340: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_TEXA C:CA_APREV D:CA_ZERO -> TEVPREV - HasIndirect: false HasLightmap: false - */ - case 0xCE06F3F2: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_TEXA C:CA_APREV D:CA_ZERO -> TEVPREV - HasIndirect: false HasLightmap: false - */ - case 0xC0E3FF1F: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_RASC C:CC_KONST D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_TEXC -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 - A:CC_ZERO B:CC_C2 C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV - HasIndirect: false HasLightmap: false - */ - case 0xFC2761B8: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_RASC -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 - A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_TEXA C:CA_APREV D:CA_ZERO -> TEVPREV - HasIndirect: false HasLightmap: true - */ - case 0xE64D1085: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_RASC -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 - A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV - HasIndirect: false HasLightmap: true - */ - case 0xB26E9E2E: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_TEXC -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 - A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_C2 -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 - HasIndirect: false HasLightmap: false - */ - case 0x4184FBCA: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_RASC -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 - A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_ONE C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV - HasIndirect: false HasLightmap: true - */ - case 0x81106196: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - HasIndirect: false HasLightmap: false - */ - case 0x15A00948: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_TEXC -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 - A:CC_ZERO B:CC_RASC C:CC_TEXC D:CC_C2 -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 - A:CC_ZERO B:CC_C2 C:CC_TEXC D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_APREV -> TEVPREV - HasIndirect: false HasLightmap: false - */ - case 0xFFF3CEBB: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_RASC -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 - A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_TEXA C:CA_APREV D:CA_ZERO -> TEVPREV - HasIndirect: false HasLightmap: true - */ - case 0x58BAA415: - /* TODO: Properly implement TEV configuration: - A:CC_ZERO B:CC_C1 C:CC_TEXC D:CC_RASC -> TEVREG0 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG0 - A:CC_ZERO B:CC_C0 C:CC_TEXC D:CC_ZERO -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_TEXA -> TEVPREV - A:CC_ZERO B:CC_TEXC C:CC_ONE D:CC_CPREV -> TEVPREV | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVPREV - A:CC_ZERO B:CC_ZERO C:CC_ZERO D:CC_TEXC -> TEVREG2 | A:CA_ZERO B:CA_ZERO C:CA_ZERO D:CA_KONST -> TEVREG2 - HasIndirect: false HasLightmap: true - */ + case 0x58BAA415: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */ + // TODO: Last stage assigns into unused reg2, perhaps for runtime material mod? + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); + break; case 0x54C6204C: _GenerateRootShader(out, "RetroShader"); break; @@ -756,6 +661,10 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0x7252CB90: /* RetroShader: Lightmap, Diffuse, Alpha=KAlpha */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); break; + case 0x72BEDDAC: /* RetroShader: DiffuseMod, Diffuse, Emissive, Specular, Reflection Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "DiffuseMod"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, + "Reflection"_tex); + break; case 0x76BEA57E: /* RetroShader: Lightmap, Diffuse, Emissive, Specular, Reflection, Alpha=1.0, IndirectTex */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex); @@ -763,6 +672,9 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0x7D6A4487: /* RetroShader: Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */ _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 0, true)); break; + case 0x81106196: /* RetroDynamicShader: Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex); + break; case 0x84319328: /* RetroShader: Reflection, UnusedSpecular?, Alpha=1.0 */ _GenerateRootShader(out, "RetroShader", WhiteColorLink("Specular"), "Reflection"_tex); break; @@ -770,6 +682,9 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, TexLink("Alpha", 0, true)); break; + case 0x8C562AB1: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); + break; case 0x8E916C01: /* RetroShader: NULL, all inputs 0 */ _GenerateRootShader(out, "RetroShader"); break; @@ -788,6 +703,13 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0xA187C630: /* RetroShader: Diffuse, Emissive, UnusedReflection?, Alpha=1.0 */ _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; + case 0xB26E9E2E: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ + // TODO: Last two stages assign into unused reg2, perhaps for runtime material mod? + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); + break; + case 0xC0E3FF1F: /* RetroShader: KColorDiffuse, Specular, Reflection, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); + break; case 0xC138DCFA: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */ _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break; @@ -804,12 +726,19 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0xCD92D4C5: /* RetroShader: Diffuse, Reflection, Alpha=KAlpha */ _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, WhiteColorLink("Specular"), "Reflection"_tex, "Alpha"_kcola); break; + case 0xCE06F3F2: /* RetroShader: Diffuse, Alpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 1, true)); + break; case 0xD73E7728: /* RetroShader: ObjLightmap, Diffuse, Alpha=DiffuseAlpha */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; case 0xDB8F01AD: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, UnusedSpecular?, Alpha=1.0 */ _GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); break; + case 0xE64D1085: /* RetroShader: Lightmap, Diffuse, Emissive, Reflection, Alpha=DiffuseAlpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Reflection"_tex, + TexLink("Alpha", 1, true)); + break; case 0xE6784B10: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha, IndirectTex */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, TexLink("Alpha", 1, true)); @@ -817,6 +746,9 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0xE68FF182: /* RetroShader: Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break; + case 0xE92F1340: /* RetroShader: Diffuse, Alpha=DiffuseAlpha*AlphaMod */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true), TexLink("AlphaMod", 1, true)); + break; case 0xEB4645CF: /* RetroDynamicAlphaShader: Diffuse*Dynamic, Alpha=DiffuseAlpha*Dynamic */ _GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break; @@ -827,6 +759,12 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "ExtendedSpecular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break; + case 0xF345C16E: /* RetroShader: Emissive, Reflection, Alpha=1.0 */ + _GenerateRootShader(out, "RetroShader", "Emissive"_tex, "Reflection"_tex); + break; + case 0xF4DA0A86: /* RetroShader: KColorDiffuse, Emissive, Alpha=KAlpha */ + _GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola); break; + break; case 0xF559DB08: /* RetroShader: Lightmap, Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); @@ -834,9 +772,16 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI case 0xF9324367: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); break; + case 0xFC2761B8: /* RetroShader: Lightmap, Diffuse, Alpha=DiffuseAlpha*AlphaMod */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true), + TexLink("AlphaMod", 2, true)); + break; case 0xFD95D7FD: /* RetroShader: ObjLightmap, Diffuse, Alpha=DiffuseAlpha */ _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break; + case 0xFFF3CEBB: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha */ + _GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 3, true)); + break; default: _DescribeTEV(material); Log.report(logvisor::Fatal, fmt("Unable to resolve shader hash {:08X}\n"), hash); diff --git a/hecl b/hecl index db10f0c2c..138328b8f 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit db10f0c2ca2ea4ab4b779798b041b3bae0d79937 +Subproject commit 138328b8f617071cbe9457f04e9cbb31cef1975e From df229671c4b5d6b73e21696e20fcd2078a44fd35 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 8 Apr 2020 19:19:50 -1000 Subject: [PATCH 05/11] MP2 PATH support --- DataSpec/DNACommon/AROTBuilder.cpp | 29 ++--- DataSpec/DNACommon/AROTBuilder.hpp | 7 +- DataSpec/DNACommon/PATH.cpp | 164 +++++++++++++++-------------- DataSpec/DNACommon/PATH.hpp | 29 ++++- DataSpec/DNAMP1/PATH.hpp | 2 +- DataSpec/DNAMP2/DNAMP2.cpp | 6 +- DataSpec/DNAMP2/MREA.cpp | 50 +++++++-- DataSpec/DNAMP2/MREA.hpp | 1 + DataSpec/DNAMP2/PATH.hpp | 2 +- DataSpec/SpecMP1.cpp | 2 +- DataSpec/SpecMP2.cpp | 2 +- hecl | 2 +- 12 files changed, 181 insertions(+), 115 deletions(-) diff --git a/DataSpec/DNACommon/AROTBuilder.cpp b/DataSpec/DNACommon/AROTBuilder.cpp index 6cdc4a351..6985a98f9 100644 --- a/DataSpec/DNACommon/AROTBuilder.cpp +++ b/DataSpec/DNACommon/AROTBuilder.cpp @@ -272,10 +272,10 @@ void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& look } } -void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB) { +template +void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB) { if (childNodes.empty()) { - path.octree.emplace_back(); - DNAPATH::PATH::OctreeNode& n = path.octree.back(); + auto& n = path.octree.emplace_back(); n.isLeaf = 1; n.aabb[0] = curAABB.min; n.aabb[1] = curAABB.max; @@ -294,8 +294,7 @@ void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAA children[i] = path.octree.size() - 1; } - path.octree.emplace_back(); - DNAMP1::PATH::OctreeNode& n = path.octree.back(); + auto& n = path.octree.emplace_back(); n.isLeaf = 0; n.aabb[0] = curAABB.min; n.aabb[1] = curAABB.max; @@ -307,6 +306,10 @@ void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAA } } +template void AROTBuilder::Node::pathWrite<4>(DNAPATH::PATH<4>& path, const zeus::CAABox& curAABB); +template void AROTBuilder::Node::pathWrite<6>(DNAPATH::PATH<6>& path, const zeus::CAABox& curAABB); +template void AROTBuilder::Node::pathWrite<7>(DNAPATH::PATH<7>& path, const zeus::CAABox& curAABB); + void AROTBuilder::build(std::vector>& secs, const zeus::CAABox& fullAabb, const std::vector& meshAabbs, const std::vector& meshes) { /* Recursively split */ @@ -377,8 +380,7 @@ std::pair, uint32_t> AROTBuilder::buildCol(const ColM std::vector triBoxes; triBoxes.reserve(mesh.trianges.size()); for (const ColMesh::Triangle& tri : mesh.trianges) { - triBoxes.emplace_back(); - zeus::CAABox& aabb = triBoxes.back(); + zeus::CAABox& aabb = triBoxes.emplace_back(); for (int e = 0; e < 3; ++e) { const ColMesh::Edge& edge = mesh.edges[tri.edges[e]]; for (int v = 0; v < 2; ++v) { @@ -401,15 +403,14 @@ std::pair, uint32_t> AROTBuilder::buildCol(const ColM return {std::move(ret), totalSize}; } -void AROTBuilder::buildPath(DNAPATH::PATH& path) { +template +void AROTBuilder::buildPath(DNAPATH::PATH& path) { /* Accumulate total AABB and gather region boxes */ std::vector regionBoxes; regionBoxes.reserve(path.regions.size()); zeus::CAABox fullAABB; - for (const DNAPATH::PATH::Region& r : path.regions) { - regionBoxes.emplace_back(r.aabb[0], r.aabb[1]); - fullAABB.accumulateBounds(regionBoxes.back()); - } + for (const auto& r : path.regions) + fullAABB.accumulateBounds(regionBoxes.emplace_back(r.aabb[0], r.aabb[1])); /* Recursively split */ BspNodeType dontCare; @@ -426,4 +427,8 @@ void AROTBuilder::buildPath(DNAPATH::PATH& path) { rootNode.pathWrite(path, fullAABB); } +template void AROTBuilder::buildPath<4>(DNAPATH::PATH<4>& path); +template void AROTBuilder::buildPath<6>(DNAPATH::PATH<6>& path); +template void AROTBuilder::buildPath<7>(DNAPATH::PATH<7>& path); + } // namespace DataSpec diff --git a/DataSpec/DNACommon/AROTBuilder.hpp b/DataSpec/DNACommon/AROTBuilder.hpp index 2ec6f4a57..6395bccaa 100644 --- a/DataSpec/DNACommon/AROTBuilder.hpp +++ b/DataSpec/DNACommon/AROTBuilder.hpp @@ -8,6 +8,7 @@ namespace DataSpec { namespace DNAPATH { +template struct PATH; } @@ -43,13 +44,15 @@ struct AROTBuilder { void writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB); void pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount); - void pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); + template + void pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); } rootNode; void build(std::vector>& secs, const zeus::CAABox& fullAabb, const std::vector& meshAabbs, const std::vector& meshes); std::pair, uint32_t> buildCol(const ColMesh& mesh, BspNodeType& rootOut); - void buildPath(DNAPATH::PATH& path); + template + void buildPath(DNAPATH::PATH& path); }; } // namespace DataSpec diff --git a/DataSpec/DNACommon/PATH.cpp b/DataSpec/DNACommon/PATH.cpp index 16a499d9e..83e42382d 100644 --- a/DataSpec/DNACommon/PATH.cpp +++ b/DataSpec/DNACommon/PATH.cpp @@ -13,71 +13,70 @@ static void OutputOctreeNode(hecl::blender::PyOutStream& os, int idx, const zeus const zeus::CVector3f pos = aabb.center(); const zeus::CVector3f extent = aabb.extents(); os.format( - "obj = bpy.data.objects.new('Leaf_%d', None)\n" - "bpy.context.scene.collection.objects.link(obj)\n" - "obj.location = (%f,%f,%f)\n" - "obj.scale = (%f,%f,%f)\n" - "obj.empty_display_type = 'CUBE'\n" - "obj.layers[1] = True\n" - "obj.layers[0] = False\n", idx, - pos.x(), pos.y(), pos.z(), extent.x(), extent.y(), extent.z()); + "obj = bpy.data.objects.new('Leaf_%d', None)\n" + "bpy.context.scene.collection.objects.link(obj)\n" + "obj.location = (%f,%f,%f)\n" + "obj.scale = (%f,%f,%f)\n" + "obj.empty_display_type = 'CUBE'\n" + "obj.layers[1] = True\n" + "obj.layers[0] = False\n", + idx, pos.x(), pos.y(), pos.z(), extent.x(), extent.y(), extent.z()); } #endif -void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf, - const std::string& areaPath) { +template +void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf, + const std::string& areaPath) { /* Open Py Stream and read sections */ hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os << - "import bpy\n" - "import bmesh\n" - "from mathutils import Vector, Matrix\n" - "\n" - "bpy.types.Material.retro_path_idx_mask = bpy.props.IntProperty(name='Retro: Path Index Mask')\n" - "bpy.types.Material.retro_path_type_mask = bpy.props.IntProperty(name='Retro: Path Type Mask')\n" - "\n" - "material_dict = {}\n" - "material_index = []\n" - "def make_ground_material(idxMask):\n" - " mat = bpy.data.materials.new('Ground %X' % idxMask)\n" - " mat.diffuse_color = (0.8, 0.460, 0.194, 1.0)\n" - " return mat\n" - "def make_flyer_material(idxMask):\n" - " mat = bpy.data.materials.new('Flyer %X' % idxMask)\n" - " mat.diffuse_color = (0.016, 0.8, 0.8, 1.0)\n" - " return mat\n" - "def make_swimmer_material(idxMask):\n" - " mat = bpy.data.materials.new('Swimmer %X' % idxMask)\n" - " mat.diffuse_color = (0.074, 0.293, 0.8, 1.0)\n" - " return mat\n" - "def select_material(meshIdxMask, meshTypeMask):\n" - " key = (meshIdxMask, meshTypeMask)\n" - " if key in material_index:\n" - " return material_index.index(key)\n" - " elif key in material_dict:\n" - " material_index.append(key)\n" - " return len(material_index)-1\n" - " else:\n" - " if meshTypeMask == 0x2:\n" - " mat = make_flyer_material(meshIdxMask)\n" - " elif meshTypeMask == 0x4:\n" - " mat = make_swimmer_material(meshIdxMask)\n" - " else:\n" - " mat = make_ground_material(meshIdxMask)\n" - " mat.retro_path_idx_mask = meshIdxMask\n" - " mat.retro_path_type_mask = meshTypeMask\n" - " material_dict[key] = mat\n" - " material_index.append(key)\n" - " return len(material_index)-1\n" - "\n"; + os << "import bpy\n" + "import bmesh\n" + "from mathutils import Vector, Matrix\n" + "\n" + "bpy.types.Material.retro_path_idx_mask = bpy.props.IntProperty(name='Retro: Path Index Mask')\n" + "bpy.types.Material.retro_path_type_mask = bpy.props.IntProperty(name='Retro: Path Type Mask')\n" + "\n" + "material_dict = {}\n" + "material_index = []\n" + "def make_ground_material(idxMask):\n" + " mat = bpy.data.materials.new('Ground %X' % idxMask)\n" + " mat.diffuse_color = (0.8, 0.460, 0.194, 1.0)\n" + " return mat\n" + "def make_flyer_material(idxMask):\n" + " mat = bpy.data.materials.new('Flyer %X' % idxMask)\n" + " mat.diffuse_color = (0.016, 0.8, 0.8, 1.0)\n" + " return mat\n" + "def make_swimmer_material(idxMask):\n" + " mat = bpy.data.materials.new('Swimmer %X' % idxMask)\n" + " mat.diffuse_color = (0.074, 0.293, 0.8, 1.0)\n" + " return mat\n" + "def select_material(meshIdxMask, meshTypeMask):\n" + " key = (meshIdxMask, meshTypeMask)\n" + " if key in material_index:\n" + " return material_index.index(key)\n" + " elif key in material_dict:\n" + " material_index.append(key)\n" + " return len(material_index)-1\n" + " else:\n" + " if meshTypeMask == 0x2:\n" + " mat = make_flyer_material(meshIdxMask)\n" + " elif meshTypeMask == 0x4:\n" + " mat = make_swimmer_material(meshIdxMask)\n" + " else:\n" + " mat = make_ground_material(meshIdxMask)\n" + " mat.retro_path_idx_mask = meshIdxMask\n" + " mat.retro_path_type_mask = meshTypeMask\n" + " material_dict[key] = mat\n" + " material_index.append(key)\n" + " return len(material_index)-1\n" + "\n"; os.format(fmt("bpy.context.scene.name = '{}'\n"), entryName); - os << - "# Clear Scene\n" - "if len(bpy.data.collections):\n" - " bpy.data.collections.remove(bpy.data.collections[0])\n" - "\n" - "bm = bmesh.new()\n" - "height_lay = bm.faces.layers.float.new('Height')\n"; + os << "# Clear Scene\n" + "if len(bpy.data.collections):\n" + " bpy.data.collections.remove(bpy.data.collections[0])\n" + "\n" + "bm = bmesh.new()\n" + "height_lay = bm.faces.layers.float.new('Height')\n"; for (const Node& n : nodes) { zeus::simd_floats f(n.position.simd); @@ -91,16 +90,15 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry for (atUint32 i = 0; i < r.nodeCount; ++i) os.format(fmt("tri_verts.append(bm.verts[{}])\n"), r.nodeStart + i); - os.format(fmt( - "face = bm.faces.get(tri_verts)\n" - "if face is None:\n" - " face = bm.faces.new(tri_verts)\n" - " face.normal_flip()\n" - "face.material_index = select_material(0x{:04X}, 0x{:04X})\n" - "face.smooth = False\n" - "face[height_lay] = {}\n" - "\n"), - r.meshIndexMask, r.meshTypeMask, r.height); + os.format(fmt("face = bm.faces.get(tri_verts)\n" + "if face is None:\n" + " face = bm.faces.new(tri_verts)\n" + " face.normal_flip()\n" + "face.material_index = select_material(0x{:04X}, 0x{:04X})\n" + "face.smooth = False\n" + "face[height_lay] = {}\n" + "\n"), + r.meshIndexMask, r.meshTypeMask, r.height); #if 0 const zeus::CVector3f center = xf->multiplyOneOverW(r.centroid); @@ -152,15 +150,14 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry zeus::simd_floats xfMtxF[4]; for (int i = 0; i < 4; ++i) w.m[i].mSimd.copy_to(xfMtxF[i]); - os.format(fmt( - "mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "path_mesh_obj.rotation_mode = 'QUATERNION'\n" - "path_mesh_obj.location = mtxd[0]\n" - "path_mesh_obj.rotation_quaternion = mtxd[1]\n" - "path_mesh_obj.scale = mtxd[2]\n"), - xfMtxF[0][0], xfMtxF[1][0], xfMtxF[2][0], xfMtxF[3][0], xfMtxF[0][1], xfMtxF[1][1], xfMtxF[2][1], xfMtxF[3][1], - xfMtxF[0][2], xfMtxF[1][2], xfMtxF[2][2], xfMtxF[3][2]); + os.format(fmt("mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "path_mesh_obj.rotation_mode = 'QUATERNION'\n" + "path_mesh_obj.location = mtxd[0]\n" + "path_mesh_obj.rotation_quaternion = mtxd[1]\n" + "path_mesh_obj.scale = mtxd[2]\n"), + xfMtxF[0][0], xfMtxF[1][0], xfMtxF[2][0], xfMtxF[3][0], xfMtxF[0][1], xfMtxF[1][1], xfMtxF[2][1], + xfMtxF[3][1], xfMtxF[0][2], xfMtxF[1][2], xfMtxF[2][2], xfMtxF[3][2]); } #if DUMP_OCTREE @@ -179,8 +176,9 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry os.close(); } -bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, - const PathMesh& mesh, hecl::blender::Token& btok) { +template +bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const PathMesh& mesh, + hecl::blender::Token& btok) { athena::io::MemoryReader r(mesh.data.data(), mesh.data.size()); PATH path; path.read(r); @@ -219,4 +217,8 @@ bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat return true; } -} // namespace DataSpec::DNAMP1 \ No newline at end of file +template struct PATH<4>; +template struct PATH<6>; +template struct PATH<7>; + +} // namespace DataSpec::DNAPATH \ No newline at end of file diff --git a/DataSpec/DNACommon/PATH.hpp b/DataSpec/DNACommon/PATH.hpp index 67dc2e64d..10ebf1c47 100644 --- a/DataSpec/DNACommon/PATH.hpp +++ b/DataSpec/DNACommon/PATH.hpp @@ -4,7 +4,32 @@ #include "DataSpec/DNACommon/PAK.hpp" namespace DataSpec::DNAPATH { -struct PATH : BigDNA { +template +struct RegionPointers {}; +template <> +struct RegionPointers<4> : BigDNA { + AT_DECL_DNA + Value regionIdxPtr; +}; +template <> +struct RegionPointers<6> : BigDNA { + AT_DECL_DNA + Value unk0; + Value unk1; + Value unk2; + Value regionIdxPtr; +}; +template <> +struct RegionPointers<7> : BigDNA { + AT_DECL_DNA + Value unk0; + Value unk1; + Value unk2; + Value regionIdxPtr; +}; + +template +struct AT_SPECIALIZE_PARMS(4, 6, 7) PATH : BigDNA { using PathMesh = hecl::blender::PathMesh; AT_DECL_DNA @@ -41,7 +66,7 @@ struct PATH : BigDNA { Value regionIdx; Value centroid; Value aabb[2]; - Value regionIdxPtr; + Value> pointers; }; Value regionCount; Vector regions; diff --git a/DataSpec/DNAMP1/PATH.hpp b/DataSpec/DNAMP1/PATH.hpp index 5b954559b..c35bc2b43 100644 --- a/DataSpec/DNAMP1/PATH.hpp +++ b/DataSpec/DNAMP1/PATH.hpp @@ -3,7 +3,7 @@ #include "DataSpec/DNAMP1/DNAMP1.hpp" namespace DataSpec::DNAMP1 { -struct PATH : DNAPATH::PATH { +struct PATH : DNAPATH::PATH<4> { static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, std::function fileChanged); diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index 679a0e8cf..779369826 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -203,7 +203,6 @@ void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId)); for (const MLVL::Area& area : mlvl.areas) { -#if 0 { /* Get PATH transform */ const nod::Node* areaNode; @@ -214,7 +213,6 @@ void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, addTo[pathId] = zeus::CMatrix4f(area.transformMtx[0], area.transformMtx[1], area.transformMtx[2], BottomRow) .transposed(); } -#endif hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath(); if (area.areaNameId.isValid()) pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, @@ -272,8 +270,8 @@ ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, con return {MAPA::Extract, {_SYS_STR(".blend")}, 4}; case SBIG('MAPU'): return {MAPU::Extract, {_SYS_STR(".blend")}, 5}; -// case SBIG('PATH'): -// return {PATH::Extract, {_SYS_STR(".blend")}, 5}; + case SBIG('PATH'): + return {PATH::Extract, {_SYS_STR(".blend")}, 5}; case SBIG('FSM2'): return {DNAFSM2::ExtractFSM2, {_SYS_STR(".yaml")}}; case SBIG('FONT'): diff --git a/DataSpec/DNAMP2/MREA.cpp b/DataSpec/DNAMP2/MREA.cpp index 01c39e07a..ee165529f 100644 --- a/DataSpec/DNAMP2/MREA.cpp +++ b/DataSpec/DNAMP2/MREA.cpp @@ -98,11 +98,11 @@ void MREA::StreamReader::seek(atInt64 diff, athena::SeekOrigin whence) { if (newAccum > target) break; dAccum = newAccum; - ++bIdx; if (info.compSize) cAccum += ROUND_UP_32(info.compSize); else cAccum += info.decompSize; + ++bIdx; } /* Seek source if needed */ @@ -116,6 +116,41 @@ void MREA::StreamReader::seek(atInt64 diff, athena::SeekOrigin whence) { m_posInBlk = target - dAccum; } +void MREA::StreamReader::seekToSection(atUint32 sec, const std::vector& secSizes) { + /* Determine which block contains section */ + atUint32 sAccum = 0; + atUint32 dAccum = 0; + atUint32 cAccum = 0; + atUint32 bIdx = 0; + for (BlockInfo& info : m_blockInfos) { + atUint32 newSAccum = sAccum + info.secCount; + if (newSAccum > sec) + break; + sAccum = newSAccum; + dAccum += info.decompSize; + if (info.compSize) + cAccum += ROUND_UP_32(info.compSize); + else + cAccum += info.decompSize; + ++bIdx; + } + + /* Seek source if needed */ + if (bIdx != m_nextBlk - 1) { + m_source.seek(m_blkBase + cAccum, athena::SeekOrigin::Begin); + m_nextBlk = bIdx; + nextBlock(); + } + + /* Seek within block */ + atUint32 target = dAccum; + while (sAccum != sec) + target += secSizes[sAccum++]; + + m_pos = target; + m_posInBlk = target - dAccum; +} + atUint64 MREA::StreamReader::readUBytesToBuf(void* buf, atUint64 len) { atUint8* bufCur = reinterpret_cast(buf); atUint64 rem = len; @@ -302,15 +337,12 @@ UniqueID32 MREA::GetPATHId(PAKEntryReadStream& rs) { head.read(rs); rs.seekAlign32(); + /* MREA decompression stream */ + StreamReader drs(rs, head.compressedBlockCount); + /* Skip to PATH */ - atUint32 curSec = 0; - atUint64 secStart = rs.position(); - while (curSec != head.pathSecIdx) - secStart += head.secSizes[curSec++]; - if (!head.secSizes[curSec]) - return {}; - rs.seek(secStart, athena::SeekOrigin::Begin); - return {rs}; + drs.seekToSection(head.pathSecIdx, head.secSizes); + return {drs}; } } // namespace DNAMP2 diff --git a/DataSpec/DNAMP2/MREA.hpp b/DataSpec/DNAMP2/MREA.hpp index 6dd18b551..65950865b 100644 --- a/DataSpec/DNAMP2/MREA.hpp +++ b/DataSpec/DNAMP2/MREA.hpp @@ -43,6 +43,7 @@ struct MREA { public: StreamReader(athena::io::IStreamReader& source, atUint32 blkCount); void seek(atInt64 diff, athena::SeekOrigin whence) override; + void seekToSection(atUint32 sec, const std::vector& secSizes); atUint64 position() const override { return m_pos; } atUint64 length() const override { return m_totalDecompLen; } atUint64 readUBytesToBuf(void* buf, atUint64 len) override; diff --git a/DataSpec/DNAMP2/PATH.hpp b/DataSpec/DNAMP2/PATH.hpp index fd8e0ab3e..8fb08fba0 100644 --- a/DataSpec/DNAMP2/PATH.hpp +++ b/DataSpec/DNAMP2/PATH.hpp @@ -3,7 +3,7 @@ #include "DataSpec/DNAMP2/DNAMP2.hpp" namespace DataSpec::DNAMP2 { -struct PATH : DNAPATH::PATH { +struct PATH : DNAPATH::PATH<6> { static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, std::function fileChanged); diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index 4e0915763..80f07c287 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -661,7 +661,7 @@ struct SpecMP1 : SpecBase { hecl::blender::Token& btok, FCookProgress progress) override { PathMesh mesh = ds.compilePathMesh(); ds.close(); - DNAPATH::PATH::Cook(out, in, mesh, btok); + DNAPATH::PATH<4>::Cook(out, in, mesh, btok); } void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, diff --git a/DataSpec/SpecMP2.cpp b/DataSpec/SpecMP2.cpp index c6b76e313..40571f350 100644 --- a/DataSpec/SpecMP2.cpp +++ b/DataSpec/SpecMP2.cpp @@ -291,7 +291,7 @@ struct SpecMP2 : SpecBase { hecl::blender::Token& btok, FCookProgress progress) override { PathMesh mesh = ds.compilePathMesh(); ds.close(); - DNAPATH::PATH::Cook(out, in, mesh, btok); + DNAPATH::PATH<6>::Cook(out, in, mesh, btok); } void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, diff --git a/hecl b/hecl index 138328b8f..191ffdc8e 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 138328b8f617071cbe9457f04e9cbb31cef1975e +Subproject commit 191ffdc8e06c20e8831e383be5431789d9d4b8fb From 73f245ee277dcaa33c162467e9892e62e3af13fd Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 8 Apr 2020 19:46:40 -1000 Subject: [PATCH 06/11] Specialize PATH by PAKBridge --- DataSpec/DNACommon/AROTBuilder.cpp | 25 ++++++++++-------- DataSpec/DNACommon/AROTBuilder.hpp | 10 +++---- DataSpec/DNACommon/PATH.cpp | 42 +++++++++++++++++++++++------- DataSpec/DNACommon/PATH.hpp | 28 +++++++++++++------- DataSpec/DNAMP1/CMakeLists.txt | 2 +- DataSpec/DNAMP1/PATH.cpp | 27 ------------------- DataSpec/DNAMP1/PATH.hpp | 9 ++----- DataSpec/DNAMP2/CMakeLists.txt | 2 +- DataSpec/DNAMP2/PATH.cpp | 26 ------------------ DataSpec/DNAMP2/PATH.hpp | 12 ++------- DataSpec/SpecMP1.cpp | 2 +- DataSpec/SpecMP2.cpp | 3 ++- 12 files changed, 79 insertions(+), 109 deletions(-) delete mode 100644 DataSpec/DNAMP1/PATH.cpp delete mode 100644 DataSpec/DNAMP2/PATH.cpp diff --git a/DataSpec/DNACommon/AROTBuilder.cpp b/DataSpec/DNACommon/AROTBuilder.cpp index 6985a98f9..f515871ac 100644 --- a/DataSpec/DNACommon/AROTBuilder.cpp +++ b/DataSpec/DNACommon/AROTBuilder.cpp @@ -1,6 +1,9 @@ #include "AROTBuilder.hpp" #include "hecl/Blender/Connection.hpp" -#include "../DNAMP1/PATH.hpp" +#include "PATH.hpp" +#include "DataSpec/DNAMP1/DNAMP1.hpp" +#include "DataSpec/DNAMP2/DNAMP2.hpp" +#include "DataSpec/DNAMP3/DNAMP3.hpp" namespace DataSpec { logvisor::Module Log("AROTBuilder"); @@ -272,8 +275,8 @@ void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& look } } -template -void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB) { +template +void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB) { if (childNodes.empty()) { auto& n = path.octree.emplace_back(); n.isLeaf = 1; @@ -306,9 +309,9 @@ void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAAB } } -template void AROTBuilder::Node::pathWrite<4>(DNAPATH::PATH<4>& path, const zeus::CAABox& curAABB); -template void AROTBuilder::Node::pathWrite<6>(DNAPATH::PATH<6>& path, const zeus::CAABox& curAABB); -template void AROTBuilder::Node::pathWrite<7>(DNAPATH::PATH<7>& path, const zeus::CAABox& curAABB); +template void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); +template void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); +template void AROTBuilder::Node::pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); void AROTBuilder::build(std::vector>& secs, const zeus::CAABox& fullAabb, const std::vector& meshAabbs, const std::vector& meshes) { @@ -403,8 +406,8 @@ std::pair, uint32_t> AROTBuilder::buildCol(const ColM return {std::move(ret), totalSize}; } -template -void AROTBuilder::buildPath(DNAPATH::PATH& path) { +template +void AROTBuilder::buildPath(DNAPATH::PATH& path) { /* Accumulate total AABB and gather region boxes */ std::vector regionBoxes; regionBoxes.reserve(path.regions.size()); @@ -427,8 +430,8 @@ void AROTBuilder::buildPath(DNAPATH::PATH& path) { rootNode.pathWrite(path, fullAABB); } -template void AROTBuilder::buildPath<4>(DNAPATH::PATH<4>& path); -template void AROTBuilder::buildPath<6>(DNAPATH::PATH<6>& path); -template void AROTBuilder::buildPath<7>(DNAPATH::PATH<7>& path); +template void AROTBuilder::buildPath(DNAPATH::PATH& path); +template void AROTBuilder::buildPath(DNAPATH::PATH& path); +template void AROTBuilder::buildPath(DNAPATH::PATH& path); } // namespace DataSpec diff --git a/DataSpec/DNACommon/AROTBuilder.hpp b/DataSpec/DNACommon/AROTBuilder.hpp index 6395bccaa..a10a00128 100644 --- a/DataSpec/DNACommon/AROTBuilder.hpp +++ b/DataSpec/DNACommon/AROTBuilder.hpp @@ -8,7 +8,7 @@ namespace DataSpec { namespace DNAPATH { -template +template struct PATH; } @@ -44,15 +44,15 @@ struct AROTBuilder { void writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB); void pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount); - template - void pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); + template + void pathWrite(DNAPATH::PATH& path, const zeus::CAABox& curAABB); } rootNode; void build(std::vector>& secs, const zeus::CAABox& fullAabb, const std::vector& meshAabbs, const std::vector& meshes); std::pair, uint32_t> buildCol(const ColMesh& mesh, BspNodeType& rootOut); - template - void buildPath(DNAPATH::PATH& path); + template + void buildPath(DNAPATH::PATH& path); }; } // namespace DataSpec diff --git a/DataSpec/DNACommon/PATH.cpp b/DataSpec/DNACommon/PATH.cpp index 83e42382d..b756b5e73 100644 --- a/DataSpec/DNACommon/PATH.cpp +++ b/DataSpec/DNACommon/PATH.cpp @@ -24,9 +24,9 @@ static void OutputOctreeNode(hecl::blender::PyOutStream& os, int idx, const zeus } #endif -template -void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf, - const std::string& areaPath) { +template +void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, + const zeus::CMatrix4f* xf, const std::string& areaPath) { /* Open Py Stream and read sections */ hecl::blender::PyOutStream os = conn.beginPythonOut(true); os << "import bpy\n" @@ -176,9 +176,33 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view os.close(); } -template -bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const PathMesh& mesh, - hecl::blender::Token& btok) { +template +bool PATH::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKBridge::PAKType::Entry& entry, + bool force, hecl::blender::Token& btok, + std::function fileChanged) { + PATH path; + path.read(rs); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::PathMesh)) + return false; + + std::string areaPath; + for (const auto& ent : hecl::DirectoryEnumerator(outPath.getParentPath().getAbsolutePath())) { + if (hecl::StringUtils::BeginsWith(ent.m_name, _SYS_STR("!area_"))) { + areaPath = hecl::SystemUTF8Conv(ent.m_name).str(); + break; + } + } + + const zeus::CMatrix4f* xf = pakRouter.lookupMAPATransform(entry.id); + path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf, areaPath); + return conn.saveBlend(); +} + +template +bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const PathMesh& mesh, + hecl::blender::Token& btok) { athena::io::MemoryReader r(mesh.data.data(), mesh.data.size()); PATH path; path.read(r); @@ -217,8 +241,8 @@ bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& return true; } -template struct PATH<4>; -template struct PATH<6>; -template struct PATH<7>; +template struct PATH; +template struct PATH; +template struct PATH; } // namespace DataSpec::DNAPATH \ No newline at end of file diff --git a/DataSpec/DNACommon/PATH.hpp b/DataSpec/DNACommon/PATH.hpp index 10ebf1c47..8552d95a9 100644 --- a/DataSpec/DNACommon/PATH.hpp +++ b/DataSpec/DNACommon/PATH.hpp @@ -2,17 +2,20 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DataSpec/DNACommon/PAK.hpp" +#include "DataSpec/DNAMP1/DNAMP1.hpp" +#include "DataSpec/DNAMP2/DNAMP2.hpp" +#include "DataSpec/DNAMP3/DNAMP3.hpp" namespace DataSpec::DNAPATH { -template +template struct RegionPointers {}; template <> -struct RegionPointers<4> : BigDNA { +struct RegionPointers : BigDNA { AT_DECL_DNA Value regionIdxPtr; }; template <> -struct RegionPointers<6> : BigDNA { +struct RegionPointers : BigDNA { AT_DECL_DNA Value unk0; Value unk1; @@ -20,7 +23,7 @@ struct RegionPointers<6> : BigDNA { Value regionIdxPtr; }; template <> -struct RegionPointers<7> : BigDNA { +struct RegionPointers : BigDNA { AT_DECL_DNA Value unk0; Value unk1; @@ -28,8 +31,9 @@ struct RegionPointers<7> : BigDNA { Value regionIdxPtr; }; -template -struct AT_SPECIALIZE_PARMS(4, 6, 7) PATH : BigDNA { +template +struct AT_SPECIALIZE_PARMS(DataSpec::DNAMP1::PAKBridge, DataSpec::DNAMP2::PAKBridge, DataSpec::DNAMP3::PAKBridge) PATH +: BigDNA { using PathMesh = hecl::blender::PathMesh; AT_DECL_DNA @@ -66,7 +70,7 @@ struct AT_SPECIALIZE_PARMS(4, 6, 7) PATH : BigDNA { Value regionIdx; Value centroid; Value aabb[2]; - Value> pointers; + Value> pointers; }; Value regionCount; Vector regions; @@ -93,7 +97,11 @@ struct AT_SPECIALIZE_PARMS(4, 6, 7) PATH : BigDNA { void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf, const std::string& areaPath); - static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, - const PathMesh& mesh, hecl::blender::Token& btok); + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKBridge::PAKType::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged); + + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const PathMesh& mesh, + hecl::blender::Token& btok); }; -} // namespace DataSpec::DNAMP1 +} // namespace DataSpec::DNAPATH diff --git a/DataSpec/DNAMP1/CMakeLists.txt b/DataSpec/DNAMP1/CMakeLists.txt index 12f703bbb..51ebe4bfe 100644 --- a/DataSpec/DNAMP1/CMakeLists.txt +++ b/DataSpec/DNAMP1/CMakeLists.txt @@ -49,7 +49,7 @@ set(DNAMP1_SOURCES ANIM.cpp CINF.cpp EVNT.cpp - PATH.cpp + PATH.hpp CMDL.hpp CMDL.cpp CMDLMaterials.cpp DCLN.cpp diff --git a/DataSpec/DNAMP1/PATH.cpp b/DataSpec/DNAMP1/PATH.cpp deleted file mode 100644 index 68dd16fdf..000000000 --- a/DataSpec/DNAMP1/PATH.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "DataSpec/DNAMP1/PATH.hpp" -#include "DataSpec/DNACommon/AROTBuilder.hpp" -#include "hecl/Blender/Connection.hpp" - -namespace DataSpec::DNAMP1 { -bool PATH::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, - std::function fileChanged) { - PATH path; - path.read(rs); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(outPath, hecl::blender::BlendType::PathMesh)) - return false; - - std::string areaPath; - for (const auto& ent : hecl::DirectoryEnumerator(outPath.getParentPath().getAbsolutePath())) { - if (hecl::StringUtils::BeginsWith(ent.m_name, _SYS_STR("!area_"))) { - areaPath = hecl::SystemUTF8Conv(ent.m_name).str(); - break; - } - } - - const zeus::CMatrix4f* xf = pakRouter.lookupMAPATransform(entry.id); - path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf, areaPath); - return conn.saveBlend(); -} -} \ No newline at end of file diff --git a/DataSpec/DNAMP1/PATH.hpp b/DataSpec/DNAMP1/PATH.hpp index c35bc2b43..07f0179f8 100644 --- a/DataSpec/DNAMP1/PATH.hpp +++ b/DataSpec/DNAMP1/PATH.hpp @@ -1,11 +1,6 @@ #pragma once #include "DataSpec/DNACommon/PATH.hpp" -#include "DataSpec/DNAMP1/DNAMP1.hpp" namespace DataSpec::DNAMP1 { -struct PATH : DNAPATH::PATH<4> { - static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, - std::function fileChanged); -}; -} // namespace DataSpec::DNAMP1 \ No newline at end of file +using PATH = DNAPATH::PATH; +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP2/CMakeLists.txt b/DataSpec/DNAMP2/CMakeLists.txt index 84b43fe51..e04014768 100644 --- a/DataSpec/DNAMP2/CMakeLists.txt +++ b/DataSpec/DNAMP2/CMakeLists.txt @@ -23,7 +23,7 @@ set(DNAMP2_SOURCES MREA.cpp MAPA.hpp MAPU.hpp - PATH.hpp PATH.cpp + PATH.hpp AFSM.hpp STRG.hpp STRG.cpp) diff --git a/DataSpec/DNAMP2/PATH.cpp b/DataSpec/DNAMP2/PATH.cpp deleted file mode 100644 index 058fd5243..000000000 --- a/DataSpec/DNAMP2/PATH.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "DataSpec/DNAMP2/PATH.hpp" -#include "hecl/Blender/Connection.hpp" - -namespace DataSpec::DNAMP2 { -bool PATH::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, - std::function fileChanged) { - PATH path; - path.read(rs); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(outPath, hecl::blender::BlendType::PathMesh)) - return false; - - std::string areaPath; - for (const auto& ent : hecl::DirectoryEnumerator(outPath.getParentPath().getAbsolutePath())) { - if (hecl::StringUtils::BeginsWith(ent.m_name, _SYS_STR("!area_"))) { - areaPath = hecl::SystemUTF8Conv(ent.m_name).str(); - break; - } - } - - const zeus::CMatrix4f* xf = pakRouter.lookupMAPATransform(entry.id); - path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf, areaPath); - return conn.saveBlend(); -} -} \ No newline at end of file diff --git a/DataSpec/DNAMP2/PATH.hpp b/DataSpec/DNAMP2/PATH.hpp index 8fb08fba0..676f4479d 100644 --- a/DataSpec/DNAMP2/PATH.hpp +++ b/DataSpec/DNAMP2/PATH.hpp @@ -1,14 +1,6 @@ #pragma once #include "DataSpec/DNACommon/PATH.hpp" -#include "DataSpec/DNAMP2/DNAMP2.hpp" namespace DataSpec::DNAMP2 { -struct PATH : DNAPATH::PATH<6> { - static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, - std::function fileChanged); - - static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, - const PathMesh& mesh, hecl::blender::Token& btok); -}; -} \ No newline at end of file +using PATH = DNAPATH::PATH; +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index 80f07c287..ddf973351 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -661,7 +661,7 @@ struct SpecMP1 : SpecBase { hecl::blender::Token& btok, FCookProgress progress) override { PathMesh mesh = ds.compilePathMesh(); ds.close(); - DNAPATH::PATH<4>::Cook(out, in, mesh, btok); + DNAMP1::PATH::Cook(out, in, mesh, btok); } void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, diff --git a/DataSpec/SpecMP2.cpp b/DataSpec/SpecMP2.cpp index 40571f350..c15acc6e0 100644 --- a/DataSpec/SpecMP2.cpp +++ b/DataSpec/SpecMP2.cpp @@ -6,6 +6,7 @@ #include "DNAMP2/MLVL.hpp" #include "DNAMP2/STRG.hpp" #include "DNAMP2/AGSC.hpp" +#include "DNAMP2/PATH.hpp" #include "DNAMP2/MAPA.hpp" #include "DNAMP1/CSNG.hpp" #include "DNACommon/MAPU.hpp" @@ -291,7 +292,7 @@ struct SpecMP2 : SpecBase { hecl::blender::Token& btok, FCookProgress progress) override { PathMesh mesh = ds.compilePathMesh(); ds.close(); - DNAPATH::PATH<6>::Cook(out, in, mesh, btok); + DNAMP2::PATH::Cook(out, in, mesh, btok); } void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, From e4ade45fd1c7cc8d208dec21b2db32c4dfa5acc4 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 8 Apr 2020 19:50:29 -1000 Subject: [PATCH 07/11] Remove unnecessary includes --- DataSpec/DNACommon/AROTBuilder.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/DataSpec/DNACommon/AROTBuilder.cpp b/DataSpec/DNACommon/AROTBuilder.cpp index f515871ac..586f19d36 100644 --- a/DataSpec/DNACommon/AROTBuilder.cpp +++ b/DataSpec/DNACommon/AROTBuilder.cpp @@ -1,9 +1,6 @@ #include "AROTBuilder.hpp" #include "hecl/Blender/Connection.hpp" #include "PATH.hpp" -#include "DataSpec/DNAMP1/DNAMP1.hpp" -#include "DataSpec/DNAMP2/DNAMP2.hpp" -#include "DataSpec/DNAMP3/DNAMP3.hpp" namespace DataSpec { logvisor::Module Log("AROTBuilder"); From a668a623cbbb2f8478b9e8f74ed54d5d50084992 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 8 Apr 2020 20:03:52 -1000 Subject: [PATCH 08/11] Exclude bitmap3 from MP3's PATH --- DataSpec/DNACommon/PATH.hpp | 7 ++++++- hecl | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/DataSpec/DNACommon/PATH.hpp b/DataSpec/DNACommon/PATH.hpp index 8552d95a9..2a3f8d793 100644 --- a/DataSpec/DNACommon/PATH.hpp +++ b/DataSpec/DNACommon/PATH.hpp @@ -77,7 +77,12 @@ struct AT_SPECIALIZE_PARMS(DataSpec::DNAMP1::PAKBridge, DataSpec::DNAMP2::PAKBri Vector bitmap1; Vector bitmap2; - Vector bitmap3; + + /* Unused in all games, removed in MP3 */ + Vector + ? 0 + : (((((regionCount * regionCount) + 31) / 32) - bitmap1.size()) * 2))> + bitmap3; Value octreeRegionLookupCount; Vector octreeRegionLookup; diff --git a/hecl b/hecl index 191ffdc8e..b3d91f520 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 191ffdc8e06c20e8831e383be5431789d9d4b8fb +Subproject commit b3d91f520ad3a9429b0116f9b531ec12b2e71809 From 859d5e90686068ef517e6924367057415abd4bcd Mon Sep 17 00:00:00 2001 From: Luke Street Date: Thu, 9 Apr 2020 22:46:09 -0400 Subject: [PATCH 09/11] DNAMP2: Mark FrontEnd as non-shared --- DataSpec/DNAMP2/DNAMP2.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index 779369826..4632705b2 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -27,7 +27,9 @@ logvisor::Module Log("urde::DNAMP2"); static bool GetNoShare(std::string_view name) { std::string lowerName(name); std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); - if (!lowerName.compare(0, 7, "metroid")) + if (lowerName.compare(0, 7, "metroid") == 0) + return false; + if (lowerName.compare(0, 8, "frontend") == 0) return false; return true; } From 380cc13abbd149869ce239d4edfb5ea262bc7efa Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 9 Apr 2020 17:20:20 -1000 Subject: [PATCH 10/11] Fixes for MP3 --- DataSpec/Blender/RetroMasterShader.py | 1062 +++++++++++++++---------- DataSpec/DNACommon/MayaSpline.hpp | 2 + DataSpec/DNACommon/RigInverter.cpp | 1 - DataSpec/DNAMP2/CINF.cpp | 43 +- DataSpec/DNAMP2/CINF.hpp | 11 +- DataSpec/DNAMP2/DNAMP2.cpp | 4 +- DataSpec/DNAMP2/MREA.cpp | 3 +- DataSpec/DNAMP3/CINF.cpp | 48 -- DataSpec/DNAMP3/CINF.hpp | 10 +- DataSpec/DNAMP3/CMDLMaterials.cpp | 550 ++++++------- DataSpec/DNAMP3/CMDLMaterials.hpp | 126 +-- DataSpec/DNAMP3/CMakeLists.txt | 3 +- DataSpec/DNAMP3/DNAMP3.cpp | 37 +- DataSpec/DNAMP3/MREA.cpp | 30 +- DataSpec/DNAMP3/MREA.hpp | 3 + DataSpec/DNAMP3/PATH.hpp | 6 + hecl | 2 +- 17 files changed, 1095 insertions(+), 846 deletions(-) delete mode 100644 DataSpec/DNAMP3/CINF.cpp create mode 100644 DataSpec/DNAMP3/PATH.hpp diff --git a/DataSpec/Blender/RetroMasterShader.py b/DataSpec/Blender/RetroMasterShader.py index 3d13f9625..4749aa409 100644 --- a/DataSpec/Blender/RetroMasterShader.py +++ b/DataSpec/Blender/RetroMasterShader.py @@ -721,11 +721,661 @@ def make_retro_dynamic_character_shader(): new_grp.links.new(final_add_shader.outputs['Shader'], alpha_mix.inputs[2]) new_grp.links.new(alpha_mix.outputs['Shader'], mat_out.inputs['Surface']) +# MP3 / DKCR Material Passes: +# https://wiki.axiodl.com/w/Materials_(Metroid_Prime_3) + +def make_retro_shader_mp3_color(): + new_grp = bpy.data.node_groups.new("__RetroShaderMP3Color", "ShaderNodeTree") + new_grp.use_fake_user = True + input = new_grp.inputs.new("NodeSocketColor", "DIFFC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "DIFBC") + input.default_value = (1.0, 1.0, 1.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "CLRC") + input.default_value = (0.5, 0.5, 0.5, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "CLRA") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "TRAN") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "RFLDC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "RFLDA") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "RFLV") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "LRLD") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "LURDC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "LURDA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "INCAC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketInt", "Add INCA") + input.default_value = 0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "OPAC") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + new_grp.outputs.new("NodeSocketShader", "Shader") + nodes = {} + node = new_grp.nodes.new("ShaderNodeBsdfDiffuse") + node.name = "Diffuse BSDF.004" + nodes["Diffuse BSDF.004"] = node + node.label = "" + node.location = (-196.910400390625, -503.60546875) + node.inputs[0].default_value = (0.800000011920929, 0.800000011920929, 0.800000011920929, 1.0) + node.inputs[1].default_value = 0.0 + node.inputs[2].default_value = (0.0, 0.0, 0.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.009" + nodes["Add Shader.009"] = node + node.label = "" + node.location = (14.618888854980469, -571.516357421875) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.008" + nodes["Add Shader.008"] = node + node.label = "" + node.location = (6.4276123046875, -926.3602905273438) + node = new_grp.nodes.new("ShaderNodeBsdfDiffuse") + node.name = "Diffuse BSDF.005" + nodes["Diffuse BSDF.005"] = node + node.label = "" + node.location = (-189.85516357421875, -865.79345703125) + node.inputs[0].default_value = (0.800000011920929, 0.800000011920929, 0.800000011920929, 1.0) + node.inputs[1].default_value = 0.0 + node.inputs[2].default_value = (0.0, 0.0, 0.0) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.005" + nodes["Mix.005"] = node + node.label = "" + node.location = (-190.5804901123047, -1017.0886840820312) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.004" + nodes["Mix.004"] = node + node.label = "" + node.location = (-381.6676940917969, -870.815673828125) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.006" + nodes["Add Shader.006"] = node + node.label = "" + node.location = (220.7507781982422, -724.6066284179688) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.005" + nodes["Add Shader.005"] = node + node.label = "" + node.location = (218.0698699951172, -528.0934448242188) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.007" + nodes["Add Shader.007"] = node + node.label = "" + node.location = (388.0714416503906, -600.8295288085938) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.002" + nodes["Mix.002"] = node + node.label = "" + node.location = (-192.1793212890625, -281.65264892578125) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.010" + nodes["Add Shader.010"] = node + node.label = "" + node.location = (522.2215576171875, -284.7532653808594) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.001" + nodes["Mix.001"] = node + node.label = "" + node.location = (-198.2812957763672, -13.079503059387207) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeBsdfDiffuse") + node.name = "Diffuse BSDF.001" + nodes["Diffuse BSDF.001"] = node + node.label = "" + node.location = (-200.4605255126953, 138.9542694091797) + node.inputs[0].default_value = (0.800000011920929, 0.800000011920929, 0.800000011920929, 1.0) + node.inputs[1].default_value = 0.0 + node.inputs[2].default_value = (0.0, 0.0, 0.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.001" + nodes["Add Shader.001"] = node + node.label = "" + node.location = (-14.161624908447266, 32.61324691772461) + node = new_grp.nodes.new("NodeGroupOutput") + node.name = "Group Output" + nodes["Group Output"] = node + node.label = "" + node.location = (948.8831176757812, -299.1160583496094) + node = new_grp.nodes.new("ShaderNodeBsdfTransparent") + node.name = "Transparent BSDF.001" + nodes["Transparent BSDF.001"] = node + node.label = "" + node.location = (604.5911254882812, -88.7776870727539) + node.inputs[0].default_value = (1.0, 1.0, 1.0, 1.0) + node = new_grp.nodes.new("ShaderNodeMixShader") + node.name = "Mix Shader" + nodes["Mix Shader"] = node + node.label = "" + node.location = (772.179443359375, -91.1546401977539) + node.inputs[0].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.012" + nodes["Add Shader.012"] = node + node.label = "" + node.location = (776.751953125, -432.8694152832031) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.011" + nodes["Add Shader.011"] = node + node.label = "" + node.location = (779.857177734375, -294.9550476074219) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.006" + nodes["Mix.006"] = node + node.label = "" + node.location = (-192.534912109375, -643.984619140625) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix.003" + nodes["Mix.003"] = node + node.label = "" + node.location = (-374.2341003417969, -515.1140747070312) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeMixRGB") + node.name = "Mix" + nodes["Mix"] = node + node.label = "" + node.location = (-500.3056640625, -114.82369995117188) + node.blend_type = "MULTIPLY" + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math" + nodes["Math"] = node + node.label = "" + node.location = (454.39404296875, 96.02081298828125) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.001" + nodes["Math.001"] = node + node.label = "" + node.location = (619.3079223632812, 90.52423095703125) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.002" + nodes["Math.002"] = node + node.label = "" + node.location = (785.3211059570312, 81.7295913696289) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeBsdfTransparent") + node.name = "Transparent BSDF" + nodes["Transparent BSDF"] = node + node.label = "" + node.location = (597.9944458007812, -480.7802734375) + node.inputs[0].default_value = (1.0, 1.0, 1.0, 1.0) + node = new_grp.nodes.new("NodeGroupInput") + node.name = "Group Input" + nodes["Group Input"] = node + node.label = "" + node.location = (-669.6587524414062, -193.9534149169922) + new_grp.links.new(nodes["Group Input"].outputs[0], nodes["Mix"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[1], nodes["Mix"].inputs[2]) + new_grp.links.new(nodes["Mix"].outputs[0], nodes["Mix.001"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[2], nodes["Mix.001"].inputs[2]) + new_grp.links.new(nodes["Mix.001"].outputs[0], nodes["Add Shader.001"].inputs[1]) + new_grp.links.new(nodes["Diffuse BSDF.001"].outputs[0], nodes["Add Shader.001"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[2], nodes["Diffuse BSDF.001"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[5], nodes["Mix.002"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[7], nodes["Mix.002"].inputs[2]) + new_grp.links.new(nodes["Mix.002"].outputs[0], nodes["Add Shader.005"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[5], nodes["Mix.003"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[8], nodes["Mix.003"].inputs[2]) + new_grp.links.new(nodes["Mix.003"].outputs[0], nodes["Diffuse BSDF.004"].inputs[0]) + new_grp.links.new(nodes["Diffuse BSDF.004"].outputs[0], nodes["Add Shader.009"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[5], nodes["Mix.004"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[10], nodes["Mix.004"].inputs[2]) + new_grp.links.new(nodes["Mix.004"].outputs[0], nodes["Diffuse BSDF.005"].inputs[0]) + new_grp.links.new(nodes["Diffuse BSDF.005"].outputs[0], nodes["Add Shader.008"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[9], nodes["Add Shader.006"].inputs[0]) + new_grp.links.new(nodes["Add Shader.005"].outputs[0], nodes["Add Shader.007"].inputs[0]) + new_grp.links.new(nodes["Add Shader.006"].outputs[0], nodes["Add Shader.007"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[10], nodes["Mix.005"].inputs[2]) + new_grp.links.new(nodes["Mix"].outputs[0], nodes["Mix.005"].inputs[1]) + new_grp.links.new(nodes["Add Shader.008"].outputs[0], nodes["Add Shader.006"].inputs[1]) + new_grp.links.new(nodes["Mix.005"].outputs[0], nodes["Add Shader.008"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[8], nodes["Mix.006"].inputs[2]) + new_grp.links.new(nodes["Mix"].outputs[0], nodes["Mix.006"].inputs[1]) + new_grp.links.new(nodes["Add Shader.009"].outputs[0], nodes["Add Shader.005"].inputs[1]) + new_grp.links.new(nodes["Mix.006"].outputs[0], nodes["Add Shader.009"].inputs[1]) + new_grp.links.new(nodes["Add Shader.007"].outputs[0], nodes["Add Shader.010"].inputs[1]) + new_grp.links.new(nodes["Add Shader.001"].outputs[0], nodes["Add Shader.010"].inputs[0]) + new_grp.links.new(nodes["Transparent BSDF"].outputs[0], nodes["Add Shader.012"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[11], nodes["Add Shader.012"].inputs[0]) + new_grp.links.new(nodes["Add Shader.012"].outputs[0], nodes["Add Shader.011"].inputs[1]) + new_grp.links.new(nodes["Add Shader.011"].outputs[0], nodes["Group Output"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[3], nodes["Math"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[13], nodes["Math"].inputs[1]) + new_grp.links.new(nodes["Math"].outputs[0], nodes["Math.001"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[4], nodes["Math.001"].inputs[1]) + new_grp.links.new(nodes["Math.001"].outputs[0], nodes["Math.002"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[6], nodes["Math.002"].inputs[0]) + new_grp.links.new(nodes["Math.002"].outputs[0], nodes["Mix Shader"].inputs[0]) + new_grp.links.new(nodes["Transparent BSDF.001"].outputs[0], nodes["Mix Shader"].inputs[1]) + new_grp.links.new(nodes["Add Shader.010"].outputs[0], nodes["Mix Shader"].inputs[2]) + new_grp.links.new(nodes["Mix Shader"].outputs[0], nodes["Add Shader.011"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[12], nodes["Transparent BSDF"].inputs[0]) + +def make_retro_shader_mp3_bloom(): + new_grp = bpy.data.node_groups.new("__RetroShaderMP3Bloom", "ShaderNodeTree") + new_grp.use_fake_user = True + input = new_grp.inputs.new("NodeSocketFloatFactor", "DIFFA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "DIFBA") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOL") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOD") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLODB") + input.default_value = 0.5 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "TRAN") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "INCAA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BNIF") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOI") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOIB") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "OPAC") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketInt", "Add INCA") + input.default_value = 0 + input.min_value = 0.000000 + input.max_value = 1.000000 + new_grp.outputs.new("NodeSocketShader", "Shader") + nodes = {} + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.003" + nodes["Math.003"] = node + node.label = "" + node.location = (-131.26889038085938, -228.6888885498047) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math" + nodes["Math"] = node + node.label = "" + node.location = (-501.6487731933594, -144.7719268798828) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.002" + nodes["Math.002"] = node + node.label = "" + node.location = (-328.3370666503906, -209.53160095214844) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("NodeGroupOutput") + node.name = "Group Output" + nodes["Group Output"] = node + node.label = "" + node.location = (1109.7938232421875, -257.2006530761719) + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.001" + nodes["Math.001"] = node + node.label = "" + node.location = (129.59579467773438, -299.0679626464844) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeBsdfDiffuse") + node.name = "Diffuse BSDF.002" + nodes["Diffuse BSDF.002"] = node + node.label = "" + node.location = (122.80331420898438, -150.7427520751953) + node.inputs[0].default_value = (0.800000011920929, 0.800000011920929, 0.800000011920929, 1.0) + node.inputs[1].default_value = 0.0 + node.inputs[2].default_value = (0.0, 0.0, 0.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.002" + nodes["Add Shader.002"] = node + node.label = "" + node.location = (312.7171325683594, -220.0266571044922) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.005" + nodes["Add Shader.005"] = node + node.label = "" + node.location = (-165.06072998046875, -549.3956298828125) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.006" + nodes["Add Shader.006"] = node + node.label = "" + node.location = (20.3157958984375, -545.8302612304688) + node = new_grp.nodes.new("ShaderNodeBsdfTransparent") + node.name = "Transparent BSDF.001" + nodes["Transparent BSDF.001"] = node + node.label = "" + node.location = (205.5854034423828, -558.1273803710938) + node.inputs[0].default_value = (1.0, 1.0, 1.0, 1.0) + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader.001" + nodes["Add Shader.001"] = node + node.label = "" + node.location = (399.876708984375, -533.2184448242188) + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.004" + nodes["Math.004"] = node + node.label = "" + node.location = (-354.23876953125, -508.8504943847656) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeAddShader") + node.name = "Add Shader" + nodes["Add Shader"] = node + node.label = "" + node.location = (875.3080444335938, -248.47450256347656) + node = new_grp.nodes.new("ShaderNodeBsdfTransparent") + node.name = "Transparent BSDF" + nodes["Transparent BSDF"] = node + node.label = "" + node.location = (502.63671875, -341.6871032714844) + node.inputs[0].default_value = (1.0, 1.0, 1.0, 1.0) + node = new_grp.nodes.new("ShaderNodeMath") + node.name = "Math.006" + nodes["Math.006"] = node + node.label = "" + node.location = (505.8763122558594, -171.7743377685547) + node.operation = "MULTIPLY" + node.inputs[0].default_value = 0.5 + node.inputs[1].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeMixShader") + node.name = "Mix Shader" + nodes["Mix Shader"] = node + node.label = "" + node.location = (682.0885620117188, -169.31057739257812) + node.inputs[0].default_value = 0.5 + node = new_grp.nodes.new("NodeGroupInput") + node.name = "Group Input" + nodes["Group Input"] = node + node.label = "" + node.location = (-669.6587524414062, -193.9534149169922) + new_grp.links.new(nodes["Group Input"].outputs[0], nodes["Math"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[1], nodes["Math"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[3], nodes["Math.002"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[4], nodes["Math.003"].inputs[1]) + new_grp.links.new(nodes["Math.002"].outputs[0], nodes["Math.003"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[2], nodes["Math.002"].inputs[0]) + new_grp.links.new(nodes["Math"].outputs[0], nodes["Math.001"].inputs[0]) + new_grp.links.new(nodes["Diffuse BSDF.002"].outputs[0], nodes["Add Shader.002"].inputs[0]) + new_grp.links.new(nodes["Math.001"].outputs[0], nodes["Add Shader.002"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[10], nodes["Math.006"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[5], nodes["Math.006"].inputs[0]) + new_grp.links.new(nodes["Math.006"].outputs[0], nodes["Mix Shader"].inputs[0]) + new_grp.links.new(nodes["Transparent BSDF"].outputs[0], nodes["Mix Shader"].inputs[1]) + new_grp.links.new(nodes["Transparent BSDF.001"].outputs[0], nodes["Add Shader.001"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[6], nodes["Math.004"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[7], nodes["Math.004"].inputs[1]) + new_grp.links.new(nodes["Math.003"].outputs[0], nodes["Math.001"].inputs[1]) + new_grp.links.new(nodes["Math.003"].outputs[0], nodes["Diffuse BSDF.002"].inputs[0]) + new_grp.links.new(nodes["Math.004"].outputs[0], nodes["Add Shader.005"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[8], nodes["Add Shader.005"].inputs[1]) + new_grp.links.new(nodes["Add Shader.005"].outputs[0], nodes["Add Shader.006"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[9], nodes["Add Shader.006"].inputs[1]) + new_grp.links.new(nodes["Add Shader.006"].outputs[0], nodes["Add Shader.001"].inputs[1]) + new_grp.links.new(nodes["Add Shader"].outputs[0], nodes["Group Output"].inputs[0]) + new_grp.links.new(nodes["Mix Shader"].outputs[0], nodes["Add Shader"].inputs[0]) + new_grp.links.new(nodes["Add Shader.002"].outputs[0], nodes["Mix Shader"].inputs[2]) + new_grp.links.new(nodes["Add Shader.001"].outputs[0], nodes["Add Shader"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[11], nodes["Transparent BSDF.001"].inputs[0]) + +def make_retro_shader_mp3(): + new_grp = bpy.data.node_groups.new("RetroShaderMP3", "ShaderNodeTree") + new_grp.use_fake_user = True + input = new_grp.inputs.new("NodeSocketColor", "DIFFC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "DIFFA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "DIFBC") + input.default_value = (1.0, 1.0, 1.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "DIFBA") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOL") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOD") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLODB") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "CLR") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "CLRA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "TRAN") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "RFLD") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "RFLDA") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "RFLV") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "LRLD") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketColor", "LURDC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "LURDA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketColor", "INCAC") + input.default_value = (0.0, 0.0, 0.0, 1.0) + input = new_grp.inputs.new("NodeSocketFloatFactor", "INCAA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketInt", "Add INCA") + input.default_value = 0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BNIF") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOI") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "BLOIB") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "OPAC") + input.default_value = 1.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "XRAYC") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "XRAYA") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + input = new_grp.inputs.new("NodeSocketFloatFactor", "XRBR") + input.default_value = 0.0 + input.min_value = 0.000000 + input.max_value = 1.000000 + nodes = {} + node = new_grp.nodes.new("ShaderNodeMixShader") + node.name = "Mix Shader" + nodes["Mix Shader"] = node + node.label = "" + node.location = (-118.33348846435547, -291.9857482910156) + node.inputs[0].default_value = 0.0 + node = new_grp.nodes.new("ShaderNodeOutputMaterial") + node.name = "Material Output" + nodes["Material Output"] = node + node.label = "" + node.location = (81.25957489013672, -265.6065368652344) + node.inputs[2].default_value = (0.0, 0.0, 0.0) + node = new_grp.nodes.new("ShaderNodeGroup") + node.name = "Group.001" + nodes["Group.001"] = node + node.label = "" + node.location = (-358.6896057128906, -60.17391586303711) + node.node_tree = bpy.data.node_groups["__RetroShaderMP3Color"] + node.inputs[0].default_value = (1.0, 1.0, 1.0, 1.0) + node.inputs[1].default_value = (1.0, 1.0, 1.0, 1.0) + node.inputs[2].default_value = (0.5, 0.5, 0.5, 1.0) + node.inputs[3].default_value = 0.5 + node.inputs[4].default_value = 0.5 + node.inputs[5].default_value = (0.0, 0.0, 0.0, 1.0) + node.inputs[6].default_value = 0.5 + node.inputs[7].default_value = (0.0, 0.0, 0.0, 1.0) + node.inputs[8].default_value = (0.0, 0.0, 0.0, 1.0) + node.inputs[9].default_value = (0.0, 0.0, 0.0, 1.0) + node.inputs[10].default_value = 0.0 + node.inputs[11].default_value = (0.0, 0.0, 0.0, 1.0) + node.inputs[12].default_value = 0 + node.inputs[13].default_value = 0.5 + node = new_grp.nodes.new("ShaderNodeGroup") + node.name = "Group" + nodes["Group"] = node + node.label = "" + node.location = (-356.9021301269531, -446.9474182128906) + node.node_tree = bpy.data.node_groups["__RetroShaderMP3Bloom"] + node.inputs[0].default_value = 1.0 + node.inputs[1].default_value = 1.0 + node.inputs[2].default_value = 0.0 + node.inputs[3].default_value = 0.0 + node.inputs[4].default_value = 0.5 + node.inputs[5].default_value = 0.5 + node.inputs[6].default_value = 0.0 + node.inputs[7].default_value = 0.0 + node.inputs[8].default_value = 0.0 + node.inputs[9].default_value = 0.0 + node.inputs[10].default_value = 0.5 + node.inputs[11].default_value = 0 + node = new_grp.nodes.new("NodeGroupInput") + node.name = "Group Input" + nodes["Group Input"] = node + node.label = "" + node.location = (-669.6587524414062, -193.9534149169922) + new_grp.links.new(nodes["Group Input"].outputs[0], nodes["Group.001"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[1], nodes["Group"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[3], nodes["Group"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[4], nodes["Group"].inputs[2]) + new_grp.links.new(nodes["Group Input"].outputs[5], nodes["Group"].inputs[3]) + new_grp.links.new(nodes["Group Input"].outputs[6], nodes["Group"].inputs[4]) + new_grp.links.new(nodes["Group Input"].outputs[17], nodes["Group"].inputs[6]) + new_grp.links.new(nodes["Group Input"].outputs[19], nodes["Group"].inputs[7]) + new_grp.links.new(nodes["Group Input"].outputs[20], nodes["Group"].inputs[8]) + new_grp.links.new(nodes["Group Input"].outputs[2], nodes["Group.001"].inputs[1]) + new_grp.links.new(nodes["Group Input"].outputs[7], nodes["Group.001"].inputs[2]) + new_grp.links.new(nodes["Group Input"].outputs[10], nodes["Group.001"].inputs[5]) + new_grp.links.new(nodes["Group Input"].outputs[12], nodes["Group.001"].inputs[7]) + new_grp.links.new(nodes["Group Input"].outputs[13], nodes["Group.001"].inputs[8]) + new_grp.links.new(nodes["Group Input"].outputs[14], nodes["Group.001"].inputs[9]) + new_grp.links.new(nodes["Group Input"].outputs[15], nodes["Group.001"].inputs[10]) + new_grp.links.new(nodes["Group Input"].outputs[16], nodes["Group.001"].inputs[11]) + new_grp.links.new(nodes["Group.001"].outputs[0], nodes["Mix Shader"].inputs[1]) + new_grp.links.new(nodes["Group"].outputs[0], nodes["Mix Shader"].inputs[2]) + new_grp.links.new(nodes["Mix Shader"].outputs[0], nodes["Material Output"].inputs[0]) + new_grp.links.new(nodes["Group Input"].outputs[21], nodes["Group"].inputs[9]) + new_grp.links.new(nodes["Group Input"].outputs[8], nodes["Group.001"].inputs[3]) + new_grp.links.new(nodes["Group Input"].outputs[9], nodes["Group.001"].inputs[4]) + new_grp.links.new(nodes["Group Input"].outputs[11], nodes["Group.001"].inputs[6]) + new_grp.links.new(nodes["Group Input"].outputs[22], nodes["Group.001"].inputs[13]) + new_grp.links.new(nodes["Group Input"].outputs[9], nodes["Group"].inputs[5]) + new_grp.links.new(nodes["Group Input"].outputs[22], nodes["Group"].inputs[10]) + new_grp.links.new(nodes["Group Input"].outputs[18], nodes["Group.001"].inputs[12]) + new_grp.links.new(nodes["Group Input"].outputs[18], nodes["Group"].inputs[11]) + ROOT_SHADER_GROUPS = ( make_retro_shader, make_retro_dynamic_shader, make_retro_dynamic_alpha_shader, - make_retro_dynamic_character_shader + make_retro_dynamic_character_shader, + make_retro_shader_mp3_color, + make_retro_shader_mp3_bloom, + make_retro_shader_mp3 ) # UV animation nodes: @@ -1196,414 +1846,6 @@ UV_ANIMATION_GROUPS = ( make_uva8 ) -# MP3 / DKCR Material Passes: -# https://wiki.axiodl.com/w/Materials_(Metroid_Prime_3) - -# Lightmap -def make_pass_diff(): - new_grp = bpy.data.node_groups.new('RetroPassDIFF', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply1 - mult1 = new_grp.nodes.new('ShaderNodeMixRGB') - mult1.blend_type = 'ADD' - mult1.inputs[0].default_value = 1.0 - mult1.location = (-600, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], mult1.inputs[1]) - new_grp.links.new(grp_in.outputs[2], mult1.inputs[2]) - new_grp.links.new(mult1.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - - -# Rim Lighting Map -def make_pass_riml(): - new_grp = bpy.data.node_groups.new('RetroPassRIML', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Bloom Lightmap -def make_pass_blol(): - new_grp = bpy.data.node_groups.new('RetroPassBLOL', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Bloom Diffuse Map -def make_pass_blod(): - new_grp = bpy.data.node_groups.new('RetroPassBLOD', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Diffuse Map -def make_pass_clr(): - new_grp = bpy.data.node_groups.new('RetroPassCLR', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply - mult1 = new_grp.nodes.new('ShaderNodeMixRGB') - mult1.blend_type = 'MULTIPLY' - mult1.inputs[0].default_value = 1.0 - grp_in.location = (-400, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], mult1.inputs[1]) - new_grp.links.new(grp_in.outputs[2], mult1.inputs[2]) - new_grp.links.new(mult1.outputs[0], grp_out.inputs[0]) - grp_out.inputs[1].default_value = 1.0 - -# Opacity Map -def make_pass_tran(): - new_grp = bpy.data.node_groups.new('RetroPassTRAN', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply - mul1 = new_grp.nodes.new('ShaderNodeMath') - mul1.operation = 'MULTIPLY' - mul1.inputs[0].default_value = 1.0 - mul1.location = (-400, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], mul1.inputs[0]) - new_grp.links.new(grp_in.outputs[2], mul1.inputs[1]) - new_grp.links.new(mul1.outputs[0], grp_out.inputs[1]) - -# Opacity Map Inverted -def make_pass_tran_inv(): - new_grp = bpy.data.node_groups.new('RetroPassTRANInv', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply - mul1 = new_grp.nodes.new('ShaderNodeMath') - mul1.operation = 'MULTIPLY' - mul1.inputs[0].default_value = 1.0 - mul1.location = (-400, 0) - - # Invert - inv1 = new_grp.nodes.new('ShaderNodeInvert') - inv1.inputs[0].default_value = 1.0 - inv1.location = (-600, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], mul1.inputs[1]) - new_grp.links.new(grp_in.outputs[2], inv1.inputs[1]) - new_grp.links.new(inv1.outputs[0], mul1.inputs[0]) - new_grp.links.new(mul1.outputs[0], grp_out.inputs[1]) - -# Incandescence Map -def make_pass_inca(): - new_grp = bpy.data.node_groups.new('RetroPassINCA', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply - add1 = new_grp.nodes.new('ShaderNodeMixRGB') - add1.blend_type = 'ADD' - add1.inputs[0].default_value = 1.0 - grp_in.location = (-400, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], add1.inputs[1]) - new_grp.links.new(grp_in.outputs[2], add1.inputs[2]) - new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - grp_out.inputs[1].default_value = 1.0 - -# Reflection Map -def make_pass_rfld(): - new_grp = bpy.data.node_groups.new('RetroPassRFLD', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Mask Color') - new_grp.inputs.new('NodeSocketFloat', 'Mask Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Multiply - mult1 = new_grp.nodes.new('ShaderNodeMixRGB') - mult1.location = (-600, 0) - mult1.blend_type = 'MULTIPLY' - mult1.inputs[0].default_value = 1.0 - - # Add - add1 = new_grp.nodes.new('ShaderNodeMixRGB') - add1.location = (-400, 0) - add1.blend_type = 'ADD' - add1.inputs[0].default_value = 1.0 - - # Links - new_grp.links.new(grp_in.outputs[0], add1.inputs[1]) - new_grp.links.new(grp_in.outputs[2], mult1.inputs[1]) - new_grp.links.new(grp_in.outputs[4], mult1.inputs[2]) - new_grp.links.new(mult1.outputs[0], add1.inputs[2]) - new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Unk1 -def make_pass_lrld(): - new_grp = bpy.data.node_groups.new('RetroPassLRLD', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Unk2 -def make_pass_lurd(): - new_grp = bpy.data.node_groups.new('RetroPassLURD', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Bloom Incandescence Map -def make_pass_bloi(): - new_grp = bpy.data.node_groups.new('RetroPassBLOI', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# X-ray Reflection Map -def make_pass_xray(): - new_grp = bpy.data.node_groups.new('RetroPassXRAY', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -# Unused -def make_pass_toon(): - new_grp = bpy.data.node_groups.new('RetroPassTOON', 'ShaderNodeTree') - new_grp.inputs.new('NodeSocketColor', 'Prev Color') - new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha') - new_grp.inputs.new('NodeSocketColor', 'Tex Color') - new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha') - new_grp.outputs.new('NodeSocketColor', 'Next Color') - new_grp.outputs.new('NodeSocketFloat', 'Next Alpha') - new_grp.use_fake_user = True - - # Group inputs - grp_in = new_grp.nodes.new('NodeGroupInput') - grp_in.location = (-800, 0) - - # Group outputs - grp_out = new_grp.nodes.new('NodeGroupOutput') - grp_out.location = (0, 0) - - # Links - new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) - new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) - -MP3_PASS_GROUPS = ( - make_pass_diff, - make_pass_riml, - make_pass_blol, - make_pass_blod, - make_pass_clr, - make_pass_tran, - make_pass_tran_inv, - make_pass_inca, - make_pass_rfld, - make_pass_lrld, - make_pass_lurd, - make_pass_bloi, - make_pass_xray, - make_pass_toon -) - def make_master_shader_library(): make_additive_output() make_blend_opaque_output() @@ -1611,6 +1853,4 @@ def make_master_shader_library(): shad() for uva in UV_ANIMATION_GROUPS: uva() - for aPass in MP3_PASS_GROUPS: - aPass() diff --git a/DataSpec/DNACommon/MayaSpline.hpp b/DataSpec/DNACommon/MayaSpline.hpp index 00b48fae3..700f78833 100644 --- a/DataSpec/DNACommon/MayaSpline.hpp +++ b/DataSpec/DNACommon/MayaSpline.hpp @@ -14,6 +14,8 @@ struct MayaSpline : public BigDNA { Value amplitude; Value unk1; Value unk2; + Vector unk1Floats; + Vector unk2Floats; }; Vector knots; diff --git a/DataSpec/DNACommon/RigInverter.cpp b/DataSpec/DNACommon/RigInverter.cpp index a22f997c4..e1c6078ef 100644 --- a/DataSpec/DNACommon/RigInverter.cpp +++ b/DataSpec/DNACommon/RigInverter.cpp @@ -141,6 +141,5 @@ zeus::CVector3f RigInverter::restorePosition(atUint32 boneId, const ze template class RigInverter; template class RigInverter; -template class RigInverter; } // namespace DataSpec::DNAANIM diff --git a/DataSpec/DNAMP2/CINF.cpp b/DataSpec/DNAMP2/CINF.cpp index f0b5f39b7..6762c4238 100644 --- a/DataSpec/DNAMP2/CINF.cpp +++ b/DataSpec/DNAMP2/CINF.cpp @@ -1,5 +1,6 @@ #include "CINF.hpp" #include "hecl/Blender/Connection.hpp" +#include "DataSpec/DNAMP3/DNAMP3.hpp" namespace DataSpec::DNAMP2 { @@ -41,7 +42,8 @@ void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const { } } -void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const { +template +void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const typename PAKBridge::PAKType::IDType& cinfId) const { DNAANIM::RigInverter inverter(*this); os.format(fmt( @@ -66,9 +68,18 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c tailF[2], bone.m_origBone.id); } - for (const Bone& bone : bones) - if (bone.parentId != 97) - os.format(fmt("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId); + if constexpr (std::is_same_v) { + if (bones.size()) { + atUint32 nullId = bones[0].parentId; + for (const Bone& bone : bones) + if (bone.parentId != nullId) + os.format(fmt("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId); + } + } else { + for (const Bone& bone : bones) + if (bone.parentId != 97) + os.format(fmt("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId); + } os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; @@ -76,8 +87,14 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c os.format(fmt("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"), *getBoneNameFromId(bone.m_origBone.id)); } +template void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const; +template void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, + const UniqueID64& cinfId) const; -std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return fmt::format(fmt("CINF_{}"), cinfId); } +template +std::string CINF::GetCINFArmatureName(const UniqueID& cinfId) { return fmt::format(fmt("CINF_{}"), cinfId); } +template std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId); +template std::string CINF::GetCINFArmatureName(const UniqueID64& cinfId); int CINF::RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId, std::unordered_map& idMap, @@ -156,9 +173,10 @@ CINF::CINF(const Armature& armature, std::unordered_map& i boneIds.push_back(it->id); } +template bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, - std::function fileChanged) { + PAKRouter& pakRouter, const typename PAKBridge::PAKType::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged) { if (!force && outPath.isFile()) return true; @@ -179,12 +197,21 @@ bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl: CINF cinf; cinf.read(rs); - cinf.sendCINFToBlender(os, entry.id); + cinf.sendCINFToBlender(os, entry.id); os.centerView(); os.close(); return conn.saveBlend(); } +template bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKBridge::PAKType::Entry& entry, + bool force, hecl::blender::Token& btok, + std::function fileChanged); +template bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename DNAMP3::PAKBridge::PAKType::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged); + bool CINF::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const hecl::blender::Armature& armature) { std::unordered_map boneIdMap; diff --git a/DataSpec/DNAMP2/CINF.hpp b/DataSpec/DNAMP2/CINF.hpp index 5f3637477..85831eb66 100644 --- a/DataSpec/DNAMP2/CINF.hpp +++ b/DataSpec/DNAMP2/CINF.hpp @@ -36,8 +36,10 @@ struct CINF : BigDNA { atUint32 getBoneIdxFromId(atUint32 id) const; const std::string* getBoneNameFromId(atUint32 id) const; void sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const; - void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const; - static std::string GetCINFArmatureName(const UniqueID32& cinfId); + template + void sendCINFToBlender(hecl::blender::PyOutStream& os, const typename PAKBridge::PAKType::IDType& cinfId) const; + template + static std::string GetCINFArmatureName(const UniqueID& cinfId); CINF() = default; using Armature = hecl::blender::Armature; @@ -48,9 +50,10 @@ struct CINF : BigDNA { CINF(const Armature& armature, std::unordered_map& idMap); + template static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, - std::function fileChanged); + PAKRouter& pakRouter, const typename PAKBridge::PAKType::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged); static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const hecl::blender::Armature& armature); diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index 63cc69754..7b1bcacf4 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -25,6 +25,8 @@ namespace DataSpec::DNAMP2 { logvisor::Module Log("urde::DNAMP2"); static bool GetNoShare(std::string_view name) { + if (name == "FrontEnd.pak"sv) + return false; std::string lowerName(name); std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); if (!lowerName.compare(0, 7, "metroid")) @@ -259,7 +261,7 @@ ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, con case SBIG('CMDL'): return {CMDL::Extract, {_SYS_STR(".blend")}, 1}; case SBIG('CINF'): - return {CINF::Extract, {_SYS_STR(".blend")}, 1}; + return {CINF::Extract, {_SYS_STR(".blend")}, 1}; case SBIG('ANCS'): return {ANCS::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; case SBIG('MLVL'): diff --git a/DataSpec/DNAMP2/MREA.cpp b/DataSpec/DNAMP2/MREA.cpp index ee165529f..a8add1605 100644 --- a/DataSpec/DNAMP2/MREA.cpp +++ b/DataSpec/DNAMP2/MREA.cpp @@ -68,8 +68,7 @@ MREA::StreamReader::StreamReader(athena::io::IStreamReader& source, atUint32 blk , m_blkCount(blkCount) { m_blockInfos.reserve(blkCount); for (atUint32 i = 0; i < blkCount; ++i) { - m_blockInfos.emplace_back(); - BlockInfo& info = m_blockInfos.back(); + BlockInfo& info = m_blockInfos.emplace_back(); info.read(source); m_totalDecompLen += info.decompSize; } diff --git a/DataSpec/DNAMP3/CINF.cpp b/DataSpec/DNAMP3/CINF.cpp deleted file mode 100644 index d8cf6ec82..000000000 --- a/DataSpec/DNAMP3/CINF.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "CINF.hpp" -#include "hecl/Blender/Connection.hpp" - -namespace DataSpec::DNAMP3 { - -void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& cinfId) const { - DNAANIM::RigInverter inverter(*this); - - os.format(fmt("arm = bpy.data.armatures.new('CINF_{}')\n" - "arm_obj = bpy.data.objects.new(arm.name, arm)\n" - "bpy.context.scene.collection.objects.link(arm_obj)\n" - "bpy.context.view_layer.objects.active = arm_obj\n" - "bpy.ops.object.mode_set(mode='EDIT')\n" - "arm_bone_table = {{}}\n"), - cinfId); - - for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) { - zeus::simd_floats originF(bone.m_origBone.origin.simd); - zeus::simd_floats tailF(bone.m_tail.mSimd); - os.format(fmt( - "bone = arm.edit_bones.new('{}')\n" - "bone.head = ({},{},{})\n" - "bone.tail = ({},{},{})\n" - "bone.use_inherit_scale = False\n" - "arm_bone_table[{}] = bone\n"), - *getBoneNameFromId(bone.m_origBone.id), originF[0], originF[1], originF[2], tailF[0], tailF[1], - tailF[2], bone.m_origBone.id); - } - - if (bones.size()) { - atUint32 nullId = bones[0].parentId; - for (const Bone& bone : bones) - if (bone.parentId != nullId) - os.format(fmt("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId); - } - - os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; - - for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - os.format(fmt("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"), - *getBoneNameFromId(bone.m_origBone.id)); -} - -std::string CINF::GetCINFArmatureName(const UniqueID64& cinfId) { - return fmt::format(fmt("CINF_{}"), cinfId); -} - -} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CINF.hpp b/DataSpec/DNAMP3/CINF.hpp index 353f21bb8..d40286143 100644 --- a/DataSpec/DNAMP3/CINF.hpp +++ b/DataSpec/DNAMP3/CINF.hpp @@ -1,14 +1,8 @@ #pragma once #include "DataSpec/DNACommon/DNACommon.hpp" -#include "../DNAMP2/CINF.hpp" +#include "DataSpec/DNAMP2/CINF.hpp" namespace DataSpec::DNAMP3 { - -struct CINF : DNAMP2::CINF { - Delete expl; - void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& cinfId) const; - static std::string GetCINFArmatureName(const UniqueID64& cinfId); -}; - +using CINF = DNAMP2::CINF; } // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CMDLMaterials.cpp b/DataSpec/DNAMP3/CMDLMaterials.cpp index 75f82dae7..e2ff1c8ae 100644 --- a/DataSpec/DNAMP3/CMDLMaterials.cpp +++ b/DataSpec/DNAMP3/CMDLMaterials.cpp @@ -6,341 +6,291 @@ using Stream = hecl::blender::PyOutStream; namespace DataSpec::DNAMP3 { using Material = MaterialSet::Material; -template <> -void MaterialSet::Material::SectionFactory::Enumerate(typename Read::StreamT& reader) { - DNAFourCC type; - type.read(reader); - switch (ISection::Type(type.toUint32())) { - case ISection::Type::PASS: - section = std::make_unique(); - section->read(reader); - break; - case ISection::Type::CLR: - section = std::make_unique(); - section->read(reader); - break; - case ISection::Type::INT: - section = std::make_unique(); - section->read(reader); - break; - default: - section.reset(); - break; - } -} -template <> -void MaterialSet::Material::SectionFactory::Enumerate(typename Write::StreamT& writer) { - if (!section) - return; - writer.writeUBytes((atUint8*)§ion->m_type, 4); - section->write(writer); -} -template <> -void MaterialSet::Material::SectionFactory::Enumerate(typename BinarySize::StreamT& s) { - s += 4; - section->binarySize(s); -} - template <> void MaterialSet::Material::Enumerate(typename Read::StreamT& reader) { header.read(reader); - sections.clear(); - do { - sections.emplace_back(); - sections.back().read(reader); - } while (sections.back().section); - sections.pop_back(); + chunks.clear(); + do { chunks.emplace_back().read(reader); } while (!chunks.back().holds_alternative()); + chunks.pop_back(); } template <> void MaterialSet::Material::Enumerate(typename Write::StreamT& writer) { header.write(writer); - for (const SectionFactory& section : sections) - section.write(writer); - writer.writeUBytes((atUint8*)"END ", 4); + for (const auto& chunk : chunks) + chunk.visit([&](auto& arg) { arg.write(writer); }); + DNAFourCC(FOURCC('END ')).write(writer); } template <> void MaterialSet::Material::Enumerate(typename BinarySize::StreamT& s) { header.binarySize(s); - for (const SectionFactory& section : sections) - section.binarySize(s); + for (const auto& chunk : chunks) + chunk.visit([&](auto& arg) { arg.binarySize(s); }); s += 4; } void MaterialSet::RegisterMaterialProps(Stream& out) { - out << "bpy.types.Material.retro_alpha_test = bpy.props.BoolProperty(name='Retro: Punchthrough Alpha')\n" + out << "bpy.types.Material.retro_enable_bloom = bpy.props.BoolProperty(name='Retro: Enable Bloom')\n" + "bpy.types.Material.retro_force_lighting_stage = bpy.props.BoolProperty(name='Retro: Force Lighting Stage')\n" + "bpy.types.Material.retro_pre_inca_transparency = bpy.props.BoolProperty(name='Retro: Pre-INCA Transparency')\n" + "bpy.types.Material.retro_alpha_test = bpy.props.BoolProperty(name='Retro: Alpha Test')\n" "bpy.types.Material.retro_shadow_occluder = bpy.props.BoolProperty(name='Retro: Shadow Occluder')\n" - "bpy.types.Material.retro_lightmapped = bpy.props.BoolProperty(name='Retro: Lightmapped')\n" - "bpy.types.Material.retro_opac = bpy.props.IntProperty(name='Retro: OPAC')\n" - "bpy.types.Material.retro_blod = bpy.props.IntProperty(name='Retro: BLOD')\n" - "bpy.types.Material.retro_bloi = bpy.props.IntProperty(name='Retro: BLOI')\n" - "bpy.types.Material.retro_bnif = bpy.props.IntProperty(name='Retro: BNIF')\n" - "bpy.types.Material.retro_xrbr = bpy.props.IntProperty(name='Retro: XRBR')\n" + "bpy.types.Material.retro_solid_white = bpy.props.BoolProperty(name='Retro: Solid White Only')\n" + "bpy.types.Material.retro_reflection_alpha_target = bpy.props.BoolProperty(name='Retro: Reflection Alpha Target')\n" + "bpy.types.Material.retro_solid_color = bpy.props.BoolProperty(name='Retro: Solid Color Only')\n" + "bpy.types.Material.retro_exclude_scan = bpy.props.BoolProperty(name='Retro: Exclude From Scan Visor')\n" + "bpy.types.Material.retro_xray_opaque = bpy.props.BoolProperty(name='Retro: XRay Opaque')\n" + "bpy.types.Material.retro_xray_alpha_target = bpy.props.BoolProperty(name='Retro: XRay Alpha Target')\n" + "bpy.types.Material.retro_inca_color_mod = bpy.props.BoolProperty(name='Retro: INCA Color Mod')\n" "\n"; } +static void LoadTexture(Stream& out, const UniqueID64& tex, + const PAKRouter& pakRouter, const PAK::Entry& entry) { + std::string texName = pakRouter.getBestEntryName(tex); + const nod::Node* node; + const typename PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(tex, &node); + hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); + if (!txtrPath.isNone()) { + txtrPath.makeDirChain(false); + PAKEntryReadStream rs = texEntry->beginReadStream(*node); + TXTR::Extract(rs, txtrPath); + } + hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex); + hecl::SystemUTF8Conv resPathView(resPath); + out.format(fmt("if '{}' in bpy.data.images:\n" + " image = bpy.data.images['{}']\n" + "else:\n" + " image = bpy.data.images.load('''//{}''')\n" + " image.name = '{}'\n" + "\n"), texName, texName, resPathView, texName); +} + void MaterialSet::ConstructMaterial(Stream& out, const PAKRouter& pakRouter, const PAK::Entry& entry, const Material& material, unsigned groupIdx, unsigned matIdx) { - unsigned i; - - out.format(fmt( - "new_material = bpy.data.materials.new('MAT_{}_{}')\n" - "new_material.use_shadows = True\n" - "new_material.use_transparent_shadows = True\n" - "new_material.diffuse_color = (1.0,1.0,1.0)\n" - "new_material.use_nodes = True\n" - "new_material.blend_method = 'BLEND'\n" - "new_nodetree = new_material.node_tree\n" - "material_node = new_nodetree.nodes['Material']\n" - "final_node = new_nodetree.nodes['Output']\n" - "\n" - "gridder = hecl.Nodegrid(new_nodetree)\n" - "gridder.place_node(final_node, 3)\n" - "gridder.place_node(material_node, 0)\n" - "material_node.material = new_material\n" - "\n" - "texture_nodes = []\n" - "kcolor_nodes = []\n" - "color_combiner_nodes = []\n" - "alpha_combiner_nodes = []\n" - "tex_links = []\n" - "tev_reg_sockets = [None]*4\n" - "\n"), - groupIdx, matIdx); + out.format(fmt("new_material = bpy.data.materials.new('MAT_{}_{}')\n"), groupIdx, matIdx); + out << "new_material.use_fake_user = True\n" + "new_material.use_nodes = True\n" + "new_material.use_backface_culling = True\n" + "new_material.show_transparent_back = False\n" + "new_material.blend_method = 'BLEND'\n" + "new_nodetree = new_material.node_tree\n" + "for n in new_nodetree.nodes:\n" + " new_nodetree.nodes.remove(n)\n" + "\n" + "gridder = hecl.Nodegrid(new_nodetree)\n" + "new_nodetree.nodes.remove(gridder.frames[2])\n" + "\n" + "texture_nodes = []\n" + "kcolors = {}\n" + "kalphas = {}\n" + "tex_links = []\n" + "\n"; /* Material Flags */ out.format(fmt( + "new_material.retro_enable_bloom = {}\n" + "new_material.retro_force_lighting_stage = {}\n" + "new_material.retro_pre_inca_transparency = {}\n" "new_material.retro_alpha_test = {}\n" "new_material.retro_shadow_occluder = {}\n" - "new_material.diffuse_color = (1, 1, 1, {})\n"), + "new_material.retro_solid_white = {}\n" + "new_material.retro_reflection_alpha_target = {}\n" + "new_material.retro_solid_color = {}\n" + "new_material.retro_exclude_scan = {}\n" + "new_material.retro_xray_opaque = {}\n" + "new_material.retro_xray_alpha_target = {}\n" + "new_material.retro_inca_color_mod = False\n"), + material.header.flags.enableBloom() ? "True" : "False", + material.header.flags.forceLightingStage() ? "True" : "False", + material.header.flags.preIncaTransparency() ? "True" : "False", material.header.flags.alphaTest() ? "True" : "False", material.header.flags.shadowOccluderMesh() ? "True" : "False", - material.header.flags.shadowOccluderMesh() ? "0" : "1"); + material.header.flags.justWhite() ? "True" : "False", + material.header.flags.reflectionAlphaTarget() ? "True" : "False", + material.header.flags.justSolidColor() ? "True" : "False", + material.header.flags.excludeFromScanVisor() ? "True" : "False", + material.header.flags.xrayOpaque() ? "True" : "False", + material.header.flags.xrayAlphaTarget() ? "True" : "False"); - /* Blend factors */ - out << "blend_node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - "blend_node.name = 'Blend'\n" - "gridder.place_node(blend_node, 2)\n"; - if (material.header.flags.alphaBlending()) - out << "blend_node.node_tree = bpy.data.node_groups['HECLBlendOutput']\n"; - else if (material.header.flags.additiveBlending()) - out << "blend_node.node_tree = bpy.data.node_groups['HECLAdditiveOutput']\n"; - else { - out << "blend_node.node_tree = bpy.data.node_groups['HECLOpaqueOutput']\n" - "new_material.blend_method = 'OPAQUE'\n"; - } + out << "pnode = new_nodetree.nodes.new('ShaderNodeGroup')\n" + "pnode.name = 'Output'\n" + "pnode.node_tree = bpy.data.node_groups['RetroShaderMP3']\n" + "gridder.place_node(pnode, 1)\n"; - /* Texmap list */ - out << "tex_maps = []\n" - "pnode = None\n" - "anode = None\n" - "rflv_tex_node = None\n"; + if (material.header.flags.additiveIncandecence()) + out << "pnode.inputs['Add INCA'].default_value = 1\n"; - /* Add PASSes */ - i = 0; - unsigned texMapIdx = 0; - unsigned texMtxIdx = 0; - unsigned kColorIdx = 0; - Material::ISection* prevSection = nullptr; - for (const Material::SectionFactory& factory : material.sections) { - factory.section->constructNode(out, pakRouter, entry, prevSection, i++, texMapIdx, texMtxIdx, kColorIdx); - Material::SectionPASS* pass = Material::SectionPASS::castTo(factory.section.get()); - if (!pass || - (pass && Material::SectionPASS::Subtype(pass->subtype.toUint32()) != Material::SectionPASS::Subtype::RFLV)) - prevSection = factory.section.get(); - } + int texMtxIdx = 0; + for (const auto& chunk : material.chunks) { + if (const Material::PASS* pass = chunk.get_if()) { + LoadTexture(out, pass->txtrId, pakRouter, entry); + out << "# Texture\n" + "tex_node = new_nodetree.nodes.new('ShaderNodeTexImage')\n" + "texture_nodes.append(tex_node)\n" + "tex_node.image = image\n"; - /* Connect final PASS */ - out << "if pnode:\n" - " new_nodetree.links.new(pnode.outputs['Next Color'], final_node.inputs['Color'])\n" - "else:\n" - " new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], final_node.inputs['Color'])\n" - "if anode:\n" - " new_nodetree.links.new(anode.outputs['Value'], final_node.inputs['Alpha'])\n" - "elif pnode:\n" - " new_nodetree.links.new(pnode.outputs['Next Alpha'], final_node.inputs['Alpha'])\n" - "else:\n" - " new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], final_node.inputs['Alpha'])\n"; -} + if (!pass->uvAnim.empty()) { + const auto& uva = pass->uvAnim[0]; + switch (uva.uvSource) { + case Material::UVAnimationUVSource::Position: + default: + out << "tex_uv_node = new_nodetree.nodes.new('ShaderNodeTexCoord')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Window'], tex_node.inputs['Vector']))\n"; + break; + case Material::UVAnimationUVSource::Normal: + out << "tex_uv_node = new_nodetree.nodes.new('ShaderNodeTexCoord')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Normal'], tex_node.inputs['Vector']))\n"; + break; + case Material::UVAnimationUVSource::UV: + out.format(fmt("tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" + "tex_uv_node.uv_map = 'UV_{}'\n"), pass->uvSrc); + break; + } + out.format(fmt("tex_uv_node.label = 'MTX_{}'\n"), texMtxIdx); + } else { + out.format(fmt("tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n" + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" + "tex_uv_node.uv_map = 'UV_{}'\n"), pass->uvSrc); + } -void Material::SectionPASS::constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, - const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, - unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const { - /* Add Texture nodes */ - if (txtrId.isValid()) { - std::string texName = pakRouter.getBestEntryName(txtrId); - const nod::Node* node; - const PAK::Entry* texEntry = pakRouter.lookupEntry(txtrId, &node); - hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); - if (txtrPath.isNone()) { - txtrPath.makeDirChain(false); - PAKEntryReadStream rs = texEntry->beginReadStream(*node); - TXTR::Extract(rs, txtrPath); + out << "gridder.place_node(tex_uv_node, 0)\n" + "gridder.place_node(tex_node, 0)\n" + "tex_uv_node.location[0] -= 120\n" + "tex_node.location[0] += 120\n" + "tex_node.location[1] += 176\n" + "\n"; + + if (!pass->uvAnim.empty()) { + const auto& uva = pass->uvAnim[0]; + DNAMP1::MaterialSet::Material::AddTextureAnim(out, uva.anim.mode, texMtxIdx++, uva.anim.vals); + } + + auto DoSwap = [&]() { + if (pass->flags.swapColorComponent() == Material::SwapColorComponent::Alpha) { + out << "swap_output = tex_node.outputs['Alpha']\n"; + } else { + out << "separate_node = new_nodetree.nodes.new('ShaderNodeSeparateRGB')\n" + "gridder.place_node(separate_node, 0, False)\n" + "separate_node.location[0] += 350\n" + "separate_node.location[1] += 350\n" + "new_nodetree.links.new(tex_node.outputs['Color'], separate_node.inputs[0])\n"; + out.format(fmt("swap_output = separate_node.outputs[{}]\n"), int(pass->flags.swapColorComponent())); + } + }; + + using Subtype = Material::PASS::Subtype; + switch (Subtype(pass->subtype.toUint32())) { + case Subtype::DIFF: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['DIFFC'])\n" + "new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['DIFFA'])\n"; + break; + case Subtype::BLOL: + DoSwap(); + out << "new_nodetree.links.new(swap_output, pnode.inputs['BLOL'])\n"; + break; + case Subtype::BLOD: + DoSwap(); + out << "new_nodetree.links.new(swap_output, pnode.inputs['BLOD'])\n"; + break; + case Subtype::CLR: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['CLR'])\n" + "new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['CLRA'])\n"; + break; + case Subtype::TRAN: + DoSwap(); + if (pass->flags.TRANInvert()) + out << "invert_node = new_nodetree.nodes.new('ShaderNodeInvert')\n" + "gridder.place_node(invert_node, 0, False)\n" + "invert_node.location[0] += 400\n" + "invert_node.location[1] += 350\n" + "new_nodetree.links.new(swap_output, invert_node.inputs['Color'])\n" + "swap_output = invert_node.outputs['Color']\n"; + out << "new_nodetree.links.new(swap_output, pnode.inputs['TRAN'])\n"; + break; + case Subtype::INCA: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['INCAC'])\n"; + if (pass->flags.alphaContribution()) { + DoSwap(); + out << "new_nodetree.links.new(swap_output, pnode.inputs['INCAA'])\n"; + } + out.format(fmt("new_material.retro_inca_color_mod = {}\n"), pass->flags.INCAColorMod() ? "True" : "False"); + break; + case Subtype::RFLV: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['RFLV'])\n"; + break; + case Subtype::RFLD: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['RFLD'])\n" + "new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['RFLDA'])\n"; + break; + case Subtype::LRLD: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['LRLD'])\n"; + break; + case Subtype::LURD: + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['LURDC'])\n" + "new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['LURDA'])\n"; + break; + case Subtype::BLOI: + DoSwap(); + out << "new_nodetree.links.new(swap_output, pnode.inputs['BLOI'])\n"; + break; + case Subtype::XRAY: + DoSwap(); + out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['XRAYC'])\n" + "new_nodetree.links.new(swap_output, pnode.inputs['XRAYA'])\n"; + break; + default: + Log.report(logvisor::Fatal, fmt("Unknown PASS subtype")); + break; + } + } else if (const Material::CLR* clr = chunk.get_if()) { + using Subtype = Material::CLR::Subtype; + athena::simd_floats vec4; + clr->color.toVec4f().simd.copy_to(vec4); + switch (Subtype(clr->subtype.toUint32())) { + case Subtype::CLR: + out.format(fmt("pnode.inputs['CLR'].default_value = ({}, {}, {}, 1.0)\n" + "pnode.inputs['CLRA'].default_value = {}\n"), + vec4[0], vec4[1], vec4[2], vec4[3]); + break; + case Subtype::DIFB: + out.format(fmt("pnode.inputs['DIFBC'].default_value = ({}, {}, {}, 1.0)\n" + "pnode.inputs['DIFBA'].default_value = {}\n"), + vec4[0], vec4[1], vec4[2], vec4[3]); + break; + default: + Log.report(logvisor::Fatal, fmt("Unknown CLR subtype")); + break; + } + } else if (const Material::INT* val = chunk.get_if()) { + using Subtype = Material::INT::Subtype; + switch (Subtype(val->subtype.toUint32())) { + case Subtype::OPAC: + out.format(fmt("pnode.inputs['OPAC'].default_value = {}\n"), val->value / 255.f); + break; + case Subtype::BLOD: + out.format(fmt("pnode.inputs['BLOD'].default_value = {}\n"), val->value / 255.f); + break; + case Subtype::BLOI: + out.format(fmt("pnode.inputs['BLOI'].default_value = {}\n"), val->value / 255.f); + break; + case Subtype::BNIF: + out.format(fmt("pnode.inputs['BNIF'].default_value = {}\n"), val->value / 255.f); + break; + case Subtype::XRBR: + out.format(fmt("pnode.inputs['XRBR'].default_value = {}\n"), val->value / 255.f); + break; + default: + Log.report(logvisor::Fatal, fmt("Unknown INT subtype")); + break; + } } - hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, txtrId); - hecl::SystemUTF8Conv resPathView(resPath); - out.format(fmt( - "if '{}' in bpy.data.textures:\n" - " image = bpy.data.images['{}']\n" - " texture = bpy.data.textures[image.name]\n" - "else:\n" - " image = bpy.data.images.load('''//{}''')\n" - " image.name = '{}'\n" - " texture = bpy.data.textures.new(image.name, 'IMAGE')\n" - " texture.image = image\n" - "tex_maps.append(texture)\n" - "\n"), - texName, texName, resPathView, texName); - if (uvAnim.size()) { - const UVAnimation& uva = uvAnim[0]; - DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uva.unk1 + (uva.unk1 < 2 ? 0 : 2)), texMtxIdx, - texMapIdx++, false); - DNAMP1::MaterialSet::Material::AddTextureAnim(out, uva.anim.mode, texMtxIdx++, uva.anim.vals); - } else - DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uvSrc + 4), -1, texMapIdx++, false); - } - - /* Special case for RFLV (environment UV mask) */ - if (Subtype(subtype.toUint32()) == Subtype::RFLV) { - if (txtrId.isValid()) - out << "rflv_tex_node = texture_nodes[-1]\n"; - return; - } - - /* Add PASS node */ - bool linkRAS = false; - out << "prev_pnode = pnode\n" - "pnode = new_nodetree.nodes.new('ShaderNodeGroup')\n"; - switch (Subtype(subtype.toUint32())) { - case Subtype::DIFF: { - out << "pnode.node_tree = bpy.data.node_groups['RetroPassDIFF']\n"; - if (txtrId.isValid()) { - out << "new_material.hecl_lightmap = texture.name\n" - << "texture.image.use_fake_user = True\n"; - } - linkRAS = true; - break; - } - case Subtype::RIML: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassRIML']\n"; - if (idx == 0) - linkRAS = true; - break; - case Subtype::BLOL: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOL']\n"; - if (idx == 0) - linkRAS = true; - break; - case Subtype::BLOD: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOD']\n"; - if (idx == 0) - linkRAS = true; - break; - case Subtype::CLR: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassCLR']\n"; - if (idx == 0) - linkRAS = true; - break; - case Subtype::TRAN: - if (flags.TRANInvert()) - out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRANInv']\n"; - else - out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRAN']\n"; - break; - case Subtype::INCA: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassINCA']\n"; - break; - case Subtype::RFLV: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLV']\n"; - break; - case Subtype::RFLD: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLD']\n" - "if rflv_tex_node:\n" - " new_nodetree.links.new(rflv_tex_node.outputs['Color'], pnode.inputs['Mask Color'])\n" - " new_nodetree.links.new(rflv_tex_node.outputs['Value'], pnode.inputs['Mask Alpha'])\n"; - break; - case Subtype::LRLD: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassLRLD']\n"; - break; - case Subtype::LURD: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassLURD']\n"; - break; - case Subtype::BLOI: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOI']\n"; - break; - case Subtype::XRAY: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassXRAY']\n"; - break; - case Subtype::TOON: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassTOON']\n"; - break; - default: - break; - } - out << "gridder.place_node(pnode, 2)\n"; - - if (txtrId.isValid()) { - out << "new_nodetree.links.new(texture_nodes[-1].outputs['Color'], pnode.inputs['Tex Color'])\n" - "new_nodetree.links.new(texture_nodes[-1].outputs['Value'], pnode.inputs['Tex Alpha'])\n"; - } - - if (linkRAS) - out << "new_nodetree.links.new(material_node.outputs['Color'], pnode.inputs['Prev Color'])\n" - "new_nodetree.links.new(material_node.outputs['Alpha'], pnode.inputs['Prev Alpha'])\n"; - else if (prevSection) { - if (prevSection->m_type == ISection::Type::PASS && - Subtype(static_cast(prevSection)->subtype.toUint32()) != Subtype::RFLV) - out << "new_nodetree.links.new(prev_pnode.outputs['Next Color'], pnode.inputs['Prev Color'])\n" - "new_nodetree.links.new(prev_pnode.outputs['Next Alpha'], pnode.inputs['Prev Alpha'])\n"; - else if (prevSection->m_type == ISection::Type::CLR) - out << "new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], pnode.inputs['Prev Color'])\n" - "new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], pnode.inputs['Prev Alpha'])\n"; - } - - /* Row Break in gridder */ - out << "gridder.row_break(2)\n"; -} - -void Material::SectionCLR::constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, - const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, - unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const { - DNAMP1::MaterialSet::Material::AddKcolor(out, color, kColorIdx++); - switch (Subtype(subtype.toUint32())) { - case Subtype::DIFB: - out << "kc_node.label += ' DIFB'\n" - "ka_node.label += ' DIFB'\n"; - break; - default: - break; - } -} - -void Material::SectionINT::constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, - const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, - unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const { - switch (Subtype(subtype.toUint32())) { - case Subtype::OPAC: { - GX::Color clr(value); - out.format(fmt( - "anode = new_nodetree.nodes.new('ShaderNodeValue')\n" - "anode.outputs['Value'].default_value = {}\n"), - float(clr[3]) / float(0xff)); - out << "gridder.place_node(anode, 1)\n"; - } break; - case Subtype::BLOD: - out.format(fmt("new_material.retro_blod = {}\n"), value); - break; - case Subtype::BLOI: - out.format(fmt("new_material.retro_bloi = {}\n"), value); - break; - case Subtype::BNIF: - out.format(fmt("new_material.retro_bnif = {}\n"), value); - break; - case Subtype::XRBR: - out.format(fmt("new_material.retro_xrbr = {}\n"), value); - break; - default: - break; } } } // namespace DataSpec::DNAMP3 + +AT_SPECIALIZE_TYPED_VARIANT_BIGDNA(DataSpec::DNAMP3::MaterialSet::Material::PASS, + DataSpec::DNAMP3::MaterialSet::Material::CLR, + DataSpec::DNAMP3::MaterialSet::Material::INT, + DataSpec::DNAMP3::MaterialSet::Material::END) diff --git a/DataSpec/DNAMP3/CMDLMaterials.hpp b/DataSpec/DNAMP3/CMDLMaterials.hpp index df73b62e0..89d562a72 100644 --- a/DataSpec/DNAMP3/CMDLMaterials.hpp +++ b/DataSpec/DNAMP3/CMDLMaterials.hpp @@ -18,6 +18,10 @@ struct MaterialSet : BigDNA { void addMaterialEndOff(atUint32) { ++materialCount; } struct Material : BigDNA { + enum class SwapColorComponent { Red, Green, Blue, Alpha }; + enum class UVAnimationUVSource : atUint16 { Position, Normal, UV }; + enum class UVAnimationMatrixConfig : atUint16 { NoMtxNoPost, MtxNoPost, NoMtxPost, MtxPost }; + AT_DECL_EXPLICIT_DNA using VAFlags = DNAMP1::MaterialSet::Material::VAFlags; struct Header : BigDNA { @@ -26,8 +30,18 @@ struct MaterialSet : BigDNA { struct Flags : BigDNA { AT_DECL_DNA Value flags; - bool alphaBlending() const { return (flags & 0x8) != 0; } - void setAlphaBlending(bool enabled) { + bool enableBloom() const { return (flags & 0x1) != 0; } + void setEnableBloom(bool enabled) { + flags &= ~0x1; + flags |= atUint32(enabled) << 0; + } + bool forceLightingStage() const { return (flags & 0x4) != 0; } + void setForceLightingStage(bool enabled) { + flags &= ~0x4; + flags |= atUint32(enabled) << 2; + } + bool preIncaTransparency() const { return (flags & 0x8) != 0; } + void setPreIncaTransparency(bool enabled) { flags &= ~0x8; flags |= atUint32(enabled) << 3; } @@ -36,8 +50,8 @@ struct MaterialSet : BigDNA { flags &= ~0x10; flags |= atUint32(enabled) << 4; } - bool additiveBlending() const { return (flags & 0x20) != 0; } - void setAdditiveBlending(bool enabled) { + bool additiveIncandecence() const { return (flags & 0x20) != 0; } + void setAdditiveIncandecence(bool enabled) { flags &= ~0x20; flags |= atUint32(enabled) << 5; } @@ -46,6 +60,36 @@ struct MaterialSet : BigDNA { flags &= ~0x100; flags |= atUint32(enabled) << 8; } + bool justWhite() const { return (flags & 0x200) != 0; } + void setJustWhite(bool enabled) { + flags &= ~0x200; + flags |= atUint32(enabled) << 9; + } + bool reflectionAlphaTarget() const { return (flags & 0x400) != 0; } + void setReflectionAlphaTarget(bool enabled) { + flags &= ~0x400; + flags |= atUint32(enabled) << 10; + } + bool justSolidColor() const { return (flags & 0x800) != 0; } + void setJustSolidColor(bool enabled) { + flags &= ~0x800; + flags |= atUint32(enabled) << 11; + } + bool excludeFromScanVisor() const { return (flags & 0x4000) != 0; } + void setExcludeFromScanVisor(bool enabled) { + flags &= ~0x4000; + flags |= atUint32(enabled) << 14; + } + bool xrayOpaque() const { return (flags & 0x8000) != 0; } + void setXRayOpaque(bool enabled) { + flags &= ~0x8000; + flags |= atUint32(enabled) << 15; + } + bool xrayAlphaTarget() const { return (flags & 0x10000) != 0; } + void setXRayAlphaTarget(bool enabled) { + flags &= ~0x10000; + flags |= atUint32(enabled) << 16; + } bool lightmapUVArray() const { return false; } /* For polymorphic compatibility with MP1/2 */ } flags; Value uniqueIdx; @@ -58,20 +102,12 @@ struct MaterialSet : BigDNA { const Header::Flags& getFlags() const { return header.flags; } const VAFlags& getVAFlags() const { return header.vaFlags; } - struct ISection : BigDNAV { - Delete expl; - enum class Type : atUint32 { PASS = SBIG('PASS'), CLR = SBIG('CLR '), INT = SBIG('INT ') } m_type; - ISection(Type type) : m_type(type) {} - virtual void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, - const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, - unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const = 0; + enum class ChunkType : atUint32 { + PASS = 'PASS', CLR = 'CLR ', INT = 'INT ', END = 'END ' }; - struct SectionPASS : ISection { - SectionPASS() : ISection(ISection::Type::PASS) {} - static SectionPASS* castTo(ISection* sec) { - return sec->m_type == Type::PASS ? static_cast(sec) : nullptr; - } - AT_DECL_DNAV + + struct PASS : hecl::TypedRecordBigDNA { + AT_DECL_DNA Value size; enum class Subtype : atUint32 { DIFF = SBIG('DIFF'), @@ -93,6 +129,21 @@ struct MaterialSet : BigDNA { struct Flags : BigDNA { AT_DECL_DNA Value flags; + SwapColorComponent swapColorComponent() const { return SwapColorComponent(flags & 0x3); } + void setSwapColorComponent(SwapColorComponent comp) { + flags &= ~0x3; + flags |= atUint32(comp) << 0; + } + bool alphaContribution() const { return (flags & 0x4) != 0; } + void setAlphaContribution(bool enabled) { + flags &= ~0x4; + flags |= atUint32(enabled) << 2; + } + bool INCAColorMod() const { return (flags & 0x8) != 0; } + void setINCAColorMod(bool enabled) { + flags &= ~0x8; + flags |= atUint32(enabled) << 3; + } bool TRANInvert() const { return (flags & 0x10) != 0; } void setTRANInvert(bool enabled) { flags &= ~0x10; @@ -104,36 +155,21 @@ struct MaterialSet : BigDNA { Value uvAnimSize; struct UVAnimation : BigDNA { AT_DECL_DNA - Value unk1; - Value unk2; + Value uvSource; + Value mtxConfig; DNAMP1::MaterialSet::Material::UVAnimation anim; }; Vector uvAnim; - - void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, - const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, - unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const override; }; - struct SectionCLR : ISection { - SectionCLR() : ISection(ISection::Type::CLR) {} - static SectionCLR* castTo(ISection* sec) { - return sec->m_type == Type::CLR ? static_cast(sec) : nullptr; - } - AT_DECL_DNAV + struct CLR : hecl::TypedRecordBigDNA { + AT_DECL_DNA enum class Subtype : atUint32 { CLR = SBIG('CLR '), DIFB = SBIG('DIFB') }; DNAFourCC subtype; GX::Color color; - - void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, - const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, - unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const override; + CLR() = default; }; - struct SectionINT : ISection { - SectionINT() : ISection(ISection::Type::INT) {} - static SectionINT* castTo(ISection* sec) { - return sec->m_type == Type::INT ? static_cast(sec) : nullptr; - } - AT_DECL_DNAV + struct INT : hecl::TypedRecordBigDNA { + AT_DECL_DNA enum class Subtype : atUint32 { OPAC = SBIG('OPAC'), BLOD = SBIG('BLOD'), @@ -143,16 +179,12 @@ struct MaterialSet : BigDNA { }; DNAFourCC subtype; Value value; - - void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, - const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, - unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const override; }; - struct SectionFactory : BigDNA { - AT_DECL_EXPLICIT_DNA - std::unique_ptr section; + struct END : hecl::TypedRecordBigDNA { + AT_DECL_DNA }; - std::vector sections; + using Chunk = hecl::TypedVariantBigDNA; + std::vector chunks; }; Vector materials; diff --git a/DataSpec/DNAMP3/CMakeLists.txt b/DataSpec/DNAMP3/CMakeLists.txt index 0c0ea91a6..e4950978b 100644 --- a/DataSpec/DNAMP3/CMakeLists.txt +++ b/DataSpec/DNAMP3/CMakeLists.txt @@ -14,11 +14,12 @@ set(DNAMP3_SOURCES DNAMP3.hpp DNAMP3.cpp PAK.cpp ANIM.cpp - CINF.cpp + CINF.hpp CHAR.cpp CMDL.hpp CMDL.cpp CMDLMaterials.cpp CSKR.cpp + PATH.hpp STRG.hpp STRG.cpp MAPA.hpp MREA.cpp) diff --git a/DataSpec/DNAMP3/DNAMP3.cpp b/DataSpec/DNAMP3/DNAMP3.cpp index a2b8199b0..c252ad33e 100644 --- a/DataSpec/DNAMP3/DNAMP3.cpp +++ b/DataSpec/DNAMP3/DNAMP3.cpp @@ -9,6 +9,7 @@ #include "CHAR.hpp" #include "MREA.hpp" #include "MAPA.hpp" +#include "PATH.hpp" #include "SAVW.hpp" #include "HINT.hpp" #include "DataSpec/DNACommon/TXTR.hpp" @@ -21,6 +22,8 @@ namespace DataSpec::DNAMP3 { logvisor::Module Log("urde::DNAMP3"); static bool GetNoShare(std::string_view name) { + if (name == "UniverseArea.pak"sv) + return false; std::string lowerName(name); std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); if (!lowerName.compare(0, 7, "metroid")) @@ -194,6 +197,16 @@ void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId)); for (const MLVL::Area& area : mlvl.areas) { + { + /* Get PATH transform */ + const nod::Node* areaNode; + const PAK::Entry* areaEntry = pakRouter.lookupEntry(area.areaMREAId, &areaNode); + PAKEntryReadStream rs = areaEntry->beginReadStream(*areaNode); + UniqueID64 pathId = MREA::GetPATHId(rs); + if (pathId.isValid()) + addTo[pathId] = zeus::CMatrix4f(area.transformMtx[0], area.transformMtx[1], area.transformMtx[2], BottomRow) + .transposed(); + } hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath(); if (area.areaNameId.isValid()) pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, @@ -236,16 +249,20 @@ ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, con return {SAVWCommon::ExtractSAVW, {_SYS_STR(".yaml")}}; case SBIG('HINT'): return {HINT::Extract, {_SYS_STR(".yaml")}}; -// case SBIG('CMDL'): -// return {CMDL::Extract, {_SYS_STR(".blend")}, 1}; -// case SBIG('CHAR'): -// return {CHAR::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; -// case SBIG('MLVL'): -// return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3}; -// case SBIG('MREA'): -// return {MREA::Extract, {_SYS_STR(".blend")}, 4}; -// case SBIG('MAPA'): -// return {MAPA::Extract, {_SYS_STR(".blend")}, 4}; + case SBIG('CMDL'): + return {CMDL::Extract, {_SYS_STR(".blend")}, 1}; + case SBIG('CINF'): + return {CINF::Extract, {_SYS_STR(".blend")}, 1}; + case SBIG('CHAR'): + return {CHAR::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; + case SBIG('MLVL'): + return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3}; + case SBIG('MREA'): + return {MREA::Extract, {_SYS_STR(".blend")}, 4}; + case SBIG('MAPA'): + return {MAPA::Extract, {_SYS_STR(".blend")}, 4}; + case SBIG('PATH'): + return {PATH::Extract, {_SYS_STR(".blend")}, 5}; case SBIG('FSM2'): return {DNAFSM2::ExtractFSM2, {_SYS_STR(".yaml")}}; case SBIG('FONT'): diff --git a/DataSpec/DNAMP3/MREA.cpp b/DataSpec/DNAMP3/MREA.cpp index a54712423..293441c11 100644 --- a/DataSpec/DNAMP3/MREA.cpp +++ b/DataSpec/DNAMP3/MREA.cpp @@ -14,16 +14,14 @@ MREA::StreamReader::StreamReader(athena::io::IStreamReader& source, atUint32 blk m_blkCount = blkCount; m_blockInfos.reserve(blkCount); for (atUint32 i = 0; i < blkCount; ++i) { - m_blockInfos.emplace_back(); - BlockInfo& info = m_blockInfos.back(); + BlockInfo& info = m_blockInfos.emplace_back(); info.read(source); m_totalDecompLen += info.decompSize; } source.seekAlign32(); m_secIdxs.reserve(secIdxCount); for (atUint32 i = 0; i < secIdxCount; ++i) { - m_secIdxs.emplace_back(); - std::pair& idx = m_secIdxs.back(); + std::pair& idx = m_secIdxs.emplace_back(); idx.first.read(source); idx.second = source.readUint32Big(); } @@ -39,6 +37,15 @@ void MREA::StreamReader::writeSecIdxs(athena::io::IStreamWriter& writer) const { } } +bool MREA::StreamReader::seekToSection(FourCC sec, const std::vector& secSizes) { + auto search = std::find_if(m_secIdxs.begin(), m_secIdxs.end(), [sec](const auto& s) { return s.first == sec; }); + if (search != m_secIdxs.end()) { + DNAMP2::MREA::StreamReader::seekToSection(search->second, secSizes); + return true; + } + return false; +} + void MREA::ReadBabeDeadToBlender_3(hecl::blender::PyOutStream& os, athena::io::IStreamReader& rs) { atUint32 bdMagic = rs.readUint32Big(); if (bdMagic != 0xBABEDEAD) @@ -254,5 +261,20 @@ bool MREA::ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Level::Area& area return false; } +UniqueID64 MREA::GetPATHId(PAKEntryReadStream& rs) { + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); + + /* MREA decompression stream */ + StreamReader drs(rs, head.compressedBlockCount, head.secIndexCount); + + /* Skip to PATH */ + if (drs.seekToSection(FOURCC('PFL2'), head.secSizes)) + return {drs}; + return {}; +} + } // namespace DNAMP3 } // namespace DataSpec diff --git a/DataSpec/DNAMP3/MREA.hpp b/DataSpec/DNAMP3/MREA.hpp index 35d234d54..5747b4393 100644 --- a/DataSpec/DNAMP3/MREA.hpp +++ b/DataSpec/DNAMP3/MREA.hpp @@ -13,6 +13,7 @@ struct MREA { StreamReader(athena::io::IStreamReader& source, atUint32 blkCount, atUint32 secIdxCount); std::vector>::const_iterator beginSecIdxs() { return m_secIdxs.begin(); } void writeSecIdxs(athena::io::IStreamWriter& writer) const; + bool seekToSection(FourCC sec, const std::vector& secSizes); }; struct Header : BigDNA { @@ -84,6 +85,8 @@ struct MREA { static void ReadBabeDeadToBlender_3(hecl::blender::PyOutStream& os, athena::io::IStreamReader& rs); + static UniqueID64 GetPATHId(PAKEntryReadStream& rs); + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, PAKRouter& pakRouter, const PAK::Entry& entry, bool, hecl::blender::Token& btok, std::function); diff --git a/DataSpec/DNAMP3/PATH.hpp b/DataSpec/DNAMP3/PATH.hpp new file mode 100644 index 000000000..f2b218055 --- /dev/null +++ b/DataSpec/DNAMP3/PATH.hpp @@ -0,0 +1,6 @@ +#pragma once +#include "DataSpec/DNACommon/PATH.hpp" + +namespace DataSpec::DNAMP3 { +using PATH = DNAPATH::PATH; +} // namespace DataSpec::DNAMP3 diff --git a/hecl b/hecl index b3d91f520..87ad5cbc8 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit b3d91f520ad3a9429b0116f9b531ec12b2e71809 +Subproject commit 87ad5cbc81dad92d54c60d388157ca6300475c19 From 9a87a2443931a37e1672ab11f79d7bc856b965d6 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 9 Apr 2020 17:21:05 -1000 Subject: [PATCH 11/11] Remove redundant condition from MP2's GetNoShare --- DataSpec/DNAMP2/DNAMP2.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index 116a29b44..208bc8d14 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -25,8 +25,6 @@ namespace DataSpec::DNAMP2 { logvisor::Module Log("urde::DNAMP2"); static bool GetNoShare(std::string_view name) { - if (name == "FrontEnd.pak"sv) - return false; std::string lowerName(name); std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); if (lowerName.compare(0, 7, "metroid") == 0)