From 43fcaf68f1518b9dbb26a06b51a57440c701d2fe Mon Sep 17 00:00:00 2001 From: zeromus Date: Wed, 3 Oct 2018 03:18:16 -0400 Subject: [PATCH] add "ability to move camera" (aka freelook). it requires use of a lua script to actually control the matrix switcheroo re: #130 --- desmume/src/gfx3d.cpp | 41 +++++++++++++++++++- desmume/src/lua-engine.cpp | 79 +++++++++++++++++++++++++++++++++++++- desmume/src/lua-engine.h | 2 + 3 files changed, 118 insertions(+), 4 deletions(-) diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 39affc53c..c475699ce 100755 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -348,6 +348,9 @@ static u16 dsDiffuse, dsAmbient, dsSpecular, dsEmission; //used for indexing the shininess table during parameters to shininess command static u8 shininessInd = 0; +// "Freelook" related things +int freelookMode = 0; +s32 freelookMatrix[16]; //-----------cached things: //these dont need to go into the savestate. they can be regenerated from HW registers @@ -743,8 +746,27 @@ static void SetVertex() if(polylist->count >= POLYLIST_SIZE) return; - GEM_TransformVertex(mtxCurrent[MATRIXMODE_POSITION], coordTransformed); //modelview - GEM_TransformVertex(mtxCurrent[MATRIXMODE_PROJECTION], coordTransformed); //projection + if(freelookMode == 2) + { + //adjust projection + s32 tmp[16]; + MatrixCopy(tmp,mtxCurrent[MATRIXMODE_PROJECTION]); + MatrixMultiply(tmp, freelookMatrix); + GEM_TransformVertex(mtxCurrent[MATRIXMODE_POSITION], coordTransformed); //modelview + GEM_TransformVertex(tmp, coordTransformed); //projection + } + else if(freelookMode == 3) + { + //use provided projection + GEM_TransformVertex(mtxCurrent[MATRIXMODE_POSITION], coordTransformed); //modelview + GEM_TransformVertex(freelookMatrix, coordTransformed); //projection + } + else + { + //no freelook + GEM_TransformVertex(mtxCurrent[MATRIXMODE_POSITION], coordTransformed); //modelview + GEM_TransformVertex(mtxCurrent[MATRIXMODE_PROJECTION], coordTransformed); //projection + } //TODO - culling should be done here. //TODO - viewport transform? @@ -904,6 +926,15 @@ static void SetVertex() } } +static void UpdateProjection() +{ + if(freelookMode == 0) return; + float floatproj[16]; + for(int i=0;i<16;i++) + floatproj[i] = mtxCurrent[MATRIXMODE_PROJECTION][i]/((float)(1<<12)); + CallRegistered3dEvent(0,floatproj); +} + static void gfx3d_glPolygonAttrib_cache() { // Light enable/disable @@ -984,6 +1015,8 @@ static void gfx3d_glPushMatrix() if (index == 1) MMU_new.gxstat.se = 1; index += 1; index &= 1; + + UpdateProjection(); } else { @@ -1031,6 +1064,8 @@ static void gfx3d_glPopMatrix(u32 v) index ^= 1; if (index == 1) MMU_new.gxstat.se = 1; MatrixCopy(mtxCurrent[mode], mtxStackProjection.matrix[0]); + + UpdateProjection(); } else { @@ -1070,6 +1105,7 @@ static void gfx3d_glStoreMatrix(u32 v) if (mode == MATRIXMODE_PROJECTION) { MatrixCopy(mtxStackProjection.matrix[0], mtxCurrent[MATRIXMODE_PROJECTION]); + UpdateProjection(); } else { @@ -1102,6 +1138,7 @@ static void gfx3d_glRestoreMatrix(u32 v) if (mode == MATRIXMODE_PROJECTION) { MatrixCopy(mtxCurrent[MATRIXMODE_PROJECTION], mtxStackProjection.matrix[0]); + UpdateProjection(); } else { diff --git a/desmume/src/lua-engine.cpp b/desmume/src/lua-engine.cpp index e8b6dd6ad..e1a0d2b4a 100644 --- a/desmume/src/lua-engine.cpp +++ b/desmume/src/lua-engine.cpp @@ -3830,6 +3830,38 @@ DEFINE_LUA_FUNCTION(emu_registermenustart, "func") return 1; } +DEFINE_LUA_FUNCTION(emu_set3dtransform, "mode, matrix") +{ + extern int freelookMode; + extern s32 freelookMatrix[16]; + + int mode = luaL_checkinteger(L,1); + freelookMode = mode; + if(mode == 2 || mode == 3) + { + for(int i=0;i<16;i++) + { + lua_rawgeti(L, 2, i+1); + freelookMatrix[i] = (s32)(lua_tonumber(L,-1)*(1<<12)); + lua_pop(L,1); + } + } + + return 0; +} + +DEFINE_LUA_FUNCTION(emu_register3devent, "func") +{ + if (!lua_isnil(L,1)) + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L,1); + lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_REGISTER3DEVENT]); + lua_insert(L,1); + lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_REGISTER3DEVENT]); + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 1; +} + // TODO /* DEFINE_LUA_FUNCTION(emu_loadrom, "filename") @@ -4674,6 +4706,8 @@ static const struct luaL_reg emulib [] = {"addmenu", emu_addmenu}, {"setmenuiteminfo", emu_setmenuiteminfo}, {"registermenustart", emu_registermenustart}, + {"register3devent", emu_register3devent}, + {"set3dtransform", emu_set3dtransform}, // alternative names // {"openrom", emu_loadrom}, {NULL, NULL} @@ -5683,7 +5717,7 @@ bool AnyLuaActive() return false; } -void CallRegisteredLuaFunctions(LuaCallID calltype) +void _CallRegisteredLuaFunctions(LuaCallID calltype, int (*beforeCallback)(lua_State*, void*), void* beforeCallbackArg) { assert((unsigned int)calltype < (unsigned int)LUACALL_COUNT); const char* idstring = luaCallIDStrings[calltype]; @@ -5720,7 +5754,9 @@ void CallRegisteredLuaFunctions(LuaCallID calltype) bool wasRunning = info.running; info.running = true; RefreshScriptSpeedStatus(); - int errorcode = lua_pcall(L, 0, 0, 0); + int nargs = 0; + if(beforeCallback) nargs = beforeCallback(L,beforeCallbackArg); + int errorcode = lua_pcall(L, nargs, 0, 0); info.running = wasRunning; RefreshScriptSpeedStatus(); if (errorcode) @@ -5744,6 +5780,45 @@ void CallRegisteredLuaFunctions(LuaCallID calltype) } } +void CallRegisteredLuaFunctions(LuaCallID calltype) +{ + _CallRegisteredLuaFunctions(calltype, NULL, NULL); +} + +static struct { + int which; + void* arg; +} todo3devent; + +int CallRegistered3dEvent_callback(lua_State* L, void* userarg) +{ + if(todo3devent.which == 0) + { + float* mat = (float*)todo3devent.arg; + lua_newtable(L); + for(int i=0;i<16;i++) + { + lua_pushnumber(L,mat[i]); + lua_rawseti(L,-2,i+1); + } + lua_setfield(L,LUA_GLOBALSINDEX,"registered3devent_arg"); + + lua_pushnumber(L,todo3devent.which); + lua_setfield(L,LUA_GLOBALSINDEX,"registered3devent_which"); + + return 0; + } + + return 0; +} + +void CallRegistered3dEvent(int which, void* arg) +{ + todo3devent.which = which; + todo3devent.arg = arg; + _CallRegisteredLuaFunctions(LUACALL_REGISTER3DEVENT, &CallRegistered3dEvent_callback, NULL); +} + void CallRegisteredLuaSaveFunctions(int savestateNumber, LuaSaveData& saveData) { const char* idstring = luaCallIDStrings[LUACALL_BEFORESAVE]; diff --git a/desmume/src/lua-engine.h b/desmume/src/lua-engine.h index cae475ea5..9ad0d91b9 100644 --- a/desmume/src/lua-engine.h +++ b/desmume/src/lua-engine.h @@ -37,6 +37,7 @@ enum LuaCallID LUACALL_AFTERLOAD, LUACALL_ONSTART, LUACALL_ONINITMENU, + LUACALL_REGISTER3DEVENT, LUACALL_SCRIPT_HOTKEY_1, LUACALL_SCRIPT_HOTKEY_2, @@ -58,6 +59,7 @@ enum LuaCallID LUACALL_COUNT }; void CallRegisteredLuaFunctions(LuaCallID calltype); +void CallRegistered3dEvent(int which, void* arg); enum LuaMemHookType {