From 118706e9ece26b31ecc0c11b824d92879f88925d Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Tue, 9 Jan 2024 23:19:24 -0800 Subject: [PATCH 01/12] Initial commit --- libzhl/functions/Point.zhl | 14 +- libzhl/functions/Vector2.zhl | 14 ++ repentogon/LuaInterfaces/LuaBeamRenderer.cpp | 17 +++ repentogon/Reimplementations/Rope.hpp | 132 +++++++++++++++++++ 4 files changed, 169 insertions(+), 8 deletions(-) create mode 100644 repentogon/Reimplementations/Rope.hpp diff --git a/libzhl/functions/Point.zhl b/libzhl/functions/Point.zhl index 850863de6..e4784e795 100644 --- a/libzhl/functions/Point.zhl +++ b/libzhl/functions/Point.zhl @@ -1,11 +1,9 @@ -"558bec83ec10568bf1f30f1046": -__thiscall void Point::UpdateNormal(Vector* unk); - struct Point depends (Vector) { {{ - Point() : _pos(Vector()), _spritesheetCoordinate(0.0f), _width(1.0f) {} - Point(Vector const& pos, float spritesheetCoordinate, float width) : _pos(pos), _spritesheetCoordinate(spritesheetCoordinate), _width(width) {} + Point() : _pos(Vector()), _lastPos(_pos), _spritesheetCoordinate(0.0f), _width(1.0f), _fixed(false) {} + Point(Vector const& pos, float spritesheetCoordinate, float width, bool fixed) : _pos(pos), _lastPos(pos), _spritesheetCoordinate(spritesheetCoordinate), _width(width) , _fixed(fixed) {} }} - Vector _pos : 0x0; - float _width : 0x8, _spritesheetCoordinate : 0xc; -} : 0x10; \ No newline at end of file + Vector _pos : 0x0, _lastPos : 0x8; + float _width : 0x10, _spritesheetCoordinate : 0x14; + bool _fixed : 0x18; +} : 0x1c; \ No newline at end of file diff --git a/libzhl/functions/Vector2.zhl b/libzhl/functions/Vector2.zhl index 9854ec6e7..26c69e8cd 100644 --- a/libzhl/functions/Vector2.zhl +++ b/libzhl/functions/Vector2.zhl @@ -29,6 +29,20 @@ struct Vector { {{ y *= amount; return *this; } + + Vector& operator+=(const Vector& other) + { + x += other.x; + y += other.y; + return *this; + } + + Vector& operator-=(const Vector& other) + { + x -= other.x; + y -= other.y; + return *this; + } }} float x : 0x0, y : 0x4; } : 0x8; diff --git a/repentogon/LuaInterfaces/LuaBeamRenderer.cpp b/repentogon/LuaInterfaces/LuaBeamRenderer.cpp index 396b9b7eb..03c36e99d 100644 --- a/repentogon/LuaInterfaces/LuaBeamRenderer.cpp +++ b/repentogon/LuaInterfaces/LuaBeamRenderer.cpp @@ -316,10 +316,25 @@ LUA_FUNCTION(Lua_PointGetPosition) { LUA_FUNCTION(Lua_PointSetPosition) { Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + point->_lastPos = point->_pos; point->_pos = *lua::GetUserdata(L, 2, lua::Metatables::VECTOR, "Vector"); return 0; } +LUA_FUNCTION(Lua_PointGetFixed) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + lua_pushboolean(L, point->_fixed); + return 1; +} + +LUA_FUNCTION(Lua_PointSetFixed) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + point->_fixed = lua::luaL_checkboolean(L, 2); + if (point->_fixed) + point->_lastPos = point->_pos; + return 0; +} + static void RegisterBeamRenderer(lua_State* L) { luaL_Reg functions[] = { { "Add", Lua_BeamAdd}, @@ -334,6 +349,8 @@ static void RegisterBeamRenderer(lua_State* L) { { "SetUnkBool", Lua_BeamSetUnkBool}, { "GetPoints", Lua_BeamGetPoints}, { "SetPoints", Lua_BeamSetPoints}, + { "GetFixed", Lua_BeamGetPoints}, + { "SetFixed", Lua_BeamSetPoints}, { NULL, NULL } }; lua::RegisterNewClass(L, lua::metatables::BeamMT, lua::metatables::BeamMT, functions, Lua_BeamRenderer__gc); diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp new file mode 100644 index 000000000..fca8a46f7 --- /dev/null +++ b/repentogon/Reimplementations/Rope.hpp @@ -0,0 +1,132 @@ +/* + This is an adaptation of work from Franciszek Szewczyk, who made an intuitive article + explaining 2D rope physics and methods of implementation. + The gist: https://gist.github.com/fszewczyk/46915c02a34a1833d83a3c2fd851b7a0 + The article: https://medium.com/@szewczyk.franciszek02/rope-simulator-in-c-a595a3ef956c + + The main changes here are the removal of gravity, the adaptation of types to IsaacRepentance ones, + and handling rendering through BeamRenderer. +*/ + +#pragma once + +#include "IsaacRepentance.h" +#include +#include +#include + +float TIMESTEP = 0.01f; // Δt in our equations +unsigned int JAKOBSEN_ITERATIONS = 50; // number of times we will enforce the distance constraint + +class Rope { + public: + Rope(Vector* start, Vector* end, unsigned int nPoints, float spriteStretchHeight, float spriteStretchWidth) { + _origin = *start; + _target = *end; + + float ropeLength = (float)sqrt(pow(_origin.x - _target.x, 2) + pow(_origin.y - _target.y, 2)); + + // There is one less segment than there are Points + unsigned int numSegments = nPoints - 1; + + _desiredDistance = ropeLength / numSegments; + + for (unsigned int i = 0; i < nPoints; i++) { + // percent distance from start to end, 0.0->1.0 + float w = (float)i / (nPoints - 1); + + Vector pos(w * _target.x + (1 - w) * _origin.x, w * _target.y + (1 - w) * _origin.y); + float spritesheetCoord = ropeLength * w * spriteStretchHeight; + + Point p(pos, spritesheetCoord, spriteStretchWidth, false); + + _points.push_back(p); + } + } + + void Update(Vector * newOrigin, Vector * newTarget) { + verletIntegration(newOrigin, newTarget); + enforceConstraints(); + } + + void Render(ANM2* anm2, unsigned int layerID, bool useOverlay, bool unk) { + g_BeamRenderer->Begin(anm2, layerID, useOverlay, unk); + + #pragma warning(suppress:4533) + ColorMod color; + for (auto it = _points.begin(); it != _points.end(); ++it) { + g_BeamRenderer->Add(&it->_pos, &color, it->_width, it->_spritesheetCoordinate); + } + + g_BeamRenderer->End(); + } + + // We need to store our Points somewhere + std::deque _points; + + // Target distance of a single segment + float _desiredDistance; + + Vector _origin; + Vector _target; + + private: + void verletIntegration(Vector* newOrigin, Vector* newTarget) { + for (auto p = _points.begin(); p != _points.end(); ++p) { + if (p->_fixed) + continue; // We do not want to move fixed Points + if (p == _points.begin()) { + p->_pos = *newOrigin; + continue; + } + if (p == _points.end() - 1) { + p->_pos = *newTarget; + continue; + } + Vector copy = p->_pos; + + // Calculating previous velocity + Vector velocity((p->_pos.x - p->_lastPos.x) / TIMESTEP, (p->_pos.y - p->_lastPos.y) / TIMESTEP); + + // Updating Point's position + p->_pos += velocity * TIMESTEP; + + p->_lastPos = copy; + } + } + + void enforceConstraints() { + // We perform the enforcement multiple times + for (unsigned int iteration = 0; iteration < JAKOBSEN_ITERATIONS; iteration++) { + // We iterate over each pair of points + for (size_t i = 1; i < _points.size(); i++) { + Point &p1 = _points[i - 1]; + Point &p2 = _points[i]; + + // Calculating distance between the Points + float distance = (float)sqrt(pow(p1._pos.x - p2._pos.x, 2) + pow(p1._pos.y - p2._pos.y, 2)); + float distanceError = distance - _desiredDistance; + + // The direction in which Points should be pulled or pushed + Vector difference(p2._pos.x - p1._pos.x, p2._pos.y - p1._pos.y); + + // We need to make it a unit vector + // This will allow us to easily scale the impact we have + // on each Point's position. + Vector direction(difference.x / (float)sqrt(pow(difference.x, 2) + pow(difference.y, 2)), difference.y / (float)sqrt(pow(difference.x, 2) + pow(difference.y, 2))); + + // Finally, we can update Points' positions + // We need to remember that fixed Points should stay in place + if (p1._fixed && !p2._fixed) { + p2._pos -= direction * distanceError; + } else if (p2._fixed && !p1._fixed) { + p1._pos += direction * distanceError; + // keeping this comparison in case both points are fixed + } else if (!p1._fixed && !p2._fixed) { + p2._pos -= direction * distanceError * 0.5; + p2._pos += direction * distanceError * 0.5; + } + } + } + } +}; From c7c5d0bdd45afaa93184e8e01bbc21f60ed46f91 Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Tue, 9 Jan 2024 23:34:49 -0800 Subject: [PATCH 02/12] change origin to entity --- repentogon/Reimplementations/Rope.hpp | 33 ++++++++++++--------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp index fca8a46f7..868b9ca29 100644 --- a/repentogon/Reimplementations/Rope.hpp +++ b/repentogon/Reimplementations/Rope.hpp @@ -20,11 +20,12 @@ unsigned int JAKOBSEN_ITERATIONS = 50; // number of times we will enforce the di class Rope { public: - Rope(Vector* start, Vector* end, unsigned int nPoints, float spriteStretchHeight, float spriteStretchWidth) { - _origin = *start; + Rope(Entity* origin, Vector* end, unsigned int nPoints, float spriteStretchHeight, float spriteStretchWidth) { + _originEntity = origin; _target = *end; + Vector* start = origin->GetPosition(); - float ropeLength = (float)sqrt(pow(_origin.x - _target.x, 2) + pow(_origin.y - _target.y, 2)); + float ropeLength = (float)sqrt(pow(start->x - _target.x, 2) + pow(start->y - _target.y, 2)); // There is one less segment than there are Points unsigned int numSegments = nPoints - 1; @@ -35,17 +36,17 @@ class Rope { // percent distance from start to end, 0.0->1.0 float w = (float)i / (nPoints - 1); - Vector pos(w * _target.x + (1 - w) * _origin.x, w * _target.y + (1 - w) * _origin.y); + Vector pos(w * _target.x + (1 - w) * start->x, w * _target.y + (1 - w) * start->y); float spritesheetCoord = ropeLength * w * spriteStretchHeight; - Point p(pos, spritesheetCoord, spriteStretchWidth, false); + Point p(pos, spritesheetCoord, spriteStretchWidth, i == 0); _points.push_back(p); } } - void Update(Vector * newOrigin, Vector * newTarget) { - verletIntegration(newOrigin, newTarget); + void Update() { + verletIntegration(); enforceConstraints(); } @@ -67,22 +68,18 @@ class Rope { // Target distance of a single segment float _desiredDistance; - Vector _origin; + Entity * _originEntity; Vector _target; private: - void verletIntegration(Vector* newOrigin, Vector* newTarget) { - for (auto p = _points.begin(); p != _points.end(); ++p) { + void verletIntegration() { + _points.begin()->_pos = *_originEntity->GetPosition(); + _points.begin()->_lastPos = _points.begin()->_pos; + + for (auto p = _points.begin()+1; p != _points.end(); ++p) { if (p->_fixed) continue; // We do not want to move fixed Points - if (p == _points.begin()) { - p->_pos = *newOrigin; - continue; - } - if (p == _points.end() - 1) { - p->_pos = *newTarget; - continue; - } + Vector copy = p->_pos; // Calculating previous velocity From 82c12723dfd668fa6391e2bc190d72f0334bdabd Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Wed, 10 Jan 2024 04:13:00 -0800 Subject: [PATCH 03/12] current progress lua seems to pretend Cord:Update doesn't exist, and is also crashing at Render before even reaching the breakpoint --- libzhl/LuaCore.cpp | 2 + libzhl/LuaCore.h | 2 + libzhl/functions/BeamRenderer.zhl | 6 +- libzhl/functions/Isaac.zhl | 3 + libzhl/functions/Point.zhl | 6 +- repentogon/LuaInterfaces/LuaBeamRenderer.cpp | 101 ++----------- repentogon/LuaInterfaces/LuaCord.cpp | 55 +++++++ repentogon/LuaInterfaces/LuaPoint.cpp | 143 +++++++++++++++++++ repentogon/Reimplementations/Rope.hpp | 21 ++- 9 files changed, 240 insertions(+), 99 deletions(-) create mode 100644 repentogon/LuaInterfaces/LuaCord.cpp create mode 100644 repentogon/LuaInterfaces/LuaPoint.cpp diff --git a/libzhl/LuaCore.cpp b/libzhl/LuaCore.cpp index c0b230253..5971d7a2a 100644 --- a/libzhl/LuaCore.cpp +++ b/libzhl/LuaCore.cpp @@ -737,6 +737,7 @@ namespace lua { const char* CollectionMenuMT = "CollectionMenu"; const char* ConsoleMT = "Console"; const char* ControllerSelectMenuMT = "ControllerSelectMenu"; + const char* CordMT = "Cord"; const char* ColorModifierMT = "ColorModifier"; const char* CustomChallengeMenuMT = "CustomChallengeMenu"; const char* CutscenesMenuMT = "CutscenesMenu"; @@ -786,6 +787,7 @@ namespace lua { const char* PlayerManagerMT = "PlayerManager"; const char* PocketItemMT = "PocketItem"; const char* PointMT = "Point"; + const char* PointDequeMT = "PointDeque"; const char* ProceduralEffectMT = "ProceduralEffect"; const char* ProceduralItemMT = "ProceduralItem"; const char* ProceduralItemManagerMT = "ProceduralItemManager"; diff --git a/libzhl/LuaCore.h b/libzhl/LuaCore.h index 6a25d0c5d..50c4e0ea7 100644 --- a/libzhl/LuaCore.h +++ b/libzhl/LuaCore.h @@ -173,6 +173,7 @@ namespace lua { extern LIBZHL_API const char* ConsoleMT; extern LIBZHL_API const char* ControllerSelectMenuMT; extern LIBZHL_API const char* ColorModifierMT; + extern LIBZHL_API const char* CordMT; extern LIBZHL_API const char* CustomChallengeMenuMT; extern LIBZHL_API const char* CutscenesMenuMT; extern LIBZHL_API const char* GridEntitiesSaveStateVectorMT; @@ -221,6 +222,7 @@ namespace lua { extern LIBZHL_API const char* PlayerManagerMT; extern LIBZHL_API const char* PocketItemMT; extern LIBZHL_API const char* PointMT; + extern LIBZHL_API const char* PointDequeMT; extern LIBZHL_API const char* ProceduralEffectMT; extern LIBZHL_API const char* ProceduralItemMT; extern LIBZHL_API const char* ProceduralItemManagerMT; diff --git a/libzhl/functions/BeamRenderer.zhl b/libzhl/functions/BeamRenderer.zhl index f7672d38e..961e7d93d 100644 --- a/libzhl/functions/BeamRenderer.zhl +++ b/libzhl/functions/BeamRenderer.zhl @@ -12,7 +12,7 @@ static void BeamRenderer::End(); // we don't actually use Point here, just a deque, but for some reason // the deque insists that Point must be defined before BeamRenderer -struct BeamRenderer depends (ANM2, Point) { +struct BeamRenderer depends (ANM2, PointDeque) { {{ BeamRenderer(ANM2& anm2, unsigned int layer, bool useOverlayData, bool unkBool) : _anm2(anm2), _layer(layer), _useOverlayData(useOverlayData), _unkBool(unkBool) {} @@ -25,5 +25,5 @@ struct BeamRenderer depends (ANM2, Point) { unsigned int _layer : 0x4; bool _useOverlayData : 0x8; bool _unkBool : 0x9; - deque_Point _points : 0xc; -} : 0x30; \ No newline at end of file + PointDeque _points : 0xc; +} : 0x20; \ No newline at end of file diff --git a/libzhl/functions/Isaac.zhl b/libzhl/functions/Isaac.zhl index 544b99a39..bb0eb4234 100644 --- a/libzhl/functions/Isaac.zhl +++ b/libzhl/functions/Isaac.zhl @@ -52,6 +52,9 @@ static __fastcall void Isaac::GetRandomPickupVelocity(Vector * buffer, Vector * "558bec83e4f883ec148b02": static __x86_64_output Vector Isaac::GetCollectibleSpawnPosition(Vector* target); +"558bec83e4c083ec34538b1d": +static __stdcall Vector* Isaac::WorldToScreen(Vector* buffer, Vector* pos); + struct Isaac { {{ LIBZHL_API static bool IsInGame(); diff --git a/libzhl/functions/Point.zhl b/libzhl/functions/Point.zhl index e4784e795..4dacfa86f 100644 --- a/libzhl/functions/Point.zhl +++ b/libzhl/functions/Point.zhl @@ -6,4 +6,8 @@ struct Point depends (Vector) { Vector _pos : 0x0, _lastPos : 0x8; float _width : 0x10, _spritesheetCoordinate : 0x14; bool _fixed : 0x18; -} : 0x1c; \ No newline at end of file +} : 0x1c; + +struct PointDeque depends (Point) { + deque_Point deque : 0x0; +} : 0x14; \ No newline at end of file diff --git a/repentogon/LuaInterfaces/LuaBeamRenderer.cpp b/repentogon/LuaInterfaces/LuaBeamRenderer.cpp index 03c36e99d..3f44fac46 100644 --- a/repentogon/LuaInterfaces/LuaBeamRenderer.cpp +++ b/repentogon/LuaInterfaces/LuaBeamRenderer.cpp @@ -48,12 +48,6 @@ LUA_FUNCTION(Lua_CreateBeamDummy) { return 1; } -void ConstructPoint(lua_State* L, Point& point, uint8_t offset) { - point._pos = *lua::GetUserdata(L, offset, lua::Metatables::VECTOR, "Vector"); - point._spritesheetCoordinate = (float)luaL_checknumber(L, offset+1); - point._width = (float)luaL_optnumber(L, offset+2, 1.0f); -} - LUA_FUNCTION(Lua_BeamAdd) { BeamRenderer* beam = lua::GetUserdata(L, 1, lua::metatables::BeamMT); Point point; @@ -62,9 +56,11 @@ LUA_FUNCTION(Lua_BeamAdd) { } else { - ConstructPoint(L, point, 2); + point._pos = *lua::GetUserdata(L, 2, lua::Metatables::VECTOR, "Vector"); + point._spritesheetCoordinate = (float)luaL_checknumber(L, 3); + point._width = (float)luaL_optnumber(L, 4, 1.0f); } - beam->_points.push_back(point); + beam->_points.deque.push_back(point); return 0; } @@ -74,7 +70,7 @@ LUA_FUNCTION(Lua_BeamRender) { int8_t error = -1; bool clearPoints = lua::luaL_optboolean(L, 2, true); - if (beam->_points.size() < 2) { + if (beam->_points.deque.size() < 2) { error = 0; goto funcEnd; } @@ -99,7 +95,7 @@ LUA_FUNCTION(Lua_BeamRender) { #pragma warning(suppress:4533) ColorMod color; - for (auto it = beam->_points.begin(); it != beam->_points.end(); ++it) { + for (auto it = beam->_points.deque.begin(); it != beam->_points.deque.end(); ++it) { g_BeamRenderer->Add(&it->_pos, &color, it->_width, it->_spritesheetCoordinate); } @@ -109,7 +105,7 @@ LUA_FUNCTION(Lua_BeamRender) { funcEnd: if (clearPoints) { - beam->_points.clear(); + beam->_points.deque.clear(); } if (error != -1) { @@ -234,10 +230,10 @@ LUA_FUNCTION(Lua_BeamRenderer__gc) { LUA_FUNCTION(Lua_BeamGetPoints) { BeamRenderer* beam = lua::GetUserdata(L, 1, lua::metatables::BeamMT); lua_newtable(L); - for (size_t i = 0; i < beam->_points.size(); ++i) { + for (size_t i = 0; i < beam->_points.deque.size(); ++i) { lua_pushinteger(L, i + 1); Point* ud = (Point*)lua_newuserdata(L, sizeof(Point)); - *ud = beam->_points[i]; + *ud = beam->_points.deque[i]; luaL_setmetatable(L, lua::metatables::PointMT); lua_rawset(L, -3); } @@ -266,75 +262,12 @@ LUA_FUNCTION(Lua_BeamSetPoints) { list.push_back(*lua::GetUserdata(L, -1, lua::metatables::PointMT)); lua_pop(L, 1); } - beam->_points = list; + beam->_points.deque = list; } return 0; } -LUA_FUNCTION(Lua_PointConstructor) { - Point point; - ConstructPoint(L, point, 1); - - Point* toLua = lua::place(L, lua::metatables::PointMT); - *toLua = point; - luaL_setmetatable(L, lua::metatables::PointMT); - - return 1; -} - -LUA_FUNCTION(Lua_PointGetSpritesheetCoordinate) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); - lua_pushnumber(L, point->_spritesheetCoordinate); - return 1; -} - -LUA_FUNCTION(Lua_PointSetSpritesheetCoordinate) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); - point->_spritesheetCoordinate = (float)luaL_checknumber(L, 2); - return 0; -} - -LUA_FUNCTION(Lua_PointGetWidth) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); - lua_pushnumber(L, point->_width); - return 1; -} - -LUA_FUNCTION(Lua_PointSetWidth) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); - point->_width = (float)luaL_checknumber(L, 2); - return 0; -} - -LUA_FUNCTION(Lua_PointGetPosition) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); - Vector* toLua = lua::luabridge::UserdataValue::place(L, lua::GetMetatableKey(lua::Metatables::VECTOR)); - *toLua = point->_pos; - return 1; -} - -LUA_FUNCTION(Lua_PointSetPosition) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); - point->_lastPos = point->_pos; - point->_pos = *lua::GetUserdata(L, 2, lua::Metatables::VECTOR, "Vector"); - return 0; -} - -LUA_FUNCTION(Lua_PointGetFixed) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); - lua_pushboolean(L, point->_fixed); - return 1; -} - -LUA_FUNCTION(Lua_PointSetFixed) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); - point->_fixed = lua::luaL_checkboolean(L, 2); - if (point->_fixed) - point->_lastPos = point->_pos; - return 0; -} - static void RegisterBeamRenderer(lua_State* L) { luaL_Reg functions[] = { { "Add", Lua_BeamAdd}, @@ -355,20 +288,6 @@ static void RegisterBeamRenderer(lua_State* L) { }; lua::RegisterNewClass(L, lua::metatables::BeamMT, lua::metatables::BeamMT, functions, Lua_BeamRenderer__gc); lua_register(L, lua::metatables::BeamMT, Lua_CreateBeamDummy); - - luaL_Reg pointFunctions[] = { - { "GetSpritesheetCoordinate", Lua_PointGetSpritesheetCoordinate}, - { "SetSpritesheetCoordinate", Lua_PointSetSpritesheetCoordinate}, - { "GetHeight", Lua_PointGetSpritesheetCoordinate}, // deprecated - { "SetHeight", Lua_PointSetSpritesheetCoordinate}, // deprecated - { "GetWidth", Lua_PointGetWidth}, - { "SetWidth", Lua_PointSetWidth}, - { "GetPosition", Lua_PointGetPosition}, - { "SetPosition", Lua_PointSetPosition}, - { NULL, NULL } - }; - lua::RegisterNewClass(L, lua::metatables::PointMT, lua::metatables::PointMT, pointFunctions); - lua_register(L, lua::metatables::PointMT, Lua_PointConstructor); } HOOK_METHOD(LuaEngine, RegisterClasses, () -> void) { diff --git a/repentogon/LuaInterfaces/LuaCord.cpp b/repentogon/LuaInterfaces/LuaCord.cpp new file mode 100644 index 000000000..c282f4ad4 --- /dev/null +++ b/repentogon/LuaInterfaces/LuaCord.cpp @@ -0,0 +1,55 @@ +#include "IsaacRepentance.h" +#include "LuaCore.h" +#include "HookSystem.h" + +#include "../Reimplementations/Rope.hpp" + +LUA_FUNCTION(Lua_CreateCord) { + Entity* parent = lua::GetUserdata(L, 1, lua::Metatables::ENTITY, "Entity"); + Vector* pos = lua::GetUserdata(L, 2, lua::Metatables::VECTOR, "Vector"); + int numPoints = (int)luaL_checkinteger(L, 3); + float stretchHeight = (float)luaL_optnumber(L, 4, 1.0); + float stretchWidth = (float)luaL_optnumber(L, 5, 1.0); + Rope* toLua = lua::place(L, lua::metatables::CordMT, parent, pos, numPoints, stretchHeight, stretchWidth); + luaL_setmetatable(L, lua::metatables::BeamMT); + return 1; +} + +LUA_FUNCTION(Lua_CordUpdate) { + Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); + rope->Update(); + return 0; +} + +LUA_FUNCTION(Lua_CordRender) { + Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); + ANM2* anm2 = lua::GetUserdata(L, 2, lua::Metatables::SPRITE, "Sprite"); + int layerID = (int)luaL_checkinteger(L, 3); + bool useOverlay = lua::luaL_checkboolean(L, 4); + bool unk = lua::luaL_optboolean(L, 5, false); + rope->Render(anm2, layerID, useOverlay, unk); + return 0; +} + +LUA_FUNCTION(Lua_Cord__gc) { + Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); + rope->~Rope(); + return 0; +} + +static void RegisterCord(lua_State* L) { + luaL_Reg functions[] = { + { "Render", Lua_CordRender}, + { "Update", Lua_CordUpdate}, + { NULL, NULL } + }; + lua::RegisterNewClass(L, lua::metatables::CordMT, lua::metatables::CordMT, functions, Lua_Cord__gc); + lua_register(L, lua::metatables::CordMT, Lua_CreateCord); +} + +HOOK_METHOD(LuaEngine, RegisterClasses, () -> void) { + super(); + + lua::LuaStackProtector protector(_state); + RegisterCord(_state); +} \ No newline at end of file diff --git a/repentogon/LuaInterfaces/LuaPoint.cpp b/repentogon/LuaInterfaces/LuaPoint.cpp new file mode 100644 index 000000000..68797e7dc --- /dev/null +++ b/repentogon/LuaInterfaces/LuaPoint.cpp @@ -0,0 +1,143 @@ +#include "IsaacRepentance.h" +#include "LuaCore.h" +#include "HookSystem.h" + +LUA_FUNCTION(Lua_PointConstructor) { + Point point; + point._pos = *lua::GetUserdata(L, 1, lua::Metatables::VECTOR, "Vector"); + point._spritesheetCoordinate = (float)luaL_checknumber(L, 2); + point._width = (float)luaL_optnumber(L, 3, 1.0f); + + Point* toLua = lua::place(L, lua::metatables::PointMT); + *toLua = point; + luaL_setmetatable(L, lua::metatables::PointMT); + + return 1; +} + +LUA_FUNCTION(Lua_PointGetSpritesheetCoordinate) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + lua_pushnumber(L, point->_spritesheetCoordinate); + return 1; +} + +LUA_FUNCTION(Lua_PointSetSpritesheetCoordinate) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + point->_spritesheetCoordinate = (float)luaL_checknumber(L, 2); + return 0; +} + +LUA_FUNCTION(Lua_PointGetWidth) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + lua_pushnumber(L, point->_width); + return 1; +} + +LUA_FUNCTION(Lua_PointSetWidth) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + point->_width = (float)luaL_checknumber(L, 2); + return 0; +} + +LUA_FUNCTION(Lua_PointGetPosition) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Vector* toLua = lua::luabridge::UserdataValue::place(L, lua::GetMetatableKey(lua::Metatables::VECTOR)); + *toLua = point->_pos; + return 1; +} + +LUA_FUNCTION(Lua_PointSetPosition) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + point->_lastPos = point->_pos; + point->_pos = *lua::GetUserdata(L, 2, lua::Metatables::VECTOR, "Vector"); + return 0; +} + +LUA_FUNCTION(Lua_PointGetFixed) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + lua_pushboolean(L, point->_fixed); + return 1; +} + +LUA_FUNCTION(Lua_PointSetFixed) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + point->_fixed = lua::luaL_checkboolean(L, 2); + if (point->_fixed) + point->_lastPos = point->_pos; + return 0; +} + +/*//////////////////// +//// Deque time +*///////////////////// + +LUA_FUNCTION(Lua_PointDequePushBack) { + PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + Point* point = lua::GetUserdata(L, 2, lua::metatables::PointMT); + d->deque.push_back(*point); + + return 0; +} + +LUA_FUNCTION(Lua_PointDequePushFront) { + PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + Point* point = lua::GetUserdata(L, 2, lua::metatables::PointMT); + d->deque.push_front(*point); + + return 0; +} + +LUA_FUNCTION(Lua_PointDequePopBack) { + PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + d->deque.pop_back(); + + return 0; +} + +LUA_FUNCTION(Lua_PointDequePopFront) { + PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + d->deque.pop_front(); + + return 0; +} + +LUA_FUNCTION(Lua_PointDeque__gc) { + PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + d->~PointDeque(); + return 0; +} + +static void RegisterPoint(lua_State* L) { + luaL_Reg pointFunctions[] = { + { "GetSpritesheetCoordinate", Lua_PointGetSpritesheetCoordinate}, + { "SetSpritesheetCoordinate", Lua_PointSetSpritesheetCoordinate}, + { "GetHeight", Lua_PointGetSpritesheetCoordinate}, // deprecated + { "SetHeight", Lua_PointSetSpritesheetCoordinate}, // deprecated + { "GetWidth", Lua_PointGetWidth}, + { "SetWidth", Lua_PointSetWidth}, + { "GetPosition", Lua_PointGetPosition}, + { "SetPosition", Lua_PointSetPosition}, + { NULL, NULL } + }; + + lua::RegisterNewClass(L, lua::metatables::PointMT, lua::metatables::PointMT, pointFunctions); + lua_register(L, lua::metatables::PointMT, Lua_PointConstructor); + + luaL_Reg dequeFunctions[] = { + { "PushBack", Lua_PointDequePushBack}, + { "PushFront", Lua_PointDequePushFront }, + { "PopBack", Lua_PointDequePopBack }, + { "PopFront", Lua_PointDequePopFront }, + { NULL, NULL } + }; + + lua::RegisterNewClass(L, lua::metatables::PointDequeMT, lua::metatables::PointDequeMT, dequeFunctions, Lua_PointDeque__gc); + //lua_register(L, lua::metatables::PointDequeMT, Lua_PointConstructor); +} + +HOOK_METHOD(LuaEngine, RegisterClasses, () -> void) { + super(); + + lua::LuaStackProtector protector(_state); + RegisterPoint(_state); +} \ No newline at end of file diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp index 868b9ca29..d9e81a62a 100644 --- a/repentogon/Reimplementations/Rope.hpp +++ b/repentogon/Reimplementations/Rope.hpp @@ -21,6 +21,7 @@ unsigned int JAKOBSEN_ITERATIONS = 50; // number of times we will enforce the di class Rope { public: Rope(Entity* origin, Vector* end, unsigned int nPoints, float spriteStretchHeight, float spriteStretchWidth) { + printf("constructing rope: entity %p, start %f %f, end %f %f, nPoints %d, spriteStretchHeight %f, float spriteStretchWidth %f\n", origin, origin->GetPosition()->x, origin->GetPosition()->y, end->x, end->y, nPoints, spriteStretchHeight, spriteStretchWidth); _originEntity = origin; _target = *end; Vector* start = origin->GetPosition(); @@ -32,6 +33,8 @@ class Rope { _desiredDistance = ropeLength / numSegments; + printf("length: %f, segments : %d, avg distance: %f\n", ropeLength, numSegments, _desiredDistance); + for (unsigned int i = 0; i < nPoints; i++) { // percent distance from start to end, 0.0->1.0 float w = (float)i / (nPoints - 1); @@ -40,6 +43,7 @@ class Rope { float spritesheetCoord = ropeLength * w * spriteStretchHeight; Point p(pos, spritesheetCoord, spriteStretchWidth, i == 0); + printf("created point at pos %f, %f with coord %f\n", p._pos.x, p._pos.y, p._spritesheetCoordinate); _points.push_back(p); } @@ -51,12 +55,18 @@ class Rope { } void Render(ANM2* anm2, unsigned int layerID, bool useOverlay, bool unk) { + __debugbreak(); + if (_points.size() < 2) + return; + g_BeamRenderer->Begin(anm2, layerID, useOverlay, unk); #pragma warning(suppress:4533) ColorMod color; + Vector buffer; for (auto it = _points.begin(); it != _points.end(); ++it) { - g_BeamRenderer->Add(&it->_pos, &color, it->_width, it->_spritesheetCoordinate); + Isaac::WorldToScreen(&buffer, &it->_pos); + g_BeamRenderer->Add(&buffer, &color, it->_width, it->_spritesheetCoordinate); } g_BeamRenderer->End(); @@ -73,12 +83,15 @@ class Rope { private: void verletIntegration() { - _points.begin()->_pos = *_originEntity->GetPosition(); - _points.begin()->_lastPos = _points.begin()->_pos; + if (_originEntity != nullptr) { + _points.begin()->_pos = *_originEntity->GetPosition(); + _points.begin()->_lastPos = _points.begin()->_pos; + } for (auto p = _points.begin()+1; p != _points.end(); ++p) { + // We do not want to move fixed Points if (p->_fixed) - continue; // We do not want to move fixed Points + continue; Vector copy = p->_pos; From ce953ebe8c8bca93908a81e3486949513734245c Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Wed, 10 Jan 2024 17:50:17 -0800 Subject: [PATCH 04/12] basic rope implementation --- libzhl/IsaacRepentance_static.cpp | 15 ++++++++ libzhl/functions/Game.zhl | 5 +-- libzhl/functions/Isaac.zhl | 4 +-- libzhl/functions/LuaEngine.zhl | 3 -- libzhl/functions/Room.zhl | 3 +- repentogon/LuaInterfaces/LuaCord.cpp | 10 +++++- repentogon/Reimplementations/Rope.hpp | 49 ++++++++++++++++----------- 7 files changed, 59 insertions(+), 30 deletions(-) diff --git a/libzhl/IsaacRepentance_static.cpp b/libzhl/IsaacRepentance_static.cpp index 7c7255ac5..beffb9534 100644 --- a/libzhl/IsaacRepentance_static.cpp +++ b/libzhl/IsaacRepentance_static.cpp @@ -198,4 +198,19 @@ bool ItemConfig::IsValidTrinket(unsigned int TrinketType) { bool Isaac::IsInGame() { return g_Manager->GetState() == 2 && g_Game; +} + +Vector * Isaac::WorldToScreen(Vector * ret, Vector* pos) { + Game * game = g_Game; + if (!game) { + ret = pos; + return ret; + } + float scale = g_DisplayPixelsPerPoint * g_PointScale; + Room* room = game->_room; + float f1 = floor((((g_WIDTH - 338.0f) * 0.5f + (pos->x - 60.0f) * 0.65f) * scale + 0.5f)); + float f2 = floor((((g_HEIGHT - 182.0f) * 0.5f + (pos->y - 140.0f) * 0.65f) * scale + 0.5f)); + ret->x = f1 / scale + room->_renderScrollOffset.x + game->_screenShakeOffset.x; + ret->y = f2 / scale + room->_renderScrollOffset.y + game->_screenShakeOffset.y; + return ret; } \ No newline at end of file diff --git a/libzhl/functions/Game.zhl b/libzhl/functions/Game.zhl index a75b4607f..60d225f16 100644 --- a/libzhl/functions/Game.zhl +++ b/libzhl/functions/Game.zhl @@ -99,7 +99,7 @@ __thiscall void Game::End(int EndingID); "e8????????c745fcffffffffa3(????????)e8": reference Game *g_Game; -struct Game depends (Level, RoomDescriptor, RoomConfigHolder, PlayerManager, Console, ItemOverlay, Ambush, ProceduralItemManager, RoomTransition, GameState, Seeds, DebugRenderer, ScoreSheet, ColorModState, GameOver, ItemPool, Leaderboard) { {{ +struct Game depends (Level, RoomDescriptor, RoomConfigHolder, PlayerManager, Console, ItemOverlay, Ambush, ProceduralItemManager, RoomTransition, GameState, Seeds, DebugRenderer, ScoreSheet, ColorModState, GameOver, ItemPool, Leaderboard, Vector) { {{ Game() { this->constructor(); @@ -189,7 +189,7 @@ struct Game depends (Level, RoomDescriptor, RoomConfigHolder, PlayerManager, Con bool LIBZHL_API IsErased(int type, int variant, int subtype); }} - //Level _level : 0x0; + //Level _level : 0x0; // we've gotta fix this, it sucks uint32_t _stage : 0x0; // 0x0 uint32_t _stageType : 0x4; // 0x4 bool _bossChallenge : 0x8; //0x8 @@ -212,6 +212,7 @@ struct Game depends (Level, RoomDescriptor, RoomConfigHolder, PlayerManager, Con unsigned int _stateFlags : 0x1822c; // 0x1822C uint32_t _greedModeTreasureRoomIdx : 0x18200; // 0x18200 RoomConfigHolder _roomConfigs : 0x1879c; // 0x1879C + Vector _screenShakeOffset : 0x1a30f0; ItemPool _itemPool : 0x1A5CC; PlayerManager _playerManager : 0x1BA40; // 0x1BA40 Console _console : 0x1bb60; // 0x1BB60 diff --git a/libzhl/functions/Isaac.zhl b/libzhl/functions/Isaac.zhl index bb0eb4234..4598f580a 100644 --- a/libzhl/functions/Isaac.zhl +++ b/libzhl/functions/Isaac.zhl @@ -52,11 +52,9 @@ static __fastcall void Isaac::GetRandomPickupVelocity(Vector * buffer, Vector * "558bec83e4f883ec148b02": static __x86_64_output Vector Isaac::GetCollectibleSpawnPosition(Vector* target); -"558bec83e4c083ec34538b1d": -static __stdcall Vector* Isaac::WorldToScreen(Vector* buffer, Vector* pos); - struct Isaac { {{ LIBZHL_API static bool IsInGame(); + LIBZHL_API static Vector WorldToScreen(Vector * buffer, Vector * pos); }} } : 0; diff --git a/libzhl/functions/LuaEngine.zhl b/libzhl/functions/LuaEngine.zhl index e0a862450..c5da2c76b 100644 --- a/libzhl/functions/LuaEngine.zhl +++ b/libzhl/functions/LuaEngine.zhl @@ -22,9 +22,6 @@ __thiscall bool LuaEngine::EntityTakeDamage(Entity* entity, float damage, "558bec6aff68????????64a1????????5083ec1c535657a1????????33c5508d45??64a3????????8965??8b0d????????8b55??c745??08000000": __thiscall void LuaEngine::EvaluateItems(Entity_Player *player, int cacheFlag); -"558bec83e4c083ec34538b1d": -static __stdcall void LuaEngine::Isaac_WorldToScreen(Vector *buffer, Vector* pos); - "8b0d(????????)c745dc01000000": reference LuaEngine *g_LuaEngine; diff --git a/libzhl/functions/Room.zhl b/libzhl/functions/Room.zhl index bc122617b..ada62b52c 100644 --- a/libzhl/functions/Room.zhl +++ b/libzhl/functions/Room.zhl @@ -70,7 +70,7 @@ bool Room::IsPersistentRoomEntity(int type, int variant, int subtype); "558bec83ec0ca1????????53894d": __thiscall bool Room::TrySpawnSpecialQuestDoor(); -struct Room depends (EntityList, RoomDescriptor, TemporaryEffects, RailManager) { +struct Room depends (EntityList, RoomDescriptor, TemporaryEffects, RailManager, Vector) { {{ inline Camera* GetCamera() { return *(Camera**)((char*)this + 0x11F8); } inline bool GetRedHeartDamage() { return *(bool*)((char*)this + 0x120C); } @@ -106,6 +106,7 @@ struct Room depends (EntityList, RoomDescriptor, TemporaryEffects, RailManager) uint32_t _doorGridPositions[8] : 0x744; // 0x744 int _roomClearDelay : 0x11ec; Camera *_Camera : 0x11f8; //0x11F8 + Vector _renderScrollOffset : 0x1204; bool _redHeartDamage : 0x120c; //0x120C EntityList _entityList : 0x1218; //0x1218 int _greedWaveTimer : 0x7130; diff --git a/repentogon/LuaInterfaces/LuaCord.cpp b/repentogon/LuaInterfaces/LuaCord.cpp index c282f4ad4..cbe30f05c 100644 --- a/repentogon/LuaInterfaces/LuaCord.cpp +++ b/repentogon/LuaInterfaces/LuaCord.cpp @@ -11,7 +11,7 @@ LUA_FUNCTION(Lua_CreateCord) { float stretchHeight = (float)luaL_optnumber(L, 4, 1.0); float stretchWidth = (float)luaL_optnumber(L, 5, 1.0); Rope* toLua = lua::place(L, lua::metatables::CordMT, parent, pos, numPoints, stretchHeight, stretchWidth); - luaL_setmetatable(L, lua::metatables::BeamMT); + luaL_setmetatable(L, lua::metatables::CordMT); return 1; } @@ -31,6 +31,14 @@ LUA_FUNCTION(Lua_CordRender) { return 0; } +LUA_FUNCTION(Lua_CordGetPoints) { + Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); + PointDeque** luaDeque = (PointDeque**)lua_newuserdata(L, sizeof(PointDeque*)); + *luaDeque = &rope->_points; + luaL_setmetatable(L, lua::metatables::PointDequeMT); + return 1; +} + LUA_FUNCTION(Lua_Cord__gc) { Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); rope->~Rope(); diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp index d9e81a62a..cf932f369 100644 --- a/repentogon/Reimplementations/Rope.hpp +++ b/repentogon/Reimplementations/Rope.hpp @@ -16,7 +16,7 @@ #include float TIMESTEP = 0.01f; // Δt in our equations -unsigned int JAKOBSEN_ITERATIONS = 50; // number of times we will enforce the distance constraint +unsigned int JAKOBSEN_ITERATIONS = 10; // number of times we will enforce the distance constraint class Rope { public: @@ -43,9 +43,9 @@ class Rope { float spritesheetCoord = ropeLength * w * spriteStretchHeight; Point p(pos, spritesheetCoord, spriteStretchWidth, i == 0); - printf("created point at pos %f, %f with coord %f\n", p._pos.x, p._pos.y, p._spritesheetCoordinate); + printf("created point at pos %f, %f with coord %f and fixed %d\n", p._pos.x, p._pos.y, p._spritesheetCoordinate, p._fixed); - _points.push_back(p); + _points.deque.push_back(p); } } @@ -55,8 +55,7 @@ class Rope { } void Render(ANM2* anm2, unsigned int layerID, bool useOverlay, bool unk) { - __debugbreak(); - if (_points.size() < 2) + if (_points.deque.size() < 2) return; g_BeamRenderer->Begin(anm2, layerID, useOverlay, unk); @@ -64,7 +63,7 @@ class Rope { #pragma warning(suppress:4533) ColorMod color; Vector buffer; - for (auto it = _points.begin(); it != _points.end(); ++it) { + for (auto it = _points.deque.begin(); it != _points.deque.end(); ++it) { Isaac::WorldToScreen(&buffer, &it->_pos); g_BeamRenderer->Add(&buffer, &color, it->_width, it->_spritesheetCoordinate); } @@ -73,7 +72,7 @@ class Rope { } // We need to store our Points somewhere - std::deque _points; + PointDeque _points; // Target distance of a single segment float _desiredDistance; @@ -84,58 +83,68 @@ class Rope { private: void verletIntegration() { if (_originEntity != nullptr) { - _points.begin()->_pos = *_originEntity->GetPosition(); - _points.begin()->_lastPos = _points.begin()->_pos; + _points.deque.begin()->_pos = *_originEntity->GetPosition(); + _points.deque.begin()->_lastPos = _points.deque.begin()->_pos; } - for (auto p = _points.begin()+1; p != _points.end(); ++p) { + for (Point& p : _points.deque) { // We do not want to move fixed Points - if (p->_fixed) + if (p._fixed) continue; - Vector copy = p->_pos; + Vector copy = p._pos; // Calculating previous velocity - Vector velocity((p->_pos.x - p->_lastPos.x) / TIMESTEP, (p->_pos.y - p->_lastPos.y) / TIMESTEP); + Vector velocity((p._pos.x - p._lastPos.x) / TIMESTEP, (p._pos.y - p._lastPos.y) / TIMESTEP); // Updating Point's position - p->_pos += velocity * TIMESTEP; + p._pos += velocity * TIMESTEP; - p->_lastPos = copy; + p._lastPos = copy; } } void enforceConstraints() { // We perform the enforcement multiple times for (unsigned int iteration = 0; iteration < JAKOBSEN_ITERATIONS; iteration++) { + printf("iteration %d: ", iteration); // We iterate over each pair of points - for (size_t i = 1; i < _points.size(); i++) { - Point &p1 = _points[i - 1]; - Point &p2 = _points[i]; + for (size_t i = 1; i < _points.deque.size(); i++) { + Point &p1 = _points.deque[i - 1]; + Point &p2 = _points.deque[i]; // Calculating distance between the Points float distance = (float)sqrt(pow(p1._pos.x - p2._pos.x, 2) + pow(p1._pos.y - p2._pos.y, 2)); float distanceError = distance - _desiredDistance; + printf("distance %f, error %f, ", distance, distanceError); + // The direction in which Points should be pulled or pushed Vector difference(p2._pos.x - p1._pos.x, p2._pos.y - p1._pos.y); + printf("difference %f, %f, ", difference.x, difference.y); // We need to make it a unit vector // This will allow us to easily scale the impact we have // on each Point's position. Vector direction(difference.x / (float)sqrt(pow(difference.x, 2) + pow(difference.y, 2)), difference.y / (float)sqrt(pow(difference.x, 2) + pow(difference.y, 2))); + printf("direction %f, %f\n", difference.x, difference.y); // Finally, we can update Points' positions // We need to remember that fixed Points should stay in place if (p1._fixed && !p2._fixed) { p2._pos -= direction * distanceError; + printf("moved p2, now %f, %f\n", p2._pos.x, p2._pos.y); } else if (p2._fixed && !p1._fixed) { p1._pos += direction * distanceError; + printf("moved p1, now %f, %f\n", p1._pos.x, p1._pos.y); // keeping this comparison in case both points are fixed - } else if (!p1._fixed && !p2._fixed) { + } else if (!p1._fixed && !p2._fixed) { p2._pos -= direction * distanceError * 0.5; - p2._pos += direction * distanceError * 0.5; + printf("moved p2 halfway, now %f, %f\n", p2._pos.x, p2._pos.y); + p1._pos += direction * distanceError * 0.5; + printf("moved p1 halfway, now %f, %f\n", p1._pos.x, p1._pos.y); } + __debugbreak(); } } } From edede5f1df355b761c28244d927d0962b75208b6 Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Wed, 10 Jan 2024 18:18:24 -0800 Subject: [PATCH 05/12] timestep and iterations are customizable --- repentogon/LuaInterfaces/LuaCord.cpp | 36 ++++++++++++++++++++++++--- repentogon/Reimplementations/Rope.hpp | 35 ++++++++++++++------------ 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaCord.cpp b/repentogon/LuaInterfaces/LuaCord.cpp index cbe30f05c..25c0ec2b2 100644 --- a/repentogon/LuaInterfaces/LuaCord.cpp +++ b/repentogon/LuaInterfaces/LuaCord.cpp @@ -8,9 +8,11 @@ LUA_FUNCTION(Lua_CreateCord) { Entity* parent = lua::GetUserdata(L, 1, lua::Metatables::ENTITY, "Entity"); Vector* pos = lua::GetUserdata(L, 2, lua::Metatables::VECTOR, "Vector"); int numPoints = (int)luaL_checkinteger(L, 3); - float stretchHeight = (float)luaL_optnumber(L, 4, 1.0); - float stretchWidth = (float)luaL_optnumber(L, 5, 1.0); - Rope* toLua = lua::place(L, lua::metatables::CordMT, parent, pos, numPoints, stretchHeight, stretchWidth); + float timestep = (float)luaL_optnumber(L, 4, 0.01); + int iterations = (int)luaL_optinteger(L, 5, 50); + float stretchHeight = (float)luaL_optnumber(L, 6, 1.0); + float stretchWidth = (float)luaL_optnumber(L, 7, 1.0); + Rope* toLua = lua::place(L, lua::metatables::CordMT, parent, pos, numPoints, timestep, iterations, stretchHeight, stretchWidth); luaL_setmetatable(L, lua::metatables::CordMT); return 1; } @@ -39,6 +41,30 @@ LUA_FUNCTION(Lua_CordGetPoints) { return 1; } +LUA_FUNCTION(Lua_CordGetTimestep) { + Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); + lua_pushnumber(L, rope->_timestep); + return 1; +} + +LUA_FUNCTION(Lua_CordSetTimestep) { + Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); + rope->_timestep = (float)luaL_checknumber(L, 2); + return 0; +} + +LUA_FUNCTION(Lua_CordGetIterations) { + Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); + lua_pushinteger(L, rope->_iterations); + return 1; +} + +LUA_FUNCTION(Lua_CordSetIterations) { + Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); + rope->_iterations = (int)luaL_checkinteger(L, 2); + return 0; +} + LUA_FUNCTION(Lua_Cord__gc) { Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); rope->~Rope(); @@ -49,6 +75,10 @@ static void RegisterCord(lua_State* L) { luaL_Reg functions[] = { { "Render", Lua_CordRender}, { "Update", Lua_CordUpdate}, + { "GetTimestep", Lua_CordGetTimestep}, + { "SetTimestep", Lua_CordSetTimestep}, + { "GetIterations", Lua_CordGetIterations}, + { "SetIterations", Lua_CordSetIterations}, { NULL, NULL } }; lua::RegisterNewClass(L, lua::metatables::CordMT, lua::metatables::CordMT, functions, Lua_Cord__gc); diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp index cf932f369..84d92a573 100644 --- a/repentogon/Reimplementations/Rope.hpp +++ b/repentogon/Reimplementations/Rope.hpp @@ -15,15 +15,15 @@ #include #include -float TIMESTEP = 0.01f; // Δt in our equations -unsigned int JAKOBSEN_ITERATIONS = 10; // number of times we will enforce the distance constraint - class Rope { public: - Rope(Entity* origin, Vector* end, unsigned int nPoints, float spriteStretchHeight, float spriteStretchWidth) { + Rope(Entity* origin, Vector* end, unsigned int nPoints, float timestep, unsigned int iterations, float spriteStretchHeight, float spriteStretchWidth) { printf("constructing rope: entity %p, start %f %f, end %f %f, nPoints %d, spriteStretchHeight %f, float spriteStretchWidth %f\n", origin, origin->GetPosition()->x, origin->GetPosition()->y, end->x, end->y, nPoints, spriteStretchHeight, spriteStretchWidth); _originEntity = origin; _target = *end; + _timestep = timestep; + _iterations = iterations; + Vector* start = origin->GetPosition(); float ropeLength = (float)sqrt(pow(start->x - _target.x, 2) + pow(start->y - _target.y, 2)); @@ -79,6 +79,9 @@ class Rope { Entity * _originEntity; Vector _target; + + float _timestep; + unsigned int _iterations; private: void verletIntegration() { @@ -95,10 +98,10 @@ class Rope { Vector copy = p._pos; // Calculating previous velocity - Vector velocity((p._pos.x - p._lastPos.x) / TIMESTEP, (p._pos.y - p._lastPos.y) / TIMESTEP); + Vector velocity((p._pos.x - p._lastPos.x) / _timestep, (p._pos.y - p._lastPos.y) / _timestep); // Updating Point's position - p._pos += velocity * TIMESTEP; + p._pos += velocity * _timestep; p._lastPos = copy; } @@ -106,8 +109,8 @@ class Rope { void enforceConstraints() { // We perform the enforcement multiple times - for (unsigned int iteration = 0; iteration < JAKOBSEN_ITERATIONS; iteration++) { - printf("iteration %d: ", iteration); + for (unsigned int iteration = 0; iteration < _iterations; iteration++) { + //printf("iteration %d: ", iteration); // We iterate over each pair of points for (size_t i = 1; i < _points.deque.size(); i++) { Point &p1 = _points.deque[i - 1]; @@ -117,34 +120,34 @@ class Rope { float distance = (float)sqrt(pow(p1._pos.x - p2._pos.x, 2) + pow(p1._pos.y - p2._pos.y, 2)); float distanceError = distance - _desiredDistance; - printf("distance %f, error %f, ", distance, distanceError); + //printf("distance %f, error %f, ", distance, distanceError); // The direction in which Points should be pulled or pushed Vector difference(p2._pos.x - p1._pos.x, p2._pos.y - p1._pos.y); - printf("difference %f, %f, ", difference.x, difference.y); + //printf("difference %f, %f, ", difference.x, difference.y); // We need to make it a unit vector // This will allow us to easily scale the impact we have // on each Point's position. Vector direction(difference.x / (float)sqrt(pow(difference.x, 2) + pow(difference.y, 2)), difference.y / (float)sqrt(pow(difference.x, 2) + pow(difference.y, 2))); - printf("direction %f, %f\n", difference.x, difference.y); + //printf("direction %f, %f\n", difference.x, difference.y); // Finally, we can update Points' positions // We need to remember that fixed Points should stay in place if (p1._fixed && !p2._fixed) { p2._pos -= direction * distanceError; - printf("moved p2, now %f, %f\n", p2._pos.x, p2._pos.y); + //printf("moved p2, now %f, %f\n", p2._pos.x, p2._pos.y); } else if (p2._fixed && !p1._fixed) { p1._pos += direction * distanceError; - printf("moved p1, now %f, %f\n", p1._pos.x, p1._pos.y); + //printf("moved p1, now %f, %f\n", p1._pos.x, p1._pos.y); // keeping this comparison in case both points are fixed } else if (!p1._fixed && !p2._fixed) { p2._pos -= direction * distanceError * 0.5; - printf("moved p2 halfway, now %f, %f\n", p2._pos.x, p2._pos.y); + //printf("moved p2 halfway, now %f, %f\n", p2._pos.x, p2._pos.y); p1._pos += direction * distanceError * 0.5; - printf("moved p1 halfway, now %f, %f\n", p1._pos.x, p1._pos.y); + //printf("moved p1 halfway, now %f, %f\n", p1._pos.x, p1._pos.y); } - __debugbreak(); + //__debugbreak(); } } } From c87fa4428277357e26f14c5f1cf81764d9ffeaf2 Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Wed, 10 Jan 2024 18:55:33 -0800 Subject: [PATCH 06/12] Fix WorldToScreen --- libzhl/functions/Isaac.zhl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libzhl/functions/Isaac.zhl b/libzhl/functions/Isaac.zhl index 4598f580a..8cfcba709 100644 --- a/libzhl/functions/Isaac.zhl +++ b/libzhl/functions/Isaac.zhl @@ -55,6 +55,6 @@ static __x86_64_output Vector Isaac::GetCollectibleSpawnPosition(Vector* target) struct Isaac { {{ LIBZHL_API static bool IsInGame(); - LIBZHL_API static Vector WorldToScreen(Vector * buffer, Vector * pos); + LIBZHL_API static Vector * WorldToScreen(Vector * buffer, Vector * pos); }} } : 0; From 1a1631eff995560d9a78e96fa88b36d749c159a4 Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Thu, 11 Jan 2024 18:41:14 -0800 Subject: [PATCH 07/12] progress --- libzhl/functions/Point.zhl | 11 ++-- repentogon/LuaInterfaces/LuaCord.cpp | 30 ++++++--- repentogon/LuaInterfaces/LuaPoint.cpp | 56 ++++++++++++++++ repentogon/Reimplementations/Rope.hpp | 93 +++++++++++++++++++-------- 4 files changed, 147 insertions(+), 43 deletions(-) diff --git a/libzhl/functions/Point.zhl b/libzhl/functions/Point.zhl index 4dacfa86f..15199c8fc 100644 --- a/libzhl/functions/Point.zhl +++ b/libzhl/functions/Point.zhl @@ -1,12 +1,13 @@ struct Point depends (Vector) { {{ - Point() : _pos(Vector()), _lastPos(_pos), _spritesheetCoordinate(0.0f), _width(1.0f), _fixed(false) {} - Point(Vector const& pos, float spritesheetCoordinate, float width, bool fixed) : _pos(pos), _lastPos(pos), _spritesheetCoordinate(spritesheetCoordinate), _width(width) , _fixed(fixed) {} + Point() : _pos(Vector()), _lastPos(_pos), _target(nullptr), _spritesheetCoordinate(0.0f), _width(1.0f), _fixed(false) {} + Point(Vector pos, Entity* target, float spritesheetCoordinate, float width, bool fixed) : _pos(pos), _lastPos(pos), _target(target), _spritesheetCoordinate(spritesheetCoordinate), _width(width) , _fixed(fixed) {} }} Vector _pos : 0x0, _lastPos : 0x8; - float _width : 0x10, _spritesheetCoordinate : 0x14; - bool _fixed : 0x18; -} : 0x1c; + Entity * _target : 0x10; + float _width : 0x14, _spritesheetCoordinate : 0x18; + bool _fixed : 0x1c; +} : 0x20; struct PointDeque depends (Point) { deque_Point deque : 0x0; diff --git a/repentogon/LuaInterfaces/LuaCord.cpp b/repentogon/LuaInterfaces/LuaCord.cpp index 25c0ec2b2..0f6f85b74 100644 --- a/repentogon/LuaInterfaces/LuaCord.cpp +++ b/repentogon/LuaInterfaces/LuaCord.cpp @@ -5,18 +5,23 @@ #include "../Reimplementations/Rope.hpp" LUA_FUNCTION(Lua_CreateCord) { - Entity* parent = lua::GetUserdata(L, 1, lua::Metatables::ENTITY, "Entity"); - Vector* pos = lua::GetUserdata(L, 2, lua::Metatables::VECTOR, "Vector"); - int numPoints = (int)luaL_checkinteger(L, 3); - float timestep = (float)luaL_optnumber(L, 4, 0.01); - int iterations = (int)luaL_optinteger(L, 5, 50); - float stretchHeight = (float)luaL_optnumber(L, 6, 1.0); - float stretchWidth = (float)luaL_optnumber(L, 7, 1.0); - Rope* toLua = lua::place(L, lua::metatables::CordMT, parent, pos, numPoints, timestep, iterations, stretchHeight, stretchWidth); + printf("lua: creating cord\n"); + int numPoints = (int)luaL_optinteger(L, 1, 2); + float timestep = (float)luaL_optnumber(L, 2, 0.01); + int iterations = (int)luaL_optinteger(L, 3, 50); + float stretchHeight = (float)luaL_optnumber(L, 4, 1.0); + float stretchWidth = (float)luaL_optnumber(L, 5, 1.0); + Rope* toLua = lua::place(L, lua::metatables::CordMT, numPoints, timestep, iterations, stretchHeight, stretchWidth); luaL_setmetatable(L, lua::metatables::CordMT); return 1; } +LUA_FUNCTION(Lua_CordInit) { + Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); + rope->Init(); + return 0; +} + LUA_FUNCTION(Lua_CordUpdate) { Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); rope->Update(); @@ -34,9 +39,10 @@ LUA_FUNCTION(Lua_CordRender) { } LUA_FUNCTION(Lua_CordGetPoints) { + printf("lua: cord getting pointdeque\n"); Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); PointDeque** luaDeque = (PointDeque**)lua_newuserdata(L, sizeof(PointDeque*)); - *luaDeque = &rope->_points; + *luaDeque = rope->GetPointDeque(); luaL_setmetatable(L, lua::metatables::PointDequeMT); return 1; } @@ -65,6 +71,8 @@ LUA_FUNCTION(Lua_CordSetIterations) { return 0; } + + LUA_FUNCTION(Lua_Cord__gc) { Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); rope->~Rope(); @@ -73,12 +81,14 @@ LUA_FUNCTION(Lua_Cord__gc) { static void RegisterCord(lua_State* L) { luaL_Reg functions[] = { - { "Render", Lua_CordRender}, + { "Init", Lua_CordInit}, { "Update", Lua_CordUpdate}, + { "Render", Lua_CordRender}, { "GetTimestep", Lua_CordGetTimestep}, { "SetTimestep", Lua_CordSetTimestep}, { "GetIterations", Lua_CordGetIterations}, { "SetIterations", Lua_CordSetIterations}, + { "GetPoints", Lua_CordGetPoints}, { NULL, NULL } }; lua::RegisterNewClass(L, lua::metatables::CordMT, lua::metatables::CordMT, functions, Lua_Cord__gc); diff --git a/repentogon/LuaInterfaces/LuaPoint.cpp b/repentogon/LuaInterfaces/LuaPoint.cpp index 68797e7dc..2328d5b73 100644 --- a/repentogon/LuaInterfaces/LuaPoint.cpp +++ b/repentogon/LuaInterfaces/LuaPoint.cpp @@ -7,6 +7,11 @@ LUA_FUNCTION(Lua_PointConstructor) { point._pos = *lua::GetUserdata(L, 1, lua::Metatables::VECTOR, "Vector"); point._spritesheetCoordinate = (float)luaL_checknumber(L, 2); point._width = (float)luaL_optnumber(L, 3, 1.0f); + Entity* target = nullptr; + if (lua_type(L, 4) == LUA_TUSERDATA) { + target = lua::GetUserdata(L, 4, lua::Metatables::ENTITY, "Entity"); + } + point._target = target; Point* toLua = lua::place(L, lua::metatables::PointMT); *toLua = point; @@ -67,6 +72,30 @@ LUA_FUNCTION(Lua_PointSetFixed) { return 0; } +LUA_FUNCTION(Lua_PointGetTarget) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + if (!point->_target) { + lua_pushnil(L); + } + else + { + lua::luabridge::UserdataPtr::push(L, point->_target, lua::GetMetatableKey(lua::Metatables::ENTITY)); + } + return 1; +} + +LUA_FUNCTION(Lua_PointSetTarget) { + Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + if (lua_isnil(L, 2)) { + point->_target = nullptr; + } + else + { + point->_target = lua::GetUserdata(L, 2, lua::Metatables::ENTITY, "Entity"); + } + return 0; +} + /*//////////////////// //// Deque time *///////////////////// @@ -101,6 +130,29 @@ LUA_FUNCTION(Lua_PointDequePopFront) { return 0; } +LUA_FUNCTION(Lua_PointDequeGet) { + PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + Point* p = &d->deque.at((int)luaL_checkinteger(L, 2)-1); + if (!p) { + lua_pushnil(L); + } + else + { + Point** toLua = (Point**)lua_newuserdata(L, sizeof(Point*)); + *toLua = p; + luaL_setmetatable(L, lua::metatables::PointMT); + } + + return 1; +} + +LUA_FUNCTION(Lua_PointDeque__len) { + PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + lua_pushinteger(L, d->deque.size()); + + return 1; +} + LUA_FUNCTION(Lua_PointDeque__gc) { PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); d->~PointDeque(); @@ -117,6 +169,8 @@ static void RegisterPoint(lua_State* L) { { "SetWidth", Lua_PointSetWidth}, { "GetPosition", Lua_PointGetPosition}, { "SetPosition", Lua_PointSetPosition}, + { "GetTarget", Lua_PointGetTarget}, + { "SetTarget", Lua_PointSetTarget}, { NULL, NULL } }; @@ -128,6 +182,8 @@ static void RegisterPoint(lua_State* L) { { "PushFront", Lua_PointDequePushFront }, { "PopBack", Lua_PointDequePopBack }, { "PopFront", Lua_PointDequePopFront }, + { "Get", Lua_PointDequeGet }, + { "__len", Lua_PointDeque__len }, { NULL, NULL } }; diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp index 84d92a573..8b041d3c2 100644 --- a/repentogon/Reimplementations/Rope.hpp +++ b/repentogon/Reimplementations/Rope.hpp @@ -17,46 +17,84 @@ class Rope { public: - Rope(Entity* origin, Vector* end, unsigned int nPoints, float timestep, unsigned int iterations, float spriteStretchHeight, float spriteStretchWidth) { - printf("constructing rope: entity %p, start %f %f, end %f %f, nPoints %d, spriteStretchHeight %f, float spriteStretchWidth %f\n", origin, origin->GetPosition()->x, origin->GetPosition()->y, end->x, end->y, nPoints, spriteStretchHeight, spriteStretchWidth); - _originEntity = origin; - _target = *end; + Rope(unsigned int nPoints, float timestep, unsigned int iterations, float spriteStretchHeight, float spriteStretchWidth) { + printf("Rope: constructing"); + _numPoints = nPoints; _timestep = timestep; _iterations = iterations; + _spriteStretch = spriteStretchHeight; + _spriteWidth = spriteStretchWidth; + _desiredDistance = 0.0f; + Vector const zero; + + for (unsigned int i = 0; i < 2; i++) { + printf("Rope: making point #%d\n", i); + Point p(zero, (Entity*)nullptr, 0.0f, spriteStretchWidth, false); + printf("Rope: pushing point #%d\n", i); + _points.deque.push_back(p); + } + + printf("Rope: done constructing\n"); + } + + void Init() { + printf("Rope::Init starting\n"); + Point* startPoint = &_points.deque.at(0); + Point endPoint = _points.deque.at(_points.deque.size()); + Vector* startPos = startPoint->_target != nullptr ? startPoint->_target->GetPosition() : &startPoint->_pos; + Vector* endPos = endPoint._target ? endPoint._target->GetPosition() : &endPoint._pos; - Vector* start = origin->GetPosition(); + float ropeLength = (float)sqrt(pow(startPos->x - endPos->x, 2) + pow(startPos->y - endPos->y, 2)); - float ropeLength = (float)sqrt(pow(start->x - _target.x, 2) + pow(start->y - _target.y, 2)); - // There is one less segment than there are Points - unsigned int numSegments = nPoints - 1; + unsigned int numSegments = _numPoints - 1; _desiredDistance = ropeLength / numSegments; printf("length: %f, segments : %d, avg distance: %f\n", ropeLength, numSegments, _desiredDistance); - for (unsigned int i = 0; i < nPoints; i++) { + _points.deque.erase(_points.deque.end()); + for (unsigned int i = 1; i < _numPoints; i++) { // percent distance from start to end, 0.0->1.0 - float w = (float)i / (nPoints - 1); + float w = (float)i / (_numPoints - 1); - Vector pos(w * _target.x + (1 - w) * start->x, w * _target.y + (1 - w) * start->y); - float spritesheetCoord = ropeLength * w * spriteStretchHeight; + Vector pos(w * endPos->x + (1 - w) * startPos->x, w * endPos->y + (1 - w) * startPos->y); + float spritesheetCoord = ropeLength * w * _spriteStretch; - Point p(pos, spritesheetCoord, spriteStretchWidth, i == 0); - printf("created point at pos %f, %f with coord %f and fixed %d\n", p._pos.x, p._pos.y, p._spritesheetCoordinate, p._fixed); - - _points.deque.push_back(p); + if (i == _numPoints - 1) { + endPoint._pos = pos; + endPoint._spritesheetCoordinate = spritesheetCoord; + _points.deque.push_back(endPoint); + printf("readded end point at pos %f, %f with coord %f and fixed %d\n", endPoint._pos.x, endPoint._pos.y, endPoint._spritesheetCoordinate, endPoint._target != nullptr); + } + else + { + Point p(pos, nullptr, spritesheetCoord, _spriteWidth, false); + _points.deque.push_back(p); + printf("created point at pos %f, %f with coord %f and fixed %d\n", p._pos.x, p._pos.y, p._spritesheetCoordinate, p._fixed); + } } + _initialized = true; } void Update() { + if (!_initialized) { + printf("Cord::Update: not initialzed"); + return; + } verletIntegration(); enforceConstraints(); } void Render(ANM2* anm2, unsigned int layerID, bool useOverlay, bool unk) { - if (_points.deque.size() < 2) + if (_points.deque.size() < 2) { + printf("Cord::Render: < 2 points"); + return; + } + if (!_initialized) { + printf("Cord::Render: not initialzed"); return; + } g_BeamRenderer->Begin(anm2, layerID, useOverlay, unk); @@ -76,21 +114,20 @@ class Rope { // Target distance of a single segment float _desiredDistance; - - Entity * _originEntity; - Vector _target; - - float _timestep; - unsigned int _iterations; + float _timestep = 0.01f; + float _spriteStretch, _spriteWidth = 1; + unsigned int _numPoints = 2; + unsigned int _iterations = 10; + bool _initialized = false; private: void verletIntegration() { - if (_originEntity != nullptr) { - _points.deque.begin()->_pos = *_originEntity->GetPosition(); - _points.deque.begin()->_lastPos = _points.deque.begin()->_pos; - } - for (Point& p : _points.deque) { + if (p._target) { + p._pos = *p._target->GetPosition(); + p._lastPos = p._pos; + continue; + } // We do not want to move fixed Points if (p._fixed) continue; From 33e9e08ade1a354fbc8b78df2570655a37f768ff Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Fri, 12 Jan 2024 00:24:30 -0800 Subject: [PATCH 08/12] pushing for debug help --- repentogon/LuaInterfaces/LuaCord.cpp | 5 ++- repentogon/LuaInterfaces/LuaPoint.cpp | 49 ++++++++++++++++++++++++++- repentogon/Reimplementations/Rope.hpp | 20 +++++++---- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaCord.cpp b/repentogon/LuaInterfaces/LuaCord.cpp index 0f6f85b74..4d83f336f 100644 --- a/repentogon/LuaInterfaces/LuaCord.cpp +++ b/repentogon/LuaInterfaces/LuaCord.cpp @@ -42,7 +42,8 @@ LUA_FUNCTION(Lua_CordGetPoints) { printf("lua: cord getting pointdeque\n"); Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); PointDeque** luaDeque = (PointDeque**)lua_newuserdata(L, sizeof(PointDeque*)); - *luaDeque = rope->GetPointDeque(); + printf("lua: cord setting luaDeque to %p\n", &rope->_points); + *luaDeque = &rope->_points; luaL_setmetatable(L, lua::metatables::PointDequeMT); return 1; } @@ -71,8 +72,6 @@ LUA_FUNCTION(Lua_CordSetIterations) { return 0; } - - LUA_FUNCTION(Lua_Cord__gc) { Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); rope->~Rope(); diff --git a/repentogon/LuaInterfaces/LuaPoint.cpp b/repentogon/LuaInterfaces/LuaPoint.cpp index 2328d5b73..aea84c2c1 100644 --- a/repentogon/LuaInterfaces/LuaPoint.cpp +++ b/repentogon/LuaInterfaces/LuaPoint.cpp @@ -118,6 +118,7 @@ LUA_FUNCTION(Lua_PointDequePushFront) { LUA_FUNCTION(Lua_PointDequePopBack) { PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + printf("PointDeque::PopBack: address %p (or %p)\n", d, &d); d->deque.pop_back(); return 0; @@ -132,12 +133,16 @@ LUA_FUNCTION(Lua_PointDequePopFront) { LUA_FUNCTION(Lua_PointDequeGet) { PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); - Point* p = &d->deque.at((int)luaL_checkinteger(L, 2)-1); + printf("PointDeque::Get: size %d\n", d->deque.size()); + Point* p = &d->deque.at((int)luaL_checkinteger(L, 2)); + printf("PointDeque::Get: p = %p\n", p); if (!p) { + printf("PointDeque::Get: it's nothing!\n"); lua_pushnil(L); } else { + printf("PointDeque::Get: pushing %p\n", p); Point** toLua = (Point**)lua_newuserdata(L, sizeof(Point*)); *toLua = p; luaL_setmetatable(L, lua::metatables::PointMT); @@ -146,6 +151,46 @@ LUA_FUNCTION(Lua_PointDequeGet) { return 1; } +LUA_FUNCTION(Lua_PointDequeGetFront) { + PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + printf("PointDeque::GetFront: deque %p, size %d\n", d, d->deque.size()); + Point* p = &d->deque.front(); + printf("PointDeque::GetFront: p = %p\n", p); + if (!p) { + printf("PointDeque::GetFront: it's nothing!\n"); + lua_pushnil(L); + } + else + { + printf("PointDeque::GetFront: pushing %p\n", p); + Point** toLua = (Point**)lua_newuserdata(L, sizeof(Point*)); + *toLua = p; + luaL_setmetatable(L, lua::metatables::PointMT); + } + + return 1; +} + +LUA_FUNCTION(Lua_PointDequeGetBack) { + PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + printf("PointDeque::GetBack: deque %p, size %d\n", d, d->deque.size()); + Point* p = &d->deque.back(); + printf("PointDeque::GetBack: p = %p\n", p); + if (!p) { + printf("PointDeque::GetBack: it's nothing!\n"); + lua_pushnil(L); + } + else + { + printf("PointDeque::GetBack: pushing %p\n", p); + Point** toLua = (Point**)lua_newuserdata(L, sizeof(Point*)); + *toLua = p; + luaL_setmetatable(L, lua::metatables::PointMT); + } + + return 1; +} + LUA_FUNCTION(Lua_PointDeque__len) { PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); lua_pushinteger(L, d->deque.size()); @@ -183,6 +228,8 @@ static void RegisterPoint(lua_State* L) { { "PopBack", Lua_PointDequePopBack }, { "PopFront", Lua_PointDequePopFront }, { "Get", Lua_PointDequeGet }, + { "GetFront", Lua_PointDequeGetFront }, + { "GetBack", Lua_PointDequeGetBack }, { "__len", Lua_PointDeque__len }, { NULL, NULL } }; diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp index 8b041d3c2..cae28757e 100644 --- a/repentogon/Reimplementations/Rope.hpp +++ b/repentogon/Reimplementations/Rope.hpp @@ -18,7 +18,7 @@ class Rope { public: Rope(unsigned int nPoints, float timestep, unsigned int iterations, float spriteStretchHeight, float spriteStretchWidth) { - printf("Rope: constructing"); + printf("Rope: constructing\n"); _numPoints = nPoints; _timestep = timestep; _iterations = iterations; @@ -33,17 +33,23 @@ class Rope { printf("Rope: pushing point #%d\n", i); _points.deque.push_back(p); } - + printf("Rope: points %p, %p\n", &_points.deque.front(), &_points.deque.back()); printf("Rope: done constructing\n"); } void Init() { - printf("Rope::Init starting\n"); - Point* startPoint = &_points.deque.at(0); - Point endPoint = _points.deque.at(_points.deque.size()); - Vector* startPos = startPoint->_target != nullptr ? startPoint->_target->GetPosition() : &startPoint->_pos; + printf("Rope::Init starting, using deque %p\n", &_points); + if (_points.deque.size() < 2) { + printf("not enough points\n"); + return; + } + Point* startPoint = &_points.deque.front(); + Point endPoint = _points.deque.back(); + Vector* startPos = startPoint->_target ? startPoint->_target->GetPosition() : &startPoint->_pos; Vector* endPos = endPoint._target ? endPoint._target->GetPosition() : &endPoint._pos; + printf("startPos: %f %f, endPos: %f %f\n", startPos->x, startPos->y, endPos->x, endPos->y); + float ropeLength = (float)sqrt(pow(startPos->x - endPos->x, 2) + pow(startPos->y - endPos->y, 2)); // There is one less segment than there are Points @@ -53,7 +59,7 @@ class Rope { printf("length: %f, segments : %d, avg distance: %f\n", ropeLength, numSegments, _desiredDistance); - _points.deque.erase(_points.deque.end()); + _points.deque.pop_back(); for (unsigned int i = 1; i < _numPoints; i++) { // percent distance from start to end, 0.0->1.0 float w = (float)i / (_numPoints - 1); From 540b7e7ac4e0d7f8cbb2022f9f75fa244f8fe542 Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Fri, 12 Jan 2024 01:11:39 -0800 Subject: [PATCH 09/12] mystery of the vanishing points wtf --- repentogon/LuaInterfaces/LuaPoint.cpp | 40 +++++++++++++-------------- repentogon/Reimplementations/Rope.hpp | 15 ++++++++-- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaPoint.cpp b/repentogon/LuaInterfaces/LuaPoint.cpp index aea84c2c1..eb9fcbc88 100644 --- a/repentogon/LuaInterfaces/LuaPoint.cpp +++ b/repentogon/LuaInterfaces/LuaPoint.cpp @@ -21,51 +21,51 @@ LUA_FUNCTION(Lua_PointConstructor) { } LUA_FUNCTION(Lua_PointGetSpritesheetCoordinate) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Point* point = *lua::GetUserdata(L, 1, lua::metatables::PointMT); lua_pushnumber(L, point->_spritesheetCoordinate); return 1; } LUA_FUNCTION(Lua_PointSetSpritesheetCoordinate) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Point* point = *lua::GetUserdata(L, 1, lua::metatables::PointMT); point->_spritesheetCoordinate = (float)luaL_checknumber(L, 2); return 0; } LUA_FUNCTION(Lua_PointGetWidth) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Point* point = *lua::GetUserdata(L, 1, lua::metatables::PointMT); lua_pushnumber(L, point->_width); return 1; } LUA_FUNCTION(Lua_PointSetWidth) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Point* point = *lua::GetUserdata(L, 1, lua::metatables::PointMT); point->_width = (float)luaL_checknumber(L, 2); return 0; } LUA_FUNCTION(Lua_PointGetPosition) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Point* point = *lua::GetUserdata(L, 1, lua::metatables::PointMT); Vector* toLua = lua::luabridge::UserdataValue::place(L, lua::GetMetatableKey(lua::Metatables::VECTOR)); *toLua = point->_pos; return 1; } LUA_FUNCTION(Lua_PointSetPosition) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Point* point = *lua::GetUserdata(L, 1, lua::metatables::PointMT); point->_lastPos = point->_pos; point->_pos = *lua::GetUserdata(L, 2, lua::Metatables::VECTOR, "Vector"); return 0; } LUA_FUNCTION(Lua_PointGetFixed) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Point* point = *lua::GetUserdata(L, 1, lua::metatables::PointMT); lua_pushboolean(L, point->_fixed); return 1; } LUA_FUNCTION(Lua_PointSetFixed) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Point* point = *lua::GetUserdata(L, 1, lua::metatables::PointMT); point->_fixed = lua::luaL_checkboolean(L, 2); if (point->_fixed) point->_lastPos = point->_pos; @@ -73,7 +73,7 @@ LUA_FUNCTION(Lua_PointSetFixed) { } LUA_FUNCTION(Lua_PointGetTarget) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Point* point = *lua::GetUserdata(L, 1, lua::metatables::PointMT); if (!point->_target) { lua_pushnil(L); } @@ -85,7 +85,7 @@ LUA_FUNCTION(Lua_PointGetTarget) { } LUA_FUNCTION(Lua_PointSetTarget) { - Point* point = lua::GetUserdata(L, 1, lua::metatables::PointMT); + Point* point = *lua::GetUserdata(L, 1, lua::metatables::PointMT); if (lua_isnil(L, 2)) { point->_target = nullptr; } @@ -101,7 +101,7 @@ LUA_FUNCTION(Lua_PointSetTarget) { *///////////////////// LUA_FUNCTION(Lua_PointDequePushBack) { - PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + PointDeque* d = *lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); Point* point = lua::GetUserdata(L, 2, lua::metatables::PointMT); d->deque.push_back(*point); @@ -109,7 +109,7 @@ LUA_FUNCTION(Lua_PointDequePushBack) { } LUA_FUNCTION(Lua_PointDequePushFront) { - PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + PointDeque* d = *lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); Point* point = lua::GetUserdata(L, 2, lua::metatables::PointMT); d->deque.push_front(*point); @@ -117,22 +117,22 @@ LUA_FUNCTION(Lua_PointDequePushFront) { } LUA_FUNCTION(Lua_PointDequePopBack) { - PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); - printf("PointDeque::PopBack: address %p (or %p)\n", d, &d); + PointDeque* d = *lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + printf("PointDeque::PopBack: address %p, size %d\n", d, d->deque.size()); d->deque.pop_back(); return 0; } LUA_FUNCTION(Lua_PointDequePopFront) { - PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + PointDeque* d = *lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); d->deque.pop_front(); return 0; } LUA_FUNCTION(Lua_PointDequeGet) { - PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + PointDeque* d = *lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); printf("PointDeque::Get: size %d\n", d->deque.size()); Point* p = &d->deque.at((int)luaL_checkinteger(L, 2)); printf("PointDeque::Get: p = %p\n", p); @@ -152,7 +152,7 @@ LUA_FUNCTION(Lua_PointDequeGet) { } LUA_FUNCTION(Lua_PointDequeGetFront) { - PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + PointDeque* d = *lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); printf("PointDeque::GetFront: deque %p, size %d\n", d, d->deque.size()); Point* p = &d->deque.front(); printf("PointDeque::GetFront: p = %p\n", p); @@ -172,7 +172,7 @@ LUA_FUNCTION(Lua_PointDequeGetFront) { } LUA_FUNCTION(Lua_PointDequeGetBack) { - PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + PointDeque* d = *lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); printf("PointDeque::GetBack: deque %p, size %d\n", d, d->deque.size()); Point* p = &d->deque.back(); printf("PointDeque::GetBack: p = %p\n", p); @@ -192,14 +192,14 @@ LUA_FUNCTION(Lua_PointDequeGetBack) { } LUA_FUNCTION(Lua_PointDeque__len) { - PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + PointDeque* d = *lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); lua_pushinteger(L, d->deque.size()); return 1; } LUA_FUNCTION(Lua_PointDeque__gc) { - PointDeque* d = lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); + PointDeque* d = *lua::GetUserdata(L, 1, lua::metatables::PointDequeMT); d->~PointDeque(); return 0; } diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp index cae28757e..213b277be 100644 --- a/repentogon/Reimplementations/Rope.hpp +++ b/repentogon/Reimplementations/Rope.hpp @@ -81,24 +81,28 @@ class Rope { } } _initialized = true; + printf("Rope::Init ending, size %d\n", _points.deque.size()); } void Update() { + //printf("Rope::Update starting, using deque %p\n", &_points); if (!_initialized) { - printf("Cord::Update: not initialzed"); + printf("Cord::Update: not initialzed\n"); return; } verletIntegration(); enforceConstraints(); + //printf("Rope::Update finished\n"); } void Render(ANM2* anm2, unsigned int layerID, bool useOverlay, bool unk) { + //printf("Rope::Render starting, using deque %p\n", &_points); if (_points.deque.size() < 2) { - printf("Cord::Render: < 2 points"); + printf("Rope::Render: < 2 points, size is %d\n", _points.deque.size()); return; } if (!_initialized) { - printf("Cord::Render: not initialzed"); + printf("Rope::Render: not initialzed\n"); return; } @@ -128,6 +132,8 @@ class Rope { private: void verletIntegration() { + printf("verletIntegration: deque size %d\n", _points.deque.size()); + int i = 0; for (Point& p : _points.deque) { if (p._target) { p._pos = *p._target->GetPosition(); @@ -147,10 +153,13 @@ class Rope { p._pos += velocity * _timestep; p._lastPos = copy; + i++; } + printf("verletIntegration: ran %d times, deque size %d\n", i, _points.deque.size()); } void enforceConstraints() { + printf("enforceConstraints: iterations %d, deque size %d\n", _iterations, _points.deque.size()); // We perform the enforcement multiple times for (unsigned int iteration = 0; iteration < _iterations; iteration++) { //printf("iteration %d: ", iteration); From 102783ff8313edd5bc4919bd843f98ddff72f151 Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Fri, 12 Jan 2024 02:37:39 -0800 Subject: [PATCH 10/12] updated debug printouts --- repentogon/LuaInterfaces/LuaCord.cpp | 1 + repentogon/Reimplementations/Rope.hpp | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/repentogon/LuaInterfaces/LuaCord.cpp b/repentogon/LuaInterfaces/LuaCord.cpp index 4d83f336f..1cf3cedd9 100644 --- a/repentogon/LuaInterfaces/LuaCord.cpp +++ b/repentogon/LuaInterfaces/LuaCord.cpp @@ -73,6 +73,7 @@ LUA_FUNCTION(Lua_CordSetIterations) { } LUA_FUNCTION(Lua_Cord__gc) { + printf("cord gc\n"); Rope* rope = lua::GetUserdata(L, 1, lua::metatables::CordMT); rope->~Rope(); return 0; diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp index 213b277be..8fbf9c5c4 100644 --- a/repentogon/Reimplementations/Rope.hpp +++ b/repentogon/Reimplementations/Rope.hpp @@ -18,7 +18,7 @@ class Rope { public: Rope(unsigned int nPoints, float timestep, unsigned int iterations, float spriteStretchHeight, float spriteStretchWidth) { - printf("Rope: constructing\n"); + printf("Rope: constructing, this %p\n", this); _numPoints = nPoints; _timestep = timestep; _iterations = iterations; @@ -38,7 +38,7 @@ class Rope { } void Init() { - printf("Rope::Init starting, using deque %p\n", &_points); + printf("Rope::Init starting, this %p, deque %p\n", this, &_points); if (_points.deque.size() < 2) { printf("not enough points\n"); return; @@ -59,6 +59,7 @@ class Rope { printf("length: %f, segments : %d, avg distance: %f\n", ropeLength, numSegments, _desiredDistance); + printf("point #0: %p\n", &_points.deque.front()); _points.deque.pop_back(); for (unsigned int i = 1; i < _numPoints; i++) { // percent distance from start to end, 0.0->1.0 @@ -71,23 +72,24 @@ class Rope { endPoint._pos = pos; endPoint._spritesheetCoordinate = spritesheetCoord; _points.deque.push_back(endPoint); - printf("readded end point at pos %f, %f with coord %f and fixed %d\n", endPoint._pos.x, endPoint._pos.y, endPoint._spritesheetCoordinate, endPoint._target != nullptr); + printf("end point #%d, addr %p, deque addr %p, pos %f, %f with coord %f and fixed %d\n", i, &endPoint, &_points.deque.back(), endPoint._pos.x, endPoint._pos.y, endPoint._spritesheetCoordinate, endPoint._target != nullptr); } else { Point p(pos, nullptr, spritesheetCoord, _spriteWidth, false); _points.deque.push_back(p); - printf("created point at pos %f, %f with coord %f and fixed %d\n", p._pos.x, p._pos.y, p._spritesheetCoordinate, p._fixed); + printf("point #%d, addr %p, deque addr %p, pos %f, %f with coord %f and fixed %d\n", i, &p, &_points.deque.back(), p._pos.x, p._pos.y, p._spritesheetCoordinate, p._fixed); } } _initialized = true; printf("Rope::Init ending, size %d\n", _points.deque.size()); + __debugbreak(); } void Update() { - //printf("Rope::Update starting, using deque %p\n", &_points); + printf("Rope::Update starting, this %p, deque %p, size %d\n", this, &_points, _points.deque.size()); if (!_initialized) { - printf("Cord::Update: not initialzed\n"); + printf("Rope::Update: not initialzed\n"); return; } verletIntegration(); @@ -98,11 +100,11 @@ class Rope { void Render(ANM2* anm2, unsigned int layerID, bool useOverlay, bool unk) { //printf("Rope::Render starting, using deque %p\n", &_points); if (_points.deque.size() < 2) { - printf("Rope::Render: < 2 points, size is %d\n", _points.deque.size()); + //printf("Rope::Render: < 2 points, size is %d\n", _points.deque.size()); return; } if (!_initialized) { - printf("Rope::Render: not initialzed\n"); + //printf("Rope::Render: not initialzed\n"); return; } @@ -132,7 +134,7 @@ class Rope { private: void verletIntegration() { - printf("verletIntegration: deque size %d\n", _points.deque.size()); + //printf("verletIntegration: deque %p, size %d\n", &_points, _points.deque.size()); int i = 0; for (Point& p : _points.deque) { if (p._target) { @@ -155,11 +157,11 @@ class Rope { p._lastPos = copy; i++; } - printf("verletIntegration: ran %d times, deque size %d\n", i, _points.deque.size()); + //printf("verletIntegration: ran %d times, deque size %d\n", i, _points.deque.size()); } void enforceConstraints() { - printf("enforceConstraints: iterations %d, deque size %d\n", _iterations, _points.deque.size()); + //printf("enforceConstraints: deque %p, iterations %d, size %d\n", &_points, _iterations, _points.deque.size()); // We perform the enforcement multiple times for (unsigned int iteration = 0; iteration < _iterations; iteration++) { //printf("iteration %d: ", iteration); From ae404affdb96c2b226f2e15fe29eb420c207f356 Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Fri, 12 Jan 2024 03:49:50 -0800 Subject: [PATCH 11/12] current progress, +bad hack --- repentogon/Reimplementations/Rope.hpp | 68 ++++++++++++++++----------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp index 8fbf9c5c4..cba54bed4 100644 --- a/repentogon/Reimplementations/Rope.hpp +++ b/repentogon/Reimplementations/Rope.hpp @@ -50,14 +50,14 @@ class Rope { printf("startPos: %f %f, endPos: %f %f\n", startPos->x, startPos->y, endPos->x, endPos->y); - float ropeLength = (float)sqrt(pow(startPos->x - endPos->x, 2) + pow(startPos->y - endPos->y, 2)); + float ropeLength = distanceFunc(*startPos, *endPos); // There is one less segment than there are Points - unsigned int numSegments = _numPoints - 1; + _numSegments = _numPoints - 1; - _desiredDistance = ropeLength / numSegments; + _desiredDistance = ropeLength / _numSegments; - printf("length: %f, segments : %d, avg distance: %f\n", ropeLength, numSegments, _desiredDistance); + printf("length: %f, segments : %d, avg distance: %f\n", ropeLength, _numSegments, _desiredDistance); printf("point #0: %p\n", &_points.deque.front()); _points.deque.pop_back(); @@ -72,7 +72,7 @@ class Rope { endPoint._pos = pos; endPoint._spritesheetCoordinate = spritesheetCoord; _points.deque.push_back(endPoint); - printf("end point #%d, addr %p, deque addr %p, pos %f, %f with coord %f and fixed %d\n", i, &endPoint, &_points.deque.back(), endPoint._pos.x, endPoint._pos.y, endPoint._spritesheetCoordinate, endPoint._target != nullptr); + //printf("end point #%d, addr %p, deque addr %p, pos %f, %f with coord %f and fixed %d\n", i, &endPoint, &_points.deque.back(), endPoint._pos.x, endPoint._pos.y, endPoint._spritesheetCoordinate, endPoint._target != nullptr); } else { @@ -83,13 +83,17 @@ class Rope { } _initialized = true; printf("Rope::Init ending, size %d\n", _points.deque.size()); - __debugbreak(); + _backup = _points; // miserable + //__debugbreak(); } void Update() { - printf("Rope::Update starting, this %p, deque %p, size %d\n", this, &_points, _points.deque.size()); + _points = _backup; + //printf("Rope::Update starting, this %p, deque %p, size %d\n", this, &_points, _points.deque.size()); + //printf("%f %f, %f %f\n", _points.deque.front()._pos.x, _points.deque.front()._pos.y, _points.deque.back()._pos.x, _points.deque.back()._pos.y); + _desiredDistance = _numSegments / distanceFunc(_points.deque.front()._pos, _points.deque.back()._pos); if (!_initialized) { - printf("Rope::Update: not initialzed\n"); + //printf("Rope::Update: not initialzed\n"); return; } verletIntegration(); @@ -113,16 +117,16 @@ class Rope { #pragma warning(suppress:4533) ColorMod color; Vector buffer; - for (auto it = _points.deque.begin(); it != _points.deque.end(); ++it) { - Isaac::WorldToScreen(&buffer, &it->_pos); - g_BeamRenderer->Add(&buffer, &color, it->_width, it->_spritesheetCoordinate); + for (Point& p : _points.deque) { + Isaac::WorldToScreen(&buffer, &p._pos); + g_BeamRenderer->Add(&buffer, &color, p._width, p._spritesheetCoordinate); } g_BeamRenderer->End(); } // We need to store our Points somewhere - PointDeque _points; + PointDeque _points, _backup; // Target distance of a single segment float _desiredDistance; @@ -130,16 +134,26 @@ class Rope { float _spriteStretch, _spriteWidth = 1; unsigned int _numPoints = 2; unsigned int _iterations = 10; + unsigned int _numSegments = 1; bool _initialized = false; private: + inline float distanceFunc(Vector a, Vector b) { + return (float)sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2)); + } + + inline bool isFixed(Point p) { + return (p._fixed || p._target != nullptr); + } + void verletIntegration() { //printf("verletIntegration: deque %p, size %d\n", &_points, _points.deque.size()); - int i = 0; + //int i = 0; for (Point& p : _points.deque) { if (p._target) { p._pos = *p._target->GetPosition(); p._lastPos = p._pos; + printf("updated position to %f, %f\n", p._pos.x, p._pos.y); continue; } // We do not want to move fixed Points @@ -155,7 +169,7 @@ class Rope { p._pos += velocity * _timestep; p._lastPos = copy; - i++; + //i++; } //printf("verletIntegration: ran %d times, deque size %d\n", i, _points.deque.size()); } @@ -164,42 +178,42 @@ class Rope { //printf("enforceConstraints: deque %p, iterations %d, size %d\n", &_points, _iterations, _points.deque.size()); // We perform the enforcement multiple times for (unsigned int iteration = 0; iteration < _iterations; iteration++) { - //printf("iteration %d: ", iteration); + printf("iteration %d: ", iteration); // We iterate over each pair of points for (size_t i = 1; i < _points.deque.size(); i++) { Point &p1 = _points.deque[i - 1]; Point &p2 = _points.deque[i]; // Calculating distance between the Points - float distance = (float)sqrt(pow(p1._pos.x - p2._pos.x, 2) + pow(p1._pos.y - p2._pos.y, 2)); + float distance = distanceFunc(p1._pos, p2._pos); float distanceError = distance - _desiredDistance; - //printf("distance %f, error %f, ", distance, distanceError); + printf("distance %f, error %f, ", distance, distanceError); - // The direction in which Points should be pulled or pushed + // The direction in which Points should be pulled or pushed Vector difference(p2._pos.x - p1._pos.x, p2._pos.y - p1._pos.y); - //printf("difference %f, %f, ", difference.x, difference.y); + printf("difference %f, %f, ", difference.x, difference.y); // We need to make it a unit vector // This will allow us to easily scale the impact we have // on each Point's position. Vector direction(difference.x / (float)sqrt(pow(difference.x, 2) + pow(difference.y, 2)), difference.y / (float)sqrt(pow(difference.x, 2) + pow(difference.y, 2))); - //printf("direction %f, %f\n", difference.x, difference.y); + printf("direction %f, %f\n", difference.x, difference.y); // Finally, we can update Points' positions // We need to remember that fixed Points should stay in place - if (p1._fixed && !p2._fixed) { + if (isFixed(p1) && !isFixed(p2)) { p2._pos -= direction * distanceError; - //printf("moved p2, now %f, %f\n", p2._pos.x, p2._pos.y); - } else if (p2._fixed && !p1._fixed) { + printf("moved p2, now %f, %f\n", p2._pos.x, p2._pos.y); + } else if (isFixed(p2) && !isFixed(p1)) { p1._pos += direction * distanceError; - //printf("moved p1, now %f, %f\n", p1._pos.x, p1._pos.y); + printf("moved p1, now %f, %f\n", p1._pos.x, p1._pos.y); // keeping this comparison in case both points are fixed - } else if (!p1._fixed && !p2._fixed) { + } else if (!isFixed(p1) && !isFixed(p2)) { p2._pos -= direction * distanceError * 0.5; - //printf("moved p2 halfway, now %f, %f\n", p2._pos.x, p2._pos.y); + printf("moved p2 halfway, now %f, %f\n", p2._pos.x, p2._pos.y); p1._pos += direction * distanceError * 0.5; - //printf("moved p1 halfway, now %f, %f\n", p1._pos.x, p1._pos.y); + printf("moved p1 halfway, now %f, %f\n", p1._pos.x, p1._pos.y); } //__debugbreak(); } From b5da82ac755a9f98853b2cb69c96fa8cdb7a3923 Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:39:16 -0800 Subject: [PATCH 12/12] ugh --- repentogon/Reimplementations/Rope.hpp | 50 +++++++++++++++------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/repentogon/Reimplementations/Rope.hpp b/repentogon/Reimplementations/Rope.hpp index cba54bed4..cf49ea9cd 100644 --- a/repentogon/Reimplementations/Rope.hpp +++ b/repentogon/Reimplementations/Rope.hpp @@ -50,14 +50,14 @@ class Rope { printf("startPos: %f %f, endPos: %f %f\n", startPos->x, startPos->y, endPos->x, endPos->y); - float ropeLength = distanceFunc(*startPos, *endPos); + _ropeLength = distanceFunc(*startPos, *endPos); // There is one less segment than there are Points _numSegments = _numPoints - 1; - _desiredDistance = ropeLength / _numSegments; + _desiredDistance = _ropeLength / _numSegments; - printf("length: %f, segments : %d, avg distance: %f\n", ropeLength, _numSegments, _desiredDistance); + printf("length: %f, segments : %d, avg distance: %f\n", _ropeLength, _numSegments, _desiredDistance); printf("point #0: %p\n", &_points.deque.front()); _points.deque.pop_back(); @@ -66,7 +66,7 @@ class Rope { float w = (float)i / (_numPoints - 1); Vector pos(w * endPos->x + (1 - w) * startPos->x, w * endPos->y + (1 - w) * startPos->y); - float spritesheetCoord = ropeLength * w * _spriteStretch; + float spritesheetCoord = _ropeLength * w * _spriteStretch; if (i == _numPoints - 1) { endPoint._pos = pos; @@ -91,7 +91,7 @@ class Rope { _points = _backup; //printf("Rope::Update starting, this %p, deque %p, size %d\n", this, &_points, _points.deque.size()); //printf("%f %f, %f %f\n", _points.deque.front()._pos.x, _points.deque.front()._pos.y, _points.deque.back()._pos.x, _points.deque.back()._pos.y); - _desiredDistance = _numSegments / distanceFunc(_points.deque.front()._pos, _points.deque.back()._pos); + //_desiredDistance = _numSegments / distanceFunc(_points.deque.front()._pos, _points.deque.back()._pos); if (!_initialized) { //printf("Rope::Update: not initialzed\n"); return; @@ -130,6 +130,7 @@ class Rope { // Target distance of a single segment float _desiredDistance; + float _ropeLength; float _timestep = 0.01f; float _spriteStretch, _spriteWidth = 1; unsigned int _numPoints = 2; @@ -151,9 +152,9 @@ class Rope { //int i = 0; for (Point& p : _points.deque) { if (p._target) { - p._pos = *p._target->GetPosition(); p._lastPos = p._pos; - printf("updated position to %f, %f\n", p._pos.x, p._pos.y); + p._pos = *p._target->GetPosition(); + //printf("updated position to %f, %f\n", p._pos.x, p._pos.y); continue; } // We do not want to move fixed Points @@ -175,48 +176,53 @@ class Rope { } void enforceConstraints() { - //printf("enforceConstraints: deque %p, iterations %d, size %d\n", &_points, _iterations, _points.deque.size()); // We perform the enforcement multiple times for (unsigned int iteration = 0; iteration < _iterations; iteration++) { - printf("iteration %d: ", iteration); + //float distanceTotal = 0.0f; + //printf("iteration %d: ", iteration); // We iterate over each pair of points for (size_t i = 1; i < _points.deque.size(); i++) { - Point &p1 = _points.deque[i - 1]; - Point &p2 = _points.deque[i]; + Point& p1 = _points.deque[i - 1]; + Point& p2 = _points.deque[i]; // Calculating distance between the Points - float distance = distanceFunc(p1._pos, p2._pos); + float distance = (float)sqrt(pow(p1._pos.x - p2._pos.x, 2) + pow(p1._pos.y - p2._pos.y, 2)); float distanceError = distance - _desiredDistance; - printf("distance %f, error %f, ", distance, distanceError); + //printf("distance %f, error %f, ", distance, distanceError); - // The direction in which Points should be pulled or pushed + // The direction in which Points should be pulled or pushed Vector difference(p2._pos.x - p1._pos.x, p2._pos.y - p1._pos.y); - printf("difference %f, %f, ", difference.x, difference.y); + //printf("difference %f, %f, ", difference.x, difference.y); // We need to make it a unit vector // This will allow us to easily scale the impact we have // on each Point's position. Vector direction(difference.x / (float)sqrt(pow(difference.x, 2) + pow(difference.y, 2)), difference.y / (float)sqrt(pow(difference.x, 2) + pow(difference.y, 2))); - printf("direction %f, %f\n", difference.x, difference.y); + //printf("direction %f, %f\n", difference.x, difference.y); // Finally, we can update Points' positions // We need to remember that fixed Points should stay in place if (isFixed(p1) && !isFixed(p2)) { p2._pos -= direction * distanceError; - printf("moved p2, now %f, %f\n", p2._pos.x, p2._pos.y); - } else if (isFixed(p2) && !isFixed(p1)) { + //printf("moved p2, now %f, %f\n", p2._pos.x, p2._pos.y); + } + else if (isFixed(p2) && !isFixed(p1)) { p1._pos += direction * distanceError; - printf("moved p1, now %f, %f\n", p1._pos.x, p1._pos.y); + //printf("moved p1, now %f, %f\n", p1._pos.x, p1._pos.y); // keeping this comparison in case both points are fixed - } else if (!isFixed(p1) && !isFixed(p2)) { + } + else if (!isFixed(p1) && !isFixed(p2)) { p2._pos -= direction * distanceError * 0.5; - printf("moved p2 halfway, now %f, %f\n", p2._pos.x, p2._pos.y); + //printf("moved p2 halfway, now %f, %f\n", p2._pos.x, p2._pos.y); p1._pos += direction * distanceError * 0.5; - printf("moved p1 halfway, now %f, %f\n", p1._pos.x, p1._pos.y); + //printf("moved p1 halfway, now %f, %f\n", p1._pos.x, p1._pos.y); } + //printf("distance: %f\n", distanceFunc(p1._pos, p2._pos)); + //distanceTotal += distanceFunc(p1._pos, p2._pos); //__debugbreak(); } + //printf("total length: %f, target: %f\n", distanceTotal, _ropeLength); } } };