From b545c75de31f63560641faa584bfa26f346b6689 Mon Sep 17 00:00:00 2001 From: Super Hackio Date: Thu, 28 Mar 2024 13:23:26 -0700 Subject: [PATCH] Introduce Phantom Renderers So you can see what you're doing:tm: --- data/specialrenderers.json | 50 ++++ src/whitehole/db/SpecialRenderers.java | 5 + .../rendering/special/PhantomRenderer.java | 231 ++++++++++++++++++ 3 files changed, 286 insertions(+) create mode 100644 src/whitehole/rendering/special/PhantomRenderer.java diff --git a/data/specialrenderers.json b/data/specialrenderers.json index e4f40a5..ffff072 100644 --- a/data/specialrenderers.json +++ b/data/specialrenderers.json @@ -229,6 +229,56 @@ } ] }, + { + "ClassName": "Dossun", + "RendererType": "Phantom", + "RendererParams": [ + { + "PhantomEntries": [ + { + "SourcePosY": "Obj_arg0", + "DefaultPosY": 1000 + } + ], + "BVA": { + "Filename": "Wait", + "Frame": 0 + } + } + ] + }, + { + "ObjectName": "LiftFlower", + "RendererType": "Phantom", + "RendererParams": [ + { + "PhantomEntries": [ + { + "SourcePosY": "Obj_arg0", + "DefaultPosY": 600 + } + ] + } + ] + }, + { + "ClassName": "SwitchingMoveBlock", + "RendererType": "Phantom", + "RendererParams": [ + { + "PhantomEntries": [ + { + "SourcePosX": "Obj_arg0", + "SourcePosY": "Obj_arg1", + "SourcePosZ": "Obj_arg2", + "SourceRotX": "Obj_arg3", + "SourceRotY": "Obj_arg4", + "SourceRotZ": "Obj_arg5", + } + ] + } + ] + }, { "ClassName": "SimpleMapObj", "RendererType": "BasicAnim", diff --git a/src/whitehole/db/SpecialRenderers.java b/src/whitehole/db/SpecialRenderers.java index 051a823..8fc2182 100644 --- a/src/whitehole/db/SpecialRenderers.java +++ b/src/whitehole/db/SpecialRenderers.java @@ -46,6 +46,8 @@ public String tryGetAdditiveCacheKey(String objModelName, AbstractObj obj) return BasicAnimationRenderer.getAdditiveCacheKey(obj, renderinfo.rendererParams); case "TwoJointScale": return TwoJointScaleRenderer.getAdditiveCacheKey(obj, renderinfo.rendererParams); + case "Phantom": + return PhantomRenderer.getAdditiveCacheKey(obj, renderinfo.rendererParams); case "PowerStar": return PowerStarRenderer.getAdditiveCacheKey(obj, (Integer)renderinfo.getRenderParamByName("DefaultFrame")); @@ -66,6 +68,9 @@ public GLRenderer tryGetSpecialRenderer(GLRenderer.RenderInfo info, String objMo case "TwoJointScale": result = new TwoJointScaleRenderer(info, objModelName, obj, renderinfo.rendererParams); break; + case "Phantom": + result = new PhantomRenderer(info, objModelName, obj, renderinfo.rendererParams); + break; case "PowerStar": result = new PowerStarRenderer(info, objModelName, obj, (Integer)renderinfo.getRenderParamByName("DefaultFrame"), diff --git a/src/whitehole/rendering/special/PhantomRenderer.java b/src/whitehole/rendering/special/PhantomRenderer.java new file mode 100644 index 0000000..4b8ddea --- /dev/null +++ b/src/whitehole/rendering/special/PhantomRenderer.java @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2024 Whitehole Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package whitehole.rendering.special; + +import com.jogamp.opengl.GL2; +import com.jogamp.opengl.GLException; +import java.util.ArrayList; +import java.util.HashMap; +import org.json.*; +import whitehole.math.Vec3f; +import whitehole.rendering.BmdRenderer; +import whitehole.rendering.GLRenderer; +import whitehole.smg.object.AbstractObj; + +/** + * + * @author Hackio + */ +public class PhantomRenderer extends BasicAnimationRenderer { + + protected HashMap rendererParams; + protected ArrayList phantomList; + + protected PhantomRenderer() { super(); } + + public PhantomRenderer(RenderInfo info, String modelName, AbstractObj obj, HashMap params) + { + if (!ctor_tryLoadModelDefault(modelName)) + return; + + rendererParams = params; + scale = obj.scale; + phantomList = createPhantoms(obj); + + ctor_initBRK(modelName, obj, params); + ctor_initBTK(modelName, obj, params); + ctor_initBTP(modelName, obj, params); + ctor_initBVA(modelName, obj, params); + + ctor_uploadData(info); + } + + + protected ArrayList createPhantoms(AbstractObj obj) + { + ArrayList params = new ArrayList(); + if (rendererParams != null && !rendererParams.isEmpty()) + { + JSONArray PhantomEntries = (JSONArray)rendererParams.get("PhantomEntries"); + + if (PhantomEntries == null) + return null; + + for(var e : PhantomEntries) + { + if (!(e instanceof JSONObject)) + continue; + JSONObject o = (JSONObject)e; + PhantomParam p = new PhantomParam(); + Float FixedPosX = o.optFloat("FixedPosX", 0.f); + Float FixedPosY = o.optFloat("FixedPosY", 0.f); + Float FixedPosZ = o.optFloat("FixedPosZ", 0.f); + Float FixedRotX = o.optFloat("FixedRotX", 0.f); + Float FixedRotY = o.optFloat("FixedRotY", 0.f); + Float FixedRotZ = o.optFloat("FixedRotZ", 0.f); + String SourcePosX = o.optString("SourcePosX", null); + String SourcePosY = o.optString("SourcePosY", null); + String SourcePosZ = o.optString("SourcePosZ", null); + String SourceRotX = o.optString("SourceRotX", null); + String SourceRotY = o.optString("SourceRotY", null); + String SourceRotZ = o.optString("SourceRotZ", null); + Integer DefaultPosX = o.optInt("DefaultPosX", 0); + Integer DefaultPosY = o.optInt("DefaultPosY", 0); + Integer DefaultPosZ = o.optInt("DefaultPosZ", 0); + Integer DefaultRotX = o.optInt("DefaultRotX", 0); + Integer DefaultRotY = o.optInt("DefaultRotY", 0); + Integer DefaultRotZ = o.optInt("DefaultRotZ", 0); + + p.offsetTranslation.x = FixedPosX; + p.offsetTranslation.y = FixedPosY; + p.offsetTranslation.z = FixedPosZ; + p.offsetRotation.x = FixedRotX; + p.offsetRotation.y = FixedRotY; + p.offsetRotation.z = FixedRotZ; + + if (SourcePosX != null) + { + p.offsetSources.add(SourcePosX); + Integer v = (Integer)obj.data.get(SourcePosX); + if (v == null || v == -1) + v = DefaultPosX; + p.offsetTranslation.x += v; + } + if (SourcePosY != null) + { + p.offsetSources.add(SourcePosY); + Integer v = (Integer)obj.data.get(SourcePosY); + if (v == null || v == -1) + v = DefaultPosY; + p.offsetTranslation.y += v; + } + if (SourcePosZ != null) + { + p.offsetSources.add(SourcePosZ); + Integer v = (Integer)obj.data.get(SourcePosZ); + if (v == null || v == -1) + v = DefaultPosZ; + p.offsetTranslation.z += v; + } + + if (SourceRotX != null) + { + p.offsetSources.add(SourceRotX); + Integer v = (Integer)obj.data.get(SourceRotX); + if (v == null || v == -1) + v = DefaultRotX; + p.offsetRotation.x += v; + } + if (SourceRotY != null) + { + p.offsetSources.add(SourceRotY); + Integer v = (Integer)obj.data.get(SourceRotY); + if (v == null || v == -1) + v = DefaultRotY; + p.offsetRotation.y += v; + } + if (SourceRotZ != null) + { + p.offsetSources.add(SourceRotZ); + Integer v = (Integer)obj.data.get(SourceRotZ); + if (v == null || v == -1) + v = DefaultRotZ; + p.offsetRotation.z += v; + } + + params.add(p); + } + } + return params; + } + + @Override + public boolean isScaled() { return false; } + @Override + public boolean hasSpecialScaling() { return true; } + + @Override + public boolean boundToObjArg(int arg) + { + String args = "Obj_arg"+arg; + for (var p : phantomList) + if (p.offsetSources.contains(args)) + return true; + return false; + } + + @Override + public void render(GLRenderer.RenderInfo info) throws GLException + { + GL2 gl = info.drawable.getGL().getGL2(); + + GLRenderer.RenderMode targetMode = GLRenderer.RenderMode.HIGHLIGHT; //Hardcoded for now... + + if (rendererParams != null && !rendererParams.isEmpty() && phantomList != null && info.renderMode == targetMode) + { + // Render Phantoms + + for (var p : phantomList) + { + if (p.absoluteTranslation == null && Vec3f.roughlyEqual(p.offsetTranslation, new Vec3f(0,0,0)) && Vec3f.roughlyEqual(p.offsetRotation, new Vec3f(0,0,0))) + continue; + + gl.glPushMatrix(); + if (p.absoluteTranslation != null) + { + gl.glRotatef(-p.baseRotation.x, 1f, 0f, 0f); + gl.glRotatef(-p.baseRotation.y, 0f, 1f, 0f); + gl.glRotatef(-p.baseRotation.z, 0f, 0f, 1f); + gl.glTranslatef(-p.baseTranslation.x, -p.baseTranslation.y, -p.baseTranslation.z); + } + gl.glTranslatef(p.offsetTranslation.x, p.offsetTranslation.y, p.offsetTranslation.z); + gl.glRotatef(p.offsetRotation.z, 0f, 0f, 1f); + gl.glRotatef(p.offsetRotation.y, 0f, 1f, 0f); + gl.glRotatef(p.offsetRotation.x, 1f, 0f, 0f); + super.render(info); + gl.glPopMatrix(); + } + } + super.render(info); + } + + public static String getAdditiveCacheKey(AbstractObj obj, HashMap params) { + return "_" + + obj.scale.toString() + + obj.data.getInt("Obj_arg0") + + obj.data.getInt("Obj_arg1") + + obj.data.getInt("Obj_arg2") + + obj.data.getInt("Obj_arg3") + + obj.data.getInt("Obj_arg4") + + obj.data.getInt("Obj_arg5") + + obj.data.getInt("Obj_arg6") + + obj.data.getInt("Obj_arg7") + + obj.data.getShort("CommonPath_ID"); + } + + + public class PhantomParam + { + public Vec3f offsetTranslation = new Vec3f(); + public Vec3f offsetRotation = new Vec3f(); + public ArrayList offsetSources = new ArrayList(); + + public Vec3f absoluteTranslation = null; + public Vec3f baseTranslation = null; + public Vec3f baseRotation = null; + } +}