diff --git a/doc/en/scripting/builtins/libmat4.md b/doc/en/scripting/builtins/libmat4.md index 7133b985..e81696bd 100644 --- a/doc/en/scripting/builtins/libmat4.md +++ b/doc/en/scripting/builtins/libmat4.md @@ -10,6 +10,7 @@ Type conventions will be used on this page. - vector - an array of three or four numbers - vec3 - array of three numbers - vec4 - array of four numbers +- quat - array of four numbers - quaternion - matrix - array of 16 numbers - matrix > [!WARNING] @@ -33,6 +34,16 @@ mat4.idt(dst: matrix) mat4.determinant(m: matrix) ``` +## Matrix from quaternion - *mat4.from_quat(...)* + +```lua +-- creates a rotation matrix from quaternion +mat4.from_quat(quaternion: quat) + +-- writes the quaternion rotation matrix to dst +mat4.from_quat(quaternion: quat, dst: matrix) +``` + ## Matrix multiplication - *mat4.mul(...)* ```lua @@ -109,6 +120,7 @@ mat4.decompose(m: matrix) { scale=vec3, rotation=matrix, + quaternion=quat, translation=vec3, skew=vec3, perspective=vec4 diff --git a/doc/ru/scripting/builtins/libmat4.md b/doc/ru/scripting/builtins/libmat4.md index 585c0374..da4e1c2f 100644 --- a/doc/ru/scripting/builtins/libmat4.md +++ b/doc/ru/scripting/builtins/libmat4.md @@ -10,6 +10,7 @@ - vector - массив из трех или четырех чисел - vec3 - массив из трех чисел - vec4 - массив из четырех чисел +- quat - массив из четырех чисел - кватернион - matrix - массив из 16 чисел - матрица > [!WARNING] @@ -33,6 +34,16 @@ mat4.idt(dst: matrix) mat4.determinant(m: matrix) ``` +## Матрица из кватерниона - *mat4.from_quat(...)* + +```lua +-- создает матрицу вращения по кватерниону +mat4.from_quat(quaternion: quat) + +-- записывает матрицу вращения по кватерниону в dst +mat4.from_quat(quaternion: quat, dst: matrix) +``` + ## Умножение матриц - *mat4.mul(...)* ```lua @@ -109,6 +120,7 @@ mat4.decompose(m: matrix) { scale=vec3, rotation=matrix, + quaternion=quat, translation=vec3, skew=vec3, perspective=vec4 diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 22b315d1..7db93096 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -105,26 +105,6 @@ function pack.data_file(packid, name) return "world:data/"..packid.."/"..name end -vec2_mt = {} -function vec2_mt.__tostring(self) - return "vec2("..self[1]..", "..self[2]..")" -end - -vec3_mt = {} -function vec3_mt.__tostring(self) - return "vec3("..self[1]..", "..self[2]..", "..self[3]..")" -end - -vec4_mt = {} -function vec4_mt.__tostring(self) - return "vec4("..self[1]..", "..self[2]..", "..self[3]..", "..self[4]..")" -end - -color_mt = {} -function color_mt.__tostring(self) - return "rgba("..self[1]..", "..self[2]..", "..self[3]..", "..self[4]..")" -end - -- events events = { handlers = {} diff --git a/src/logic/BlocksController.cpp b/src/logic/BlocksController.cpp index 5a57d729..8f49635c 100644 --- a/src/logic/BlocksController.cpp +++ b/src/logic/BlocksController.cpp @@ -15,42 +15,6 @@ #include "scripting/scripting.hpp" -Clock::Clock(int tickRate, int tickParts) - : tickRate(tickRate), - tickParts(tickParts) { -} - -bool Clock::update(float delta) { - tickTimer += delta; - float delay = 1.0f / float(tickRate); - if (tickTimer > delay || tickPartsUndone) { - if (tickPartsUndone) { - tickPartsUndone--; - } else { - tickTimer = fmod(tickTimer, delay); - tickPartsUndone = tickParts-1; - } - return true; - } - return false; -} - -int Clock::getParts() const { - return tickParts; -} - -int Clock::getPart() const { - return tickParts-tickPartsUndone-1; -} - -int Clock::getTickRate() const { - return tickRate; -} - -int Clock::getTickId() const { - return tickId; -} - BlocksController::BlocksController(Level* level, uint padding) : level(level), chunks(level->chunks.get()), @@ -134,12 +98,34 @@ void BlocksController::onBlocksTick(int tickid, int parts) { } } +void BlocksController::randomTick( + const Chunk& chunk, int segments, const ContentIndices* indices +) { + const int segheight = CHUNK_H / segments; + + for (int s = 0; s < segments; s++) { + for (int i = 0; i < 4; i++) { + int bx = random.rand() % CHUNK_W; + int by = random.rand() % segheight + s * segheight; + int bz = random.rand() % CHUNK_D; + const voxel& vox = chunk.voxels[(by * CHUNK_D + bz) * CHUNK_W + bx]; + Block* block = indices->blocks.get(vox.id); + if (block->rt.funcsset.randupdate) { + scripting::random_update_block( + block, + chunk.x * CHUNK_W + bx, by, + chunk.z * CHUNK_D + bz + ); + } + } + } +} + void BlocksController::randomTick(int tickid, int parts) { + auto indices = level->content->getIndices(); const int w = chunks->w; const int d = chunks->d; int segments = 4; - int segheight = CHUNK_H / segments; - auto indices = level->content->getIndices(); for (uint z = padding; z < d-padding; z++){ for (uint x = padding; x < w-padding; x++){ @@ -151,22 +137,7 @@ void BlocksController::randomTick(int tickid, int parts) { if (chunk == nullptr || !chunk->flags.lighted) { continue; } - for (int s = 0; s < segments; s++) { - for (int i = 0; i < 4; i++) { - int bx = random.rand() % CHUNK_W; - int by = random.rand() % segheight + s * segheight; - int bz = random.rand() % CHUNK_D; - const voxel& vox = chunk->voxels[(by * CHUNK_D + bz) * CHUNK_W + bx]; - Block* block = indices->blocks.get(vox.id); - if (block->rt.funcsset.randupdate) { - scripting::random_update_block( - block, - chunk->x * CHUNK_W + bx, by, - chunk->z * CHUNK_D + bz - ); - } - } - } + randomTick(*chunk, segments, indices); } } } diff --git a/src/logic/BlocksController.hpp b/src/logic/BlocksController.hpp index 179302f5..0c904932 100644 --- a/src/logic/BlocksController.hpp +++ b/src/logic/BlocksController.hpp @@ -4,6 +4,7 @@ #include "../typedefs.hpp" #include "../maths/fastmaths.hpp" #include "../voxels/voxel.hpp" +#include "../util/Clock.hpp" #include #include @@ -11,8 +12,10 @@ class Player; class Block; class Level; +class Chunk; class Chunks; class Lighting; +class ContentIndices; enum class BlockInteraction { step, @@ -25,32 +28,14 @@ using on_block_interaction = std::function; -class Clock { - int tickRate; - int tickParts; - - float tickTimer = 0.0f; - int tickId = 0; - int tickPartsUndone = 0; -public: - Clock(int tickRate, int tickParts); - - bool update(float delta); - - int getParts() const; - int getPart() const; - int getTickRate() const; - int getTickId() const; -}; - -/* BlocksController manages block updates and block data (aka inventories) */ +/// BlocksController manages block updates and data (inventories, metadata) class BlocksController { Level* level; Chunks* chunks; Lighting* lighting; - Clock randTickClock; - Clock blocksTickClock; - Clock worldTickClock; + util::Clock randTickClock; + util::Clock blocksTickClock; + util::Clock worldTickClock; uint padding; FastRandom random; std::vector blockInteractionCallbacks; @@ -64,6 +49,7 @@ public: void placeBlock(Player* player, const Block* def, blockstate state, int x, int y, int z); void update(float delta); + void randomTick(const Chunk& chunk, int segments, const ContentIndices* indices); void randomTick(int tickid, int parts); void onBlocksTick(int tickid, int parts); int64_t createBlockInventory(int x, int y, int z); diff --git a/src/logic/scripting/lua/lib__rigidbody.cpp b/src/logic/scripting/lua/lib__rigidbody.cpp index 075736cd..ea9c138f 100644 --- a/src/logic/scripting/lua/lib__rigidbody.cpp +++ b/src/logic/scripting/lua/lib__rigidbody.cpp @@ -4,7 +4,7 @@ static int l_get_vel(lua::State* L) { if (auto entity = get_entity(L, 1)) { - return lua::pushvec3_arr(L, entity->getRigidbody().hitbox.velocity); + return lua::pushvec3(L, entity->getRigidbody().hitbox.velocity); } return 0; } @@ -32,7 +32,7 @@ static int l_set_enabled(lua::State* L) { static int l_get_size(lua::State* L) { if (auto entity = get_entity(L, 1)) { - return lua::pushvec3_arr(L, entity->getRigidbody().hitbox.halfsize * 2.0f); + return lua::pushvec3(L, entity->getRigidbody().hitbox.halfsize * 2.0f); } return 0; } diff --git a/src/logic/scripting/lua/lib__transform.cpp b/src/logic/scripting/lua/lib__transform.cpp index 11ee1566..0eb7fc9c 100644 --- a/src/logic/scripting/lua/lib__transform.cpp +++ b/src/logic/scripting/lua/lib__transform.cpp @@ -2,7 +2,7 @@ static int l_get_pos(lua::State* L) { if (auto entity = get_entity(L, 1)) { - return lua::pushvec3_arr(L, entity->getTransform().pos); + return lua::pushvec3(L, entity->getTransform().pos); } return 0; } @@ -18,7 +18,7 @@ static int l_set_pos(lua::State* L) { static int l_get_size(lua::State* L) { if (auto entity = get_entity(L, 1)) { - return lua::pushvec3_arr(L, entity->getTransform().size); + return lua::pushvec3(L, entity->getTransform().size); } return 0; } diff --git a/src/logic/scripting/lua/libaudio.cpp b/src/logic/scripting/lua/libaudio.cpp index ec874971..398bd6b5 100644 --- a/src/logic/scripting/lua/libaudio.cpp +++ b/src/logic/scripting/lua/libaudio.cpp @@ -334,7 +334,7 @@ static int l_audio_get_duration(lua::State* L) { static int l_audio_get_position(lua::State* L) { auto speaker = audio::get_speaker(lua::tointeger(L, 1)); if (speaker != nullptr) { - return lua::pushvec3(L, speaker->getPosition()); + return lua::pushvec3_stack(L, speaker->getPosition()); } return 0; } @@ -343,7 +343,7 @@ static int l_audio_get_position(lua::State* L) { static int l_audio_get_velocity(lua::State* L) { auto speaker = audio::get_speaker(lua::tointeger(L, 1)); if (speaker != nullptr) { - return lua::pushvec3(L, speaker->getVelocity()); + return lua::pushvec3_stack(L, speaker->getVelocity()); } return 0; } diff --git a/src/logic/scripting/lua/libblock.cpp b/src/logic/scripting/lua/libblock.cpp index c4bdf41a..51182807 100644 --- a/src/logic/scripting/lua/libblock.cpp +++ b/src/logic/scripting/lua/libblock.cpp @@ -61,7 +61,7 @@ static int l_is_extended(lua::State* L) { static int l_get_size(lua::State* L) { if (auto def = require_block(L)) { - return lua::pushivec3(L, def->size.x, def->size.y, def->size.z); + return lua::pushivec3_stack(L, def->size.x, def->size.y, def->size.z); } return 0; } @@ -80,7 +80,7 @@ static int l_seek_origin(lua::State* L) { auto z = lua::tointeger(L, 3); auto vox = level->chunks->get(x, y, z); auto def = indices->blocks.get(vox->id); - return lua::pushivec3(L, level->chunks->seekOrigin({x, y, z}, def, vox->state)); + return lua::pushivec3_stack(L, level->chunks->seekOrigin({x, y, z}, def, vox->state)); } static int l_set(lua::State* L) { @@ -119,14 +119,14 @@ static int l_get_x(lua::State* L) { auto z = lua::tointeger(L, 3); auto vox = level->chunks->get(x, y, z); if (vox == nullptr) { - return lua::pushivec3(L, 1, 0, 0); + return lua::pushivec3_stack(L, 1, 0, 0); } auto def = level->content->getIndices()->blocks.get(vox->id); if (!def->rotatable) { - return lua::pushivec3(L, 1, 0, 0); + return lua::pushivec3_stack(L, 1, 0, 0); } else { const CoordSystem& rot = def->rotations.variants[vox->state.rotation]; - return lua::pushivec3(L, rot.axisX.x, rot.axisX.y, rot.axisX.z); + return lua::pushivec3_stack(L, rot.axisX.x, rot.axisX.y, rot.axisX.z); } } @@ -136,14 +136,14 @@ static int l_get_y(lua::State* L) { auto z = lua::tointeger(L, 3); auto vox = level->chunks->get(x, y, z); if (vox == nullptr) { - return lua::pushivec3(L, 0, 1, 0); + return lua::pushivec3_stack(L, 0, 1, 0); } auto def = level->content->getIndices()->blocks.get(vox->id); if (!def->rotatable) { - return lua::pushivec3(L, 0, 1, 0); + return lua::pushivec3_stack(L, 0, 1, 0); } else { const CoordSystem& rot = def->rotations.variants[vox->state.rotation]; - return lua::pushivec3(L, rot.axisY.x, rot.axisY.y, rot.axisY.z); + return lua::pushivec3_stack(L, rot.axisY.x, rot.axisY.y, rot.axisY.z); } } @@ -153,14 +153,14 @@ static int l_get_z(lua::State* L) { auto z = lua::tointeger(L, 3); auto vox = level->chunks->get(x, y, z); if (vox == nullptr) { - return lua::pushivec3(L, 0, 0, 1); + return lua::pushivec3_stack(L, 0, 0, 1); } auto def = level->content->getIndices()->blocks.get(vox->id); if (!def->rotatable) { - return lua::pushivec3(L, 0, 0, 1); + return lua::pushivec3_stack(L, 0, 0, 1); } else { const CoordSystem& rot = def->rotations.variants[vox->state.rotation]; - return lua::pushivec3(L, rot.axisZ.x, rot.axisZ.y, rot.axisZ.z); + return lua::pushivec3_stack(L, rot.axisZ.x, rot.axisZ.y, rot.axisZ.z); } } @@ -284,10 +284,10 @@ static int l_get_hitbox(lua::State* L) { auto& hitbox = def->rt.hitboxes[lua::tointeger(L, 2)].at(0); lua::createtable(L, 2, 0); - lua::pushvec3_arr(L, hitbox.min()); + lua::pushvec3(L, hitbox.min()); lua::rawseti(L, 1); - lua::pushvec3_arr(L, hitbox.size()); + lua::pushvec3(L, hitbox.size()); lua::rawseti(L, 2); return 1; } @@ -361,16 +361,16 @@ static int l_raycast(lua::State* L) { lua::createtable(L, 0, 5); } - lua::pushvec3_arr(L, end); + lua::pushvec3(L, end); lua::setfield(L, "endpoint"); - lua::pushvec3_arr(L, normal); + lua::pushvec3(L, normal); lua::setfield(L, "normal"); lua::pushnumber(L, glm::distance(start, end)); lua::setfield(L, "length"); - lua::pushvec3_arr(L, iend); + lua::pushvec3(L, iend); lua::setfield(L, "iendpoint"); lua::pushinteger(L, voxel->id); diff --git a/src/logic/scripting/lua/libcamera.cpp b/src/logic/scripting/lua/libcamera.cpp index 69f681d1..255e2b3d 100644 --- a/src/logic/scripting/lua/libcamera.cpp +++ b/src/logic/scripting/lua/libcamera.cpp @@ -34,7 +34,7 @@ static int l_name(lua::State* L) { } static int getter_pos(lua::State* L, const Camera& camera) { - return lua::pushvec3_arr(L, camera.position); + return lua::pushvec3(L, camera.position); } static void setter_pos(lua::State* L, Camera& camera, int idx) { @@ -79,13 +79,13 @@ static void setter_flipped(lua::State* L, Camera& camera, int idx) { } static int getter_front(lua::State* L, const Camera& camera) { - return lua::pushvec3_arr(L, camera.front); + return lua::pushvec3(L, camera.front); } static int getter_right(lua::State* L, const Camera& camera) { - return lua::pushvec3_arr(L, camera.right); + return lua::pushvec3(L, camera.right); } static int getter_up(lua::State* L, const Camera& camera) { - return lua::pushvec3_arr(L, camera.up); + return lua::pushvec3(L, camera.up); } static int l_look_at(lua::State* L) { diff --git a/src/logic/scripting/lua/libentity.cpp b/src/logic/scripting/lua/libentity.cpp index 55c36090..5c98307e 100644 --- a/src/logic/scripting/lua/libentity.cpp +++ b/src/logic/scripting/lua/libentity.cpp @@ -138,16 +138,16 @@ static int l_raycast(lua::State* L) { lua::createtable(L, 0, 6); } - lua::pushvec3_arr(L, start + dir * ray->distance); + lua::pushvec3(L, start + dir * ray->distance); lua::setfield(L, "endpoint"); - lua::pushvec3_arr(L, ray->normal); + lua::pushvec3(L, ray->normal); lua::setfield(L, "normal"); lua::pushnumber(L, glm::distance(start, end)); lua::setfield(L, "length"); - lua::pushvec3_arr(L, iend); + lua::pushvec3(L, iend); lua::setfield(L, "iendpoint"); lua::pushinteger(L, block); @@ -162,16 +162,16 @@ static int l_raycast(lua::State* L) { } else { lua::createtable(L, 0, 5); } - lua::pushvec3_arr(L, end); + lua::pushvec3(L, end); lua::setfield(L, "endpoint"); - lua::pushvec3_arr(L, normal); + lua::pushvec3(L, normal); lua::setfield(L, "normal"); lua::pushnumber(L, glm::distance(start, end)); lua::setfield(L, "length"); - lua::pushvec3_arr(L, iend); + lua::pushvec3(L, iend); lua::setfield(L, "iendpoint"); lua::pushinteger(L, block); diff --git a/src/logic/scripting/lua/libgui.cpp b/src/logic/scripting/lua/libgui.cpp index 7555f48d..7ae64d86 100644 --- a/src/logic/scripting/lua/libgui.cpp +++ b/src/logic/scripting/lua/libgui.cpp @@ -204,7 +204,7 @@ static int p_get_track_width(UINode* node, lua::State* L) { static int p_get_track_color(UINode* node, lua::State* L) { if (auto bar = dynamic_cast(node)) { - return lua::pushcolor_arr(L, bar->getTrackColor()); + return lua::pushcolor(L, bar->getTrackColor()); } return 0; } @@ -281,13 +281,13 @@ static int p_set_interval(UINode* node, lua::State* L) { } static int p_get_color(UINode* node, lua::State* L) { - return lua::pushcolor_arr(L, node->getColor()); + return lua::pushcolor(L, node->getColor()); } static int p_get_hover_color(UINode* node, lua::State* L) { - return lua::pushcolor_arr(L, node->getHoverColor()); + return lua::pushcolor(L, node->getHoverColor()); } static int p_get_pressed_color(UINode* node, lua::State* L) { - return lua::pushcolor_arr(L, node->getPressedColor()); + return lua::pushcolor(L, node->getPressedColor()); } static int p_get_tooltip(UINode* node, lua::State* L) { return lua::pushwstring(L, node->getTooltip()); @@ -296,13 +296,13 @@ static int p_get_tooltip_delay(UINode* node, lua::State* L) { return lua::pushnumber(L, node->getTooltipDelay()); } static int p_get_pos(UINode* node, lua::State* L) { - return lua::pushvec2_arr(L, node->getPos()); + return lua::pushvec2(L, node->getPos()); } static int p_get_wpos(UINode* node, lua::State* L) { - return lua::pushvec2_arr(L, node->calcPos()); + return lua::pushvec2(L, node->calcPos()); } static int p_get_size(UINode* node, lua::State* L) { - return lua::pushvec2_arr(L, node->getSize()); + return lua::pushvec2(L, node->getSize()); } static int p_is_interactive(UINode* node, lua::State* L) { return lua::pushboolean(L, node->isInteractive()); @@ -588,7 +588,7 @@ static int l_gui_get_locales_info(lua::State* L) { } static int l_gui_getviewport(lua::State* L) { - return lua::pushvec2_arr(L, engine->getGUI()->getContainer()->getSize()); + return lua::pushvec2(L, engine->getGUI()->getContainer()->getSize()); } const luaL_Reg guilib [] = { diff --git a/src/logic/scripting/lua/libinput.cpp b/src/logic/scripting/lua/libinput.cpp index 5969d598..f09cc4a4 100644 --- a/src/logic/scripting/lua/libinput.cpp +++ b/src/logic/scripting/lua/libinput.cpp @@ -45,7 +45,7 @@ static int l_add_callback(lua::State* L) { } static int l_get_mouse_pos(lua::State* L) { - return lua::pushvec2_arr(L, Events::cursor); + return lua::pushvec2(L, Events::cursor); } static int l_get_bindings(lua::State* L) { diff --git a/src/logic/scripting/lua/libmat4.cpp b/src/logic/scripting/lua/libmat4.cpp index 74b2ce7f..e4a5dfd3 100644 --- a/src/logic/scripting/lua/libmat4.cpp +++ b/src/logic/scripting/lua/libmat4.cpp @@ -52,9 +52,9 @@ static int l_mul(lua::State* L) { switch (argc) { case 2: { if (len2 == 4) { - return lua::pushvec4(L, matrix1 * lua::tovec4(L, 2)); + return lua::pushvec4_stack(L, matrix1 * lua::tovec4(L, 2)); } else if (len2 == 3) { - return lua::pushvec3(L, matrix1 * glm::vec4(lua::tovec3(L, 2), 1.0f)); + return lua::pushvec3_stack(L, matrix1 * glm::vec4(lua::tovec3(L, 2), 1.0f)); } return lua::pushmat4(L, matrix1 * lua::tomat4(L, 2)); } @@ -172,6 +172,7 @@ static int l_transpose(lua::State* L) { /// mat4.decompose(m: float[16]) -> { /// scale=float[3], /// rotation=float[16], +/// quaternion=float[4], /// translation=float[3], /// skew=float[3], /// perspective=float[4] @@ -192,21 +193,24 @@ static int l_decompose(lua::State* L) { perspective ); - lua::createtable(L, 0, 5); + lua::createtable(L, 0, 6); - lua::pushvec3_arr(L, scale); + lua::pushvec3(L, scale); lua::setfield(L, "scale"); lua::pushmat4(L, glm::toMat4(rotation)); lua::setfield(L, "rotation"); - lua::pushvec3_arr(L, translation); + lua::pushquat(L, rotation); + lua::setfield(L, "quaternion"); + + lua::pushvec3(L, translation); lua::setfield(L, "translation"); - lua::pushvec3_arr(L, skew); + lua::pushvec3(L, skew); lua::setfield(L, "skew"); - lua::pushvec4_arr(L, perspective); + lua::pushvec4(L, perspective); lua::setfield(L, "perspective"); return 1; } @@ -227,6 +231,21 @@ static int l_look_at(lua::State* L) { } } +static int l_from_quat(lua::State* L) { + uint argc = lua::gettop(L); + if (argc != 1 && argc != 2) { + throw std::runtime_error("invalid arguments number (1 or 2 expected)"); + } + auto quat = lua::toquat(L, 1); + switch (argc) { + case 1: + return lua::pushmat4(L, glm::toMat4(quat)); + case 2: + return lua::setmat4(L, 2, glm::toMat4(quat)); + } + return 0; +} + static int l_tostring(lua::State* L) { auto matrix = lua::tomat4(L, 1); bool multiline = lua::toboolean(L, 2); @@ -266,6 +285,7 @@ const luaL_Reg mat4lib [] = { {"determinant", lua::wrap}, {"decompose", lua::wrap}, {"look_at", lua::wrap}, + {"from_quat", lua::wrap}, {"tostring", lua::wrap}, {NULL, NULL} }; diff --git a/src/logic/scripting/lua/libplayer.cpp b/src/logic/scripting/lua/libplayer.cpp index 06724901..36088569 100644 --- a/src/logic/scripting/lua/libplayer.cpp +++ b/src/logic/scripting/lua/libplayer.cpp @@ -17,7 +17,7 @@ inline std::shared_ptr get_player(lua::State* L, int idx) { static int l_get_pos(lua::State* L) { if (auto player = get_player(L, 1)) { - return lua::pushvec3(L, player->getPosition()); + return lua::pushvec3_stack(L, player->getPosition()); } return 0; } @@ -37,7 +37,7 @@ static int l_set_pos(lua::State* L) { static int l_get_vel(lua::State* L) { if (auto player = get_player(L, 1)) { if (auto hitbox = player->getHitbox()) { - return lua::pushvec3(L, hitbox->velocity); + return lua::pushvec3_stack(L, hitbox->velocity); } } return 0; @@ -59,7 +59,7 @@ static int l_set_vel(lua::State* L) { static int l_get_rot(lua::State* L) { if (auto player = get_player(L, 1)) { - return lua::pushvec3(L, player->cam); + return lua::pushvec3_stack(L, player->cam); } return 0; } @@ -85,7 +85,7 @@ static int l_set_rot(lua::State* L) { static int l_get_dir(lua::State* L) { if (auto player = get_player(L, 1)) { - return lua::pushvec3_arr(L, player->camera->front); + return lua::pushvec3(L, player->camera->front); } return 0; } @@ -133,7 +133,7 @@ static int l_get_selected_block(lua::State* L) { if (player->selection.vox.id == BLOCK_VOID) { return 0; } - return lua::pushivec3(L, player->selection.position); + return lua::pushivec3_stack(L, player->selection.position); } return 0; } @@ -149,7 +149,7 @@ static int l_get_selected_entity(lua::State* L) { static int l_get_spawnpoint(lua::State* L) { if (auto player = get_player(L, 1)) { - return lua::pushvec3(L, player->getSpawnPoint()); + return lua::pushvec3_stack(L, player->getSpawnPoint()); } return 0; } diff --git a/src/logic/scripting/lua/libvecn.cpp b/src/logic/scripting/lua/libvecn.cpp index 1aa4d43f..0ed68a6b 100644 --- a/src/logic/scripting/lua/libvecn.cpp +++ b/src/logic/scripting/lua/libvecn.cpp @@ -140,7 +140,7 @@ static int l_spherical_rand(lua::State* L) { int argc = lua::gettop(L); switch (argc) { case 1: - return lua::pushvec3_arr(L, glm::sphericalRand(lua::tonumber(L, 1))); + return lua::pushvec3(L, glm::sphericalRand(lua::tonumber(L, 1))); case 2: return lua::setvec(L, 2, glm::sphericalRand(static_cast(lua::tonumber(L, 1)))); diff --git a/src/logic/scripting/lua/lua_util.hpp b/src/logic/scripting/lua/lua_util.hpp index ed0b1cde..5237604c 100644 --- a/src/logic/scripting/lua/lua_util.hpp +++ b/src/logic/scripting/lua/lua_util.hpp @@ -7,6 +7,8 @@ #include #include #include +#define GLM_ENABLE_EXPERIMENTAL +#include // NOTE: const std::string& used instead of string_view because c_str() needed namespace lua { @@ -116,28 +118,47 @@ namespace lua { return 1; } - inline int pushivec3(lua::State* L, lua::Integer x, lua::Integer y, lua::Integer z) { + template + inline int pushvec(lua::State* L, glm::vec vec) { + createtable(L, n, 0); + for (int i = 0; i < n; i++) { + pushnumber(L, vec[i]); + rawseti(L, i+1); + } + return 1; + } + + template + inline int pushivec(lua::State* L, glm::vec vec) { + createtable(L, n, 0); + for (int i = 0; i < n; i++) { + pushinteger(L, vec[i]); + rawseti(L, i+1); + } + return 1; + } + + inline int pushivec3_stack(lua::State* L, lua::Integer x, lua::Integer y, lua::Integer z) { pushinteger(L, x); pushinteger(L, y); pushinteger(L, z); return 3; } - inline int pushivec3(lua::State* L, glm::ivec3 vec) { + inline int pushivec3_stack(lua::State* L, glm::ivec3 vec) { pushinteger(L, vec.x); pushinteger(L, vec.y); pushinteger(L, vec.z); return 3; } - inline int pushvec3(lua::State* L, glm::vec3 vec) { + inline int pushvec3_stack(lua::State* L, glm::vec3 vec) { pushnumber(L, vec.x); pushnumber(L, vec.y); pushnumber(L, vec.z); return 3; } - - inline int pushvec4(lua::State* L, glm::vec4 vec) { + inline int pushvec4_stack(lua::State* L, glm::vec4 vec) { pushnumber(L, vec.x); pushnumber(L, vec.y); pushnumber(L, vec.z); @@ -152,62 +173,30 @@ namespace lua { lua_pushvalue(L, idx); return 1; } - inline int pushvec2_arr(lua::State* L, glm::vec2 vec) { - createtable(L, 2, 0); - getglobal(L, "vec2_mt"); - setmetatable(L); - - pushnumber(L, vec.x); - rawseti(L, 1); - pushnumber(L, vec.y); - rawseti(L, 2); - return 1; + inline int pushvec2(lua::State* L, glm::vec2 vec) { + return pushvec(L, vec); } - inline int pushvec3_arr(lua::State* L, glm::vec3 vec) { - createtable(L, 3, 0); - getglobal(L, "vec3_mt"); - setmetatable(L); - - pushnumber(L, vec.x); - rawseti(L, 1); - pushnumber(L, vec.y); - rawseti(L, 2); - pushnumber(L, vec.z); - rawseti(L, 3); - return 1; + inline int pushvec3(lua::State* L, glm::vec3 vec) { + return pushvec(L, vec); } - inline int pushvec4_arr(lua::State* L, glm::vec4 vec) { + inline int pushvec4(lua::State* L, glm::vec4 vec) { + return pushvec(L, vec); + } + inline int pushcolor(lua::State* L, glm::vec4 vec) { + return pushivec(L, glm::ivec4(vec*255.0f)); + } + + inline int pushquat(lua::State* L, glm::quat quat) { createtable(L, 4, 0); - getglobal(L, "vec4_mt"); - setmetatable(L); - - pushnumber(L, vec.x); - rawseti(L, 1); - pushnumber(L, vec.y); - rawseti(L, 2); - pushnumber(L, vec.z); - rawseti(L, 3); - pushnumber(L, vec.w); - rawseti(L, 4); + for (size_t i = 0; i < 4; i++) { + pushnumber(L, quat[i]); + rawseti(L, i+1); + } return 1; } - inline int pushcolor_arr(lua::State* L, glm::vec4 vec) { - createtable(L, 4, 0); - getglobal(L, "color_mt"); - setmetatable(L); - pushinteger(L, vec.x*255); - rawseti(L, 1); - pushinteger(L, vec.y*255); - rawseti(L, 2); - pushinteger(L, vec.z*255); - rawseti(L, 3); - pushinteger(L, vec.w*255); - rawseti(L, 4); - return 1; - } inline int pushmat4(lua::State* L, glm::mat4 matrix) { createtable(L, 16, 0); for (uint y = 0; y < 4; y++) { @@ -396,6 +385,24 @@ namespace lua { pop(L); return glm::vec4(x, y, z, w); } + + inline glm::quat toquat(lua::State* L, int idx) { + pushvalue(L, idx); + if (!istable(L, idx) || objlen(L, idx) < 4) { + throw std::runtime_error("value must be an array of four numbers"); + } + rawgeti(L, 1); + auto x = tonumber(L, -1); pop(L); + rawgeti(L, 2); + auto y = tonumber(L, -1); pop(L); + rawgeti(L, 3); + auto z = tonumber(L, -1); pop(L); + rawgeti(L, 4); + auto w = tonumber(L, -1); pop(L); + pop(L); + return glm::quat(x, y, z, w); + } + inline glm::vec3 tovec3_stack(lua::State* L, int idx) { return glm::vec3( tonumber(L, idx), tonumber(L, idx+1), tonumber(L, idx+2) diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 3b46455d..cdfcba3c 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -201,27 +201,27 @@ void scripting::on_blocks_tick(const Block* block, int tps) { void scripting::update_block(const Block* block, int x, int y, int z) { std::string name = block->name + ".update"; lua::emit_event(lua::get_main_thread(), name, [x, y, z] (auto L) { - return lua::pushivec3(L, x, y, z); + return lua::pushivec3_stack(L, x, y, z); }); } void scripting::random_update_block(const Block* block, int x, int y, int z) { std::string name = block->name + ".randupdate"; lua::emit_event(lua::get_main_thread(), name, [x, y, z] (auto L) { - return lua::pushivec3(L, x, y, z); + return lua::pushivec3_stack(L, x, y, z); }); } void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) { std::string name = block->name + ".placed"; lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (auto L) { - lua::pushivec3(L, x, y, z); + lua::pushivec3_stack(L, x, y, z); lua::pushinteger(L, player ? player->getId() : -1); return 4; }); auto world_event_args = [block, x, y, z, player] (lua::State* L) { lua::pushinteger(L, block->rt.id); - lua::pushivec3(L, x, y, z); + lua::pushivec3_stack(L, x, y, z); lua::pushinteger(L, player ? player->getId() : -1); return 5; }; @@ -236,14 +236,14 @@ void scripting::on_block_broken(Player* player, const Block* block, int x, int y std::string name = block->name + ".broken"; if (block->rt.funcsset.onbroken) { lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (auto L) { - lua::pushivec3(L, x, y, z); + lua::pushivec3_stack(L, x, y, z); lua::pushinteger(L, player ? player->getId() : -1); return 4; }); } auto world_event_args = [block, x, y, z, player] (lua::State* L) { lua::pushinteger(L, block->rt.id); - lua::pushivec3(L, x, y, z); + lua::pushivec3_stack(L, x, y, z); lua::pushinteger(L, player ? player->getId() : -1); return 5; }; @@ -257,7 +257,7 @@ void scripting::on_block_broken(Player* player, const Block* block, int x, int y bool scripting::on_block_interact(Player* player, const Block* block, glm::ivec3 pos) { std::string name = block->name + ".interact"; return lua::emit_event(lua::get_main_thread(), name, [pos, player] (auto L) { - lua::pushivec3(L, pos.x, pos.y, pos.z); + lua::pushivec3_stack(L, pos.x, pos.y, pos.z); lua::pushinteger(L, player->getId()); return 4; }); @@ -273,7 +273,7 @@ bool scripting::on_item_use(Player* player, const ItemDef* item) { bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z) { std::string name = item->name + ".useon"; return lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (auto L) { - lua::pushivec3(L, x, y, z); + lua::pushivec3_stack(L, x, y, z); lua::pushinteger(L, player->getId()); return 4; }); @@ -282,7 +282,7 @@ bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z) { std::string name = item->name + ".blockbreakby"; return lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (auto L) { - lua::pushivec3(L, x, y, z); + lua::pushivec3_stack(L, x, y, z); lua::pushinteger(L, player->getId()); return 4; }); diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index a6c2f528..a29e7d60 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -56,7 +56,7 @@ void Entity::setRig(const rigging::SkeletonConfig* rigConfig) { ); } -Entities::Entities(Level* level) : level(level) { +Entities::Entities(Level* level) : level(level), sensorsTickClock(20, 3) { } template @@ -350,52 +350,60 @@ void Entities::clean() { } } -void Entities::preparePhysics() { - static uint64_t frameid = 0; - frameid++; - auto view = registry.view(); - auto physics = level->physics.get(); - std::vector sensors; - for (auto [entity, eid, transform, rigidbody] : view.each()) { - if (!rigidbody.enabled) { - continue; - } - // TODO: temporary optimization until threaded solution - if ((eid.uid + frameid) % 3 != 0) { - continue; - } - for (size_t i = 0; i < rigidbody.sensors.size(); i++) { - auto& sensor = rigidbody.sensors[i]; - for (auto oid : sensor.prevEntered) { - if (sensor.nextEntered.find(oid) == sensor.nextEntered.end()) { - sensor.exitCallback(sensor.entity, i, oid); - } +void Entities::updateSensors( + Rigidbody& body, const Transform& tsf, std::vector& sensors +) { + for (size_t i = 0; i < body.sensors.size(); i++) { + auto& sensor = body.sensors[i]; + for (auto oid : sensor.prevEntered) { + if (sensor.nextEntered.find(oid) == sensor.nextEntered.end()) { + sensor.exitCallback(sensor.entity, i, oid); } - sensor.prevEntered = sensor.nextEntered; - sensor.nextEntered.clear(); + } + sensor.prevEntered = sensor.nextEntered; + sensor.nextEntered.clear(); - switch (sensor.type) { - case SensorType::AABB: - sensor.calculated.aabb = sensor.params.aabb; - sensor.calculated.aabb.transform(transform.combined); - break; - case SensorType::RADIUS: - sensor.calculated.radial = glm::vec4( - rigidbody.hitbox.position.x, - rigidbody.hitbox.position.y, - rigidbody.hitbox.position.z, - sensor.params.radial.w* - sensor.params.radial.w); - break; - } - sensors.push_back(&sensor); + switch (sensor.type) { + case SensorType::AABB: + sensor.calculated.aabb = sensor.params.aabb; + sensor.calculated.aabb.transform(tsf.combined); + break; + case SensorType::RADIUS: + sensor.calculated.radial = glm::vec4( + body.hitbox.position.x, + body.hitbox.position.y, + body.hitbox.position.z, + sensor.params.radial.w* + sensor.params.radial.w); + break; } + sensors.push_back(&sensor); + } +} + +void Entities::preparePhysics(float delta) { + if (sensorsTickClock.update(delta)) { + auto part = sensorsTickClock.getPart(); + auto parts = sensorsTickClock.getParts(); + + auto view = registry.view(); + auto physics = level->physics.get(); + std::vector sensors; + for (auto [entity, eid, transform, rigidbody] : view.each()) { + if (!rigidbody.enabled) { + continue; + } + if ((eid.uid + part) % parts != 0) { + continue; + } + updateSensors(rigidbody, transform, sensors); + } + physics->setSensors(std::move(sensors)); } - physics->setSensors(std::move(sensors)); } void Entities::updatePhysics(float delta) { - preparePhysics(); + preparePhysics(delta); auto view = registry.view(); auto physics = level->physics.get(); diff --git a/src/objects/Entities.hpp b/src/objects/Entities.hpp index 8dd87813..7bc4c2e3 100644 --- a/src/objects/Entities.hpp +++ b/src/objects/Entities.hpp @@ -4,6 +4,7 @@ #include "../typedefs.hpp" #include "../physics/Hitbox.hpp" #include "../data/dynamic.hpp" +#include "../util/Clock.hpp" #include #include @@ -161,8 +162,12 @@ class Entities { std::unordered_map entities; std::unordered_map uids; entityid_t nextID = 1; + util::Clock sensorsTickClock; - void preparePhysics(); + void updateSensors( + Rigidbody& body, const Transform& tsf, std::vector& sensors + ); + void preparePhysics(float delta); public: struct RaycastResult { entityid_t entity; diff --git a/src/util/Clock.cpp b/src/util/Clock.cpp new file mode 100644 index 00000000..bb81112e --- /dev/null +++ b/src/util/Clock.cpp @@ -0,0 +1,41 @@ +#include "Clock.hpp" + +#include + +using namespace util; + +Clock::Clock(int tickRate, int tickParts) + : tickRate(tickRate), + tickParts(tickParts) { +} + +bool Clock::update(float delta) { + tickTimer += delta; + float delay = 1.0f / float(tickRate); + if (tickTimer > delay || tickPartsUndone) { + if (tickPartsUndone) { + tickPartsUndone--; + } else { + tickTimer = std::fmod(tickTimer, delay); + tickPartsUndone = tickParts-1; + } + return true; + } + return false; +} + +int Clock::getParts() const { + return tickParts; +} + +int Clock::getPart() const { + return tickParts-tickPartsUndone-1; +} + +int Clock::getTickRate() const { + return tickRate; +} + +int Clock::getTickId() const { + return tickId; +} diff --git a/src/util/Clock.hpp b/src/util/Clock.hpp new file mode 100644 index 00000000..6a59051a --- /dev/null +++ b/src/util/Clock.hpp @@ -0,0 +1,24 @@ +#ifndef UTIL_CLOCK_HPP_ +#define UTIL_CLOCK_HPP_ + +namespace util { + class Clock { + int tickRate; + int tickParts; + + float tickTimer = 0.0f; + int tickId = 0; + int tickPartsUndone = 0; + public: + Clock(int tickRate, int tickParts); + + bool update(float delta); + + int getParts() const; + int getPart() const; + int getTickRate() const; + int getTickId() const; + }; +} + +#endif // UTIL_CLOCK_HPP_