diff --git a/src/editor/main.cpp b/src/editor/main.cpp index 93cca04..df2cb24 100644 --- a/src/editor/main.cpp +++ b/src/editor/main.cpp @@ -360,7 +360,7 @@ class App : public OgreBites::ApplicationContext { SkyBoxRenderer *sky; bool mGrab; KeyboardListener mKbd; - SceneData mEditorNormalScene, mEditorAltScene; + SceneData mEditorNormalScene; public: App() @@ -377,7 +377,6 @@ public: OgreBites::ApplicationContext::setup(); Ogre::Root *root = getRoot(); mEditorNormalScene.setup(root, getOverlaySystem()); - mEditorAltScene.setup(root, getOverlaySystem()); } bool isWindowGrab() { @@ -407,7 +406,6 @@ public: { // and tell it to render into the main window mEditorNormalScene.initCamera("fps_camera"); - mEditorNormalScene.initCamera("alt_camera"); mViewport = getRenderWindow()->addViewport( mEditorNormalScene.mCamera); } @@ -420,7 +418,6 @@ public: << "\n"; Ogre::Root *root = getRoot(); mEditorNormalScene.setupRTSS(); - mEditorAltScene.setupRTSS(); setWindowGrab(false); std::cout << "Init camera" << "\n"; @@ -455,26 +452,6 @@ public: ECS::get().modified(); } ECS::update(delta); -#if 0 - if (switchWindow) { - int scene = ECS::get().scene; - mEditorNormalScene.mScnMgr->removeRenderQueueListener( - getOverlaySystem()); - mEditorAltScene.mScnMgr->removeRenderQueueListener( - getOverlaySystem()); - mViewport->setOverlaysEnabled(false); - if (scene == 0) - mViewport->setCamera( - mEditorNormalScene.mCamera); - else if (scene == 1) - mViewport->setCamera(mEditorAltScene.mCamera); - mViewport->setOverlaysEnabled(true); - mEditorNormalScene.mScnMgr->addRenderQueueListener( - getOverlaySystem()); - mEditorAltScene.mScnMgr->addRenderQueueListener( - getOverlaySystem()); - } -#endif } class InputListenerChainFlexible : public OgreBites::InputListener { protected: @@ -632,10 +609,6 @@ public: mEditorNormalScene.mScnMgr, /*mDynWorld.get(), */ mEditorNormalScene.mCameraNode, mEditorNormalScene.mCamera, getRenderWindow()); - ECS::setupEditorAlt( - mEditorAltScene.mScnMgr, - /*mDynWorld.get(), */ mEditorAltScene.mCameraNode, - mEditorAltScene.mCamera, getRenderWindow()); ECS::get().import (); ECS::get().import (); ECS::get().set( @@ -667,14 +640,6 @@ public: nullptr, { getImGuiInputListener(), &mKbd } }); ECS::get().add(); -#if 0 - ECS::get() - .observer("UpdateEditorScene") - .event(flecs::OnSet) - .each([&](ECS::EditorSceneSwitch &sw) { - switchWindow = true; - }); -#endif std::shared_ptr manualObj( mEditorNormalScene.mScnMgr->createManualObject( "EditorGizmo")); @@ -684,79 +649,6 @@ public: gizmoNode->attachObject(manualObj.get()); manualObj->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY); ECS::get().set({ manualObj, gizmoNode }); -#if 0 - ECS::get() - .system("UpdateEditorCamera") - .kind(flecs::OnUpdate) - .each([&](const ECS::EngineData &eng, - ECS::Camera &camera, - const ECS::Input &input) { - if (!camera.configured) { - // create a pivot at roughly the character's shoulder - camera.mCameraPivot = - eng.mScnMgr->getRootSceneNode() - ->createChildSceneNode(); - camera.mCameraGoal = - camera.mCameraPivot - ->createChildSceneNode( - Ogre::Vector3( - 0, 2, - 0)); - camera.mCameraNode->setPosition( - camera.mCameraPivot - ->getPosition() + - camera.mCameraGoal - ->getPosition()); - camera.mCameraGoal->lookAt( - Ogre::Vector3(0, 0, -10), - Ogre::Node::TS_PARENT); - camera.mCameraPivot->setFixedYawAxis( - true); - camera.mCameraGoal->setFixedYawAxis( - true); - camera.mCameraNode->setFixedYawAxis( - true); - // our model is quite small, so reduce the clipping planes - camera.mCamera->setNearClipDistance( - 0.1f); - camera.mCamera->setFarClipDistance(700); - - camera.mPivotPitch = 0; - camera.configured = true; - } else { - // place the camera pivot roughly at the character's shoulder -#if 0 - camera.mCameraPivot->setPosition( - ch.mBodyNode->getPosition() + - Ogre::Vector3::UNIT_Y * CAM_HEIGHT); -#endif - // move the camera smoothly to the goal - Ogre::Vector3 goalOffset = - camera.mCameraGoal - ->_getDerivedPosition() - - camera.mCameraNode - ->getPosition(); - camera.mCameraNode->translate( - goalOffset * eng.delta * 9.0f); - // always look at the pivot -#if 0 - camera.mCameraNode->lookAt( - camera.mCameraPivot - ->_getDerivedPosition(), - Ogre::Node::TS_PARENT); -#endif - camera.mCameraNode->_setDerivedOrientation( - camera.mCameraGoal - ->_getDerivedOrientation()); - } - if (input.control & 512 && input.mouse_moved) { - mCameraPivot->yaw( - Ogre::Radian(-input.mouse.x * - 3.0f * eng.delta)); - } - }); -#endif } bool get_gui_active() { diff --git a/src/gamedata/GameData.cpp b/src/gamedata/GameData.cpp index 7485e87..60e098a 100644 --- a/src/gamedata/GameData.cpp +++ b/src/gamedata/GameData.cpp @@ -259,9 +259,4 @@ bool Vector3::zeroLength() const return (l < 1e-06 * 1e-06); } -void setupEditorAlt(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode, - Ogre::Camera *camera, Ogre::RenderWindow *window) -{ -} - } diff --git a/src/gamedata/TerrainModule.cpp b/src/gamedata/TerrainModule.cpp index 8f57779..33c4eb9 100644 --- a/src/gamedata/TerrainModule.cpp +++ b/src/gamedata/TerrainModule.cpp @@ -347,8 +347,8 @@ public: break; long x = collider_queue.front().x; long y = collider_queue.front().y; - std::cout << x << " " << y << " " - << collider_queue.size() << std::endl; + // std::cout << x << " " << y << " " + // << collider_queue.size() << std::endl; Ogre::Terrain *terrain = group->getTerrain(x, y); Ogre::Vector3 worldPos; group->convertTerrainSlotToWorldPosition(x, y, diff --git a/src/gamedata/items/items.cpp b/src/gamedata/items/items.cpp index 7b9d777..988131d 100644 --- a/src/gamedata/items/items.cpp +++ b/src/gamedata/items/items.cpp @@ -13,6 +13,7 @@ #include "TerrainModule.h" #include "physics.h" #include "PhysicsModule.h" +#include "LuaData.h" #include "harbour.h" #include "temple.h" #include "town.h" @@ -30,6 +31,92 @@ void showItemPopup(const std::pair &item) StaticGeometryModule::getItemProperties(item.first); nlohmann::json j = nlohmann::json::parse(prop); Ogre::String itemType = j["type"].get(); + bool changed = false; + bool set = false; + bool offset = false; + Ogre::Vector3 offsetVal(0, 0, 0); + int i; + struct OffsetButton { + Ogre::String label; + Ogre::Vector3 offset; + ImGuiDir direction; + }; + struct OffsetButton buttons_large[] = { + { "ElevateUp", { 0, 1, 0 }, ImGuiDir::ImGuiDir_Up }, + { "ElevateDown", { 0, -1, 0 }, ImGuiDir::ImGuiDir_Down }, + { "X+", { 1, 0, 0 }, ImGuiDir::ImGuiDir_None }, + { "X-", { -1, 0, 0 }, ImGuiDir::ImGuiDir_None }, + { "Z+", { 0, 0, 1 }, ImGuiDir::ImGuiDir_None }, + { "Z-", { 0, 0, -1 }, ImGuiDir::ImGuiDir_None }, + }; + struct OffsetButton buttons_small[] = { + { "SmallElevateUp", + { 0, 0.1f, 0 }, + ImGuiDir::ImGuiDir_Up }, + { "SmallElevateDown", + { 0, -0.1f, 0 }, + ImGuiDir::ImGuiDir_Down }, + { "0.1 X+", { 0.1f, 0, 0 }, ImGuiDir::ImGuiDir_None }, + { "0.1 X-", { -0.1f, 0, 0 }, ImGuiDir::ImGuiDir_None }, + { "0.1 Z+", { 0, 0, 0.1f }, ImGuiDir::ImGuiDir_None }, + { "0.1 Z-", { 0, 0, -0.1f }, ImGuiDir::ImGuiDir_None }, + }; + + if (ImGui::SmallButton("Set position from cursor")) { + changed = true; + set = true; + } + auto buttonGroup = [&](struct OffsetButton *button, int count) { + int i; + for (i = 0; i < count; i++) { + if (i > 0) + ImGui::SameLine(); + if (button[i].direction != + ImGuiDir::ImGuiDir_None) { + if (ImGui::ArrowButton( + button[i].label.c_str(), + button[i].direction)) { + offsetVal = button[i].offset; + offset = true; + changed = true; + } + } else { + if (ImGui::SmallButton( + button[i].label.c_str())) { + offsetVal = button[i].offset; + offset = true; + changed = true; + } + } + } + }; + buttonGroup(buttons_large, + sizeof(buttons_large) / sizeof(buttons_large[0])); + buttonGroup(buttons_small, + sizeof(buttons_small) / sizeof(buttons_small[0])); + if (changed) { + Ogre::Vector3 position = + item.first.get().position; + Ogre::Quaternion orientation = + item.first.get().orientation; + if (set) { + position = ECS::get() + .sceneNode + ->_getDerivedPosition(); + orientation = + ECS::get() + .sceneNode + ->_getDerivedOrientation(); + } else if (offset) + position += offsetVal; + item.first.get_mut().position = position; + item.first.get_mut().orientation = + orientation; + item.first.modified(); + StaticGeometryModule::saveItems(); + StaticGeometryModule::destroyItemGeometry(item.first); + StaticGeometryModule::createItemGeometry(item.first); + } if (itemType == "harbour") createHarbourPopup(item); else if (itemType == "temple") @@ -82,8 +169,9 @@ void createItemsMenu() if (ImGui::BeginMenu("Town")) { Items::createTownMenu(); ImGui::EndMenu(); - } + } } + } namespace Geometry { @@ -220,4 +308,4 @@ flecs::entity createMeshGeometry(const Ogre::String &meshName, } } -} \ No newline at end of file +} diff --git a/src/gamedata/items/items.h b/src/gamedata/items/items.h index 44e6d1d..ad65087 100644 --- a/src/gamedata/items/items.h +++ b/src/gamedata/items/items.h @@ -86,4 +86,4 @@ static void from_json(const nlohmann::json &j, Ogre::Quaternion &orientation) orientation.z = j["z"].get(); } } -#endif \ No newline at end of file +#endif diff --git a/src/gamedata/items/town.cpp b/src/gamedata/items/town.cpp index 053d494..fc657f9 100644 --- a/src/gamedata/items/town.cpp +++ b/src/gamedata/items/town.cpp @@ -1,5 +1,8 @@ #include #include +#include +#include +#include #include #include #include @@ -12,12 +15,77 @@ #include "StaticGeometryModule.h" #include "physics.h" #include "PhysicsModule.h" +#include "LuaData.h" #include "items.h" #include "town.h" + +void serializeMesh(Ogre::MeshPtr mesh, const Ogre::String &meshName) +{ + Ogre::MeshSerializer meshSerializer; + + meshSerializer.exportMesh(mesh, meshName, + Ogre::Serializer::ENDIAN_NATIVE); +} namespace ECS { namespace Items { +int64_t makeCellKey(int kx, int ky, int kz) +{ + int64_t key = + (int64_t)kx + 1024 * (int64_t)ky + 1024 * 1024 * (int64_t)kz; + return key; +} +int64_t makeCellKey(const nlohmann::json &cell) +{ + int64_t kx = cell["x"].get(); + int64_t ky = cell["y"].get(); + int64_t kz = cell["z"].get(); + int64_t key = makeCellKey(kx, ky, kz); + return key; +}; +void displayGrid(flecs::entity e, nlohmann::json &lot, int index, + Ogre::SceneNode *sceneNode, const Ogre::Vector3 &localPosition, + const Ogre::Quaternion &localRotation) +{ + if (lot.find("edited") == lot.end()) { + lot["edited"] = true; + int width = lot["width"].get(); + int height = lot["height"].get(); + Ogre::Vector3 worldPosition = + sceneNode->_getDerivedPosition() + localPosition; + Ogre::Quaternion worldRotation = + sceneNode->_getDerivedOrientation() * localRotation; + Ogre::Vector3 origin = worldPosition + + worldRotation * Ogre::Vector3::UNIT_X * + 4.0f * (-width / 2) + + worldRotation * Ogre::Vector3::UNIT_Z * + 4.0f * (-height / 2); + Ogre::ManualObject *mobj = + ECS::get().mScnMgr->createManualObject( + "lot" + + Ogre::StringConverter::toString(e.id()) + "_" + + Ogre::StringConverter::toString(index)); + mobj->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY); + mobj->begin(ECS::get().material, + Ogre::RenderOperation::OT_LINE_LIST); + mobj->setBufferUsage(Ogre::HardwareBufferUsage::HBU_GPU_ONLY); + int i, j; + for (j = 0; j < width; j++) { + Ogre::Vector3 d1 = worldRotation * + Ogre::Vector3::UNIT_X * 4.0f * j; + Ogre::Vector3 d2 = worldRotation * + Ogre::Vector3::UNIT_Z * 4.0f * + height; + mobj->position(origin + d1); + mobj->colour(Ogre::ColourValue(0, 1, 1, 1)); + mobj->position(origin + d1 + d2); + mobj->colour(Ogre::ColourValue(0, 1, 1, 1)); + } + mobj->end(); + sceneNode->attachObject(mobj); + } +} void createTownItem() { Ogre::Vector3 itemPosition = @@ -37,6 +105,670 @@ void createTownMenu() if (ImGui::MenuItem("Create")) createTownItem(); } +bool editCell(const Ogre::String &cellLabel, nlohmann::json &cell) +{ + bool changed = false; + auto checkboxBit = [cellLabel, &changed](Ogre::String label, + nlohmann::json &cell, + uint64_t bit) { + uint64_t flags = cell["flags"].get(); + bool status = (flags & bit) == bit; + if (ImGui::Checkbox((label + "##" + cellLabel).c_str(), + &status)) { + if (status) + flags |= bit; + else + flags &= ~bit; + cell["flags"] = flags; + changed = true; + } + }; + checkboxBit("Floor", cell, (1ULL << 0)); + checkboxBit("Ceiling", cell, (1ULL << 1)); + checkboxBit("Ext Wall X-", cell, (1ULL << 2)); + checkboxBit("Ext Wall X+", cell, (1ULL << 3)); + checkboxBit("Ext Wall Z+", cell, (1ULL << 4)); + checkboxBit("Ext Wall Z-", cell, (1ULL << 5)); + checkboxBit("Ext Door X-", cell, (1ULL << 6)); + checkboxBit("Ext Door X+", cell, (1ULL << 7)); + checkboxBit("Ext Door Z+", cell, (1ULL << 8)); + checkboxBit("Ext Door Z-", cell, (1ULL << 9)); + checkboxBit("Ext Window X-", cell, (1ULL << 10)); + checkboxBit("Ext Window X+", cell, (1ULL << 11)); + checkboxBit("Ext Window Z+", cell, (1ULL << 12)); + checkboxBit("Ext Window Z-", cell, (1ULL << 13)); + checkboxBit("Int Wall X-", cell, (1ULL << 14)); + checkboxBit("Int Wall X+", cell, (1ULL << 15)); + checkboxBit("Int Wall Z+", cell, (1ULL << 16)); + checkboxBit("Int Wall Z-", cell, (1ULL << 17)); + checkboxBit("Int Door X-", cell, (1ULL << 18)); + checkboxBit("Int Door X+", cell, (1ULL << 19)); + checkboxBit("Int Door Z+", cell, (1ULL << 20)); + checkboxBit("Int Door Z-", cell, (1ULL << 21)); + checkboxBit("Int Window X-", cell, (1ULL << 22)); + checkboxBit("Int Window X+", cell, (1ULL << 23)); + checkboxBit("Int Window Z+", cell, (1ULL << 24)); + checkboxBit("Int Window Z-", cell, (1ULL << 25)); + return changed; +} + +struct CellsScript { + struct room { + int minX; + int minZ; + int sizeX; + int sizeZ; + }; + std::vector rooms; + lua_State *L; + int currentX; + int currentY; + int currentZ; + Ogre::String cellScript; + nlohmann::json &cells; + CellsScript(const Ogre::String &cellScript, nlohmann::json &cells) + : L(luaL_newstate()) + , currentX(0) + , currentY(0) + , currentZ(0) + , cellScript(cellScript) + , cells(cells) + { + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + int pX = lua_tointeger(L, 1); + int pY = lua_tointeger(L, 2); + int pZ = lua_tointeger(L, 3); + _this->currentX = pX; + _this->currentY = pY; + _this->currentZ = pZ; + return 0; + }, + 1); + lua_setglobal(L, "pos"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + int pX = lua_tointeger(L, 1); + int pY = lua_tointeger(L, 2); + int pZ = lua_tointeger(L, 3); + _this->currentX += pX; + _this->currentY += pY; + _this->currentZ += pZ; + return 0; + }, + 1); + lua_setglobal(L, "go"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + _this->cell(0); + return 0; + }, + 1); + lua_setglobal(L, "cell"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + Ogre::String cmd = lua_tostring(L, 1); + Ogre::String bit = lua_tostring(L, 2); + _this->bitCmd(cmd, bit); + return 0; + }, + 1); + lua_setglobal(L, "bit"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + int minX = lua_tointeger(L, 1); + int minZ = lua_tointeger(L, 2); + int sizeX = lua_tointeger(L, 3); + int sizeZ = lua_tointeger(L, 4); + int r = _this->room(minX, minZ, sizeX, sizeZ); + std::cout << "room: " << r << std::endl; + lua_pushinteger(L, r); + return 1; + }, + 1); + lua_setglobal(L, "room"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + int minX = lua_tointeger(L, 1); + int minZ = lua_tointeger(L, 2); + int sizeX = lua_tointeger(L, 3); + int sizeZ = lua_tointeger(L, 4); + _this->clear_area(minX, minZ, sizeX, sizeZ); + return 0; + }, + 1); + lua_setglobal(L, "clear_area"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + int r1 = lua_tointeger(L, 1); + int r2 = lua_tointeger(L, 2); + _this->connect_rooms(r1, r2); + std::cout << "connect rooms: " << r1 << " " + << r2 << std::endl; + return 0; + }, + 1); + lua_setglobal(L, "connect_rooms"); + } + std::string trim(const std::string &str) + { + // Find the first character that is not a whitespace character + const std::string ws = + " \t\n\r\f\v"; // Common whitespace characters + size_t first = str.find_first_not_of(ws); + + // If all characters are whitespace (or string is empty), return an empty string + if (std::string::npos == first) { + return ""; + } + + // Find the last character that is not a whitespace character + size_t last = str.find_last_not_of(ws); + + // Extract the substring between the first and last non-whitespace characters + return str.substr(first, (last - first + 1)); + } + std::vector split_and_trim(const std::string &s, + char delimiter) + { + std::vector tokens; + std::string token; + std::stringstream ss(s); // Use stringstream to parse the string + + // Use getline to extract each token based on the delimiter + while (std::getline(ss, token, delimiter)) { + // Trim whitespace from the extracted token + std::string trimmed_token = trim(token); + // Add the trimmed token to the vector (optional: skip empty strings) + if (!trimmed_token.empty()) { + tokens.push_back(trimmed_token); + } + } + return tokens; + } + void buildCellIndex() + { + for (auto &cell : cells) + cell["id"] = makeCellKey(cell); + } + int findCell(int X, int Y, int Z) + { + int64_t key = makeCellKey(X, Y, Z); + int result = -1; + int i; + for (i = 0; i < cells.size(); i++) { + int64_t ckey = makeCellKey(cells[i]); + if (key == ckey) { + result = i; + break; + } + } + return result; + } + void bitCmd(const Ogre::String &cmd, const Ogre::String &bit) + { + uint64_t flags = 0; + std::vector bitconv = { + "floor", "ceiling", "wallx-", "wallx+", + "wallz+", "wallz-", "doorx-", "doorx+", + "doorz+", "doorz-", "windowx-", "windowx+", + "windowz+", "windowz-", "iwallx-", "iwallx+", + "iwallz+", "iwallz-", "idoorx-", "idoorx+", + "idoorz+", "idoorz-", "iwindowx-", "iwindowx+", + "iwindowz+", "iwindowz-" + }; + std::vector bits = split_and_trim(bit, ','); + bool cmdSet = cmd == "set"; + bool cmdClear = cmd == "clear"; + int cellIndex = findCell(currentX, currentY, currentZ); + if (cellIndex >= 0) + flags = cells[cellIndex]["flags"].get(); + for (auto &sbit : bits) { + auto loc = + std::find(bitconv.begin(), bitconv.end(), sbit); + if (loc != bitconv.end()) { + int index = std::distance(bitconv.begin(), loc); + if (cmdSet) + flags |= (1 << (uint64_t)index); + if (cmdClear) + flags &= ~(1 << (uint64_t)index); + } + } + cell(flags); + } + void cell(uint64_t flags) + { + if (findCell(currentX, currentY, currentZ) == -1) { + nlohmann::json cell; + buildCellIndex(); + cell["x"] = currentX; + cell["y"] = currentY; + cell["z"] = currentZ; + cell["flags"] = flags; + cell["id"] = makeCellKey(cell); + cells.push_back(cell); + } else { + int index = findCell(currentX, currentY, currentZ); + if (index >= 0) + cells[index]["flags"] = flags; + } + } + void clear() + { + int index = findCell(currentX, currentY, currentZ); + if (index >= 0) + cells.erase(index); + } + void clear_area(int minX, int minZ, int sizeX, int sizeZ) + { + int i, j; + for (i = 0; i < sizeZ; i++) + for (j = 0; j < sizeX; j++) { + currentX = minX + j; + currentZ = minZ + i; + clear(); + } + } + int room(int minX, int minZ, int sizeX, int sizeZ) + { + int i, j, ret; + clear_area(minX, minZ, sizeX, sizeZ); + for (i = 0; i < sizeZ; i++) + for (j = 0; j < sizeX; j++) { + currentX = minX + j; + currentZ = minZ + i; + bitCmd("set", "floor,ceiling"); + } + for (i = 0; i < sizeX; i++) { + currentX = minX + i; + currentZ = minZ; + bitCmd("set", "iwallz-"); + } + for (i = 0; i < sizeX; i++) { + currentX = minX + i; + currentZ = minZ + sizeZ - 1; + bitCmd("set", "iwallz+"); + } + for (i = 0; i < sizeZ; i++) { + currentX = minX; + currentZ = minZ + i; + bitCmd("set", "iwallx-"); + } + for (i = 0; i < sizeZ; i++) { + currentX = minX + sizeX - 1; + currentZ = minZ + i; + bitCmd("set", "iwallx+"); + } + ret = rooms.size(); + rooms.push_back({ minX, minZ, sizeX, sizeZ }); + return ret; + } + std::vector > roomEdge(int room) + { + std::vector > seg; + int i; + for (i = 0; i < rooms[room].sizeX; i++) { + seg.push_back( + { rooms[room].minX + i, rooms[room].minZ }); + seg.push_back( + { rooms[room].minX + i, + rooms[room].minZ + rooms[room].sizeZ - 1 }); + } + for (i = 0; i < rooms[room].sizeZ; i++) { + seg.push_back( + { rooms[room].minX, rooms[room].minZ + i }); + seg.push_back( + { rooms[room].minX + rooms[room].sizeZ - 1, + rooms[room].minZ + i }); + } + return seg; + } + bool adjacent(std::pair c1, std::pair c2) + { + int dx = std::abs(c1.first - c2.first); + int dz = std::abs(c1.second - c2.second); + return (dx == 0 && dz == 1) || (dx == 1 && dz == 0); + } + std::vector > adjacentCells(int room, int other) + { + std::vector > room_seg = roomEdge(room); + std::vector > other_seg = roomEdge(other); + std::vector > ret; + for (auto &cell : room_seg) + for (auto &ocell : other_seg) { + if (adjacent(cell, ocell)) + ret.push_back(cell); + } + return ret; + } + void connect_rooms(int r1, int r2) + { + std::vector > seg1 = adjacentCells(r1, r2), + seg2 = adjacentCells(r2, r1); + for (auto &cell : seg1) { + std::cout << "seg1: " << cell.first << " " + << cell.second << std::endl; + } + for (auto &cell : seg2) { + std::cout << "seg2: " << cell.first << " " + << cell.second << std::endl; + } + int sumX = 0, sumZ = 0; + int sumOX = 0, sumOZ = 0; + int count = 0; + for (auto &cell : seg1) { + sumX += cell.first; + sumZ += cell.second; + count++; + } + if (count == 0) + return; + sumX /= count; + sumZ /= count; + count = 0; + for (auto &cell : seg2) { + sumOX += cell.first; + sumOZ += cell.second; + count++; + } + if (count == 0) + return; + sumOX /= count; + sumOZ /= count; + int dx = sumX - sumOX; + int dz = sumZ - sumOZ; + std::cout << dx << " " << dz << std::endl; + OgreAssert(std::abs(dx) == 1 && dz == 0 || + dx == 0 && std::abs(dz) == 1, + "shit happens"); + if (dz < 0) { + currentX = sumX; + currentZ = sumZ; + bitCmd("clear", "iwallz+"); + bitCmd("set", "idoorz+"); + currentX = sumOX; + currentZ = sumOZ; + bitCmd("clear", "iwallz-"); + bitCmd("set", "idoorz-"); + } + if (dz > 0) { + currentX = sumX; + currentZ = sumZ; + bitCmd("clear", "iwallz-"); + bitCmd("set", "idoorz-"); + currentX = sumOX; + currentZ = sumOZ; + bitCmd("clear", "iwallz+"); + bitCmd("set", "idoorz+"); + } + if (dx < 0) { + currentX = sumX; + currentZ = sumZ; + bitCmd("clear", "iwallx+"); + bitCmd("set", "idoorx+"); + currentX = sumOX; + currentZ = sumOZ; + bitCmd("clear", "iwallx-"); + bitCmd("set", "idoorx-"); + } + if (dx > 0) { + currentX = sumX; + currentZ = sumZ; + bitCmd("clear", "iwallx-"); + bitCmd("set", "idoorx-"); + currentX = sumOX; + currentZ = sumOZ; + bitCmd("clear", "iwallx+"); + bitCmd("set", "idoorx+"); + } + int cell1 = findCell(sumX, currentY, sumZ); + int cell2 = findCell(sumOX, currentY, sumOZ); + std::cout << sumX << " " << sumZ << "..." << sumOX << " " + << sumOZ << std::endl; + std::cout << dx << " " << dz << " " << cell1 << " " << cell2 + << std::endl; + // OgreAssert(false, "eeeeeh"); + // OgreAssert(false, "eeeeeh"); + } + virtual ~CellsScript() + { + lua_close(L); + } + void run() + { + int result = luaL_dostring(L, cellScript.c_str()); + if (result != LUA_OK) { + std::cerr << "Lua script execution failed: " + << lua_tostring(L, -1) << std::endl; + lua_pop(L, 1); + } else + std::cout << "Running script OK" << std::endl; + } +}; +bool editLot(const Ogre::String &lotLabel, nlohmann::json &lot) +{ + bool changed = false; + float angle = lot["angle"].get(); + if (ImGui::SliderFloat(("Lot Angle##" + lotLabel).c_str(), &angle, + -180.0f, 180.0f)) { + lot["angle"] = angle; + changed = true; + } + float elevation = lot["elevation"].get(); + if (ImGui::SliderFloat(("Lot Elevation##" + lotLabel).c_str(), + &elevation, -10.0f, 10.0f)) { + lot["elevation"] = elevation; + changed = true; + } + int width = lot["width"].get(); + if (ImGui::SliderInt(("Lot Width##" + lotLabel).c_str(), &width, 4, + 50)) { + lot["width"] = width; + changed = true; + } + int depth = lot["depth"].get(); + if (ImGui::SliderInt(("Lot Depth##" + lotLabel).c_str(), &depth, 4, + 50)) { + lot["depth"] = depth; + changed = true; + } + nlohmann::json cells = nlohmann::json::array(); + static char text_buffer[16384]; + strcpy(text_buffer, ""); + if (lot.find("cellScript") != lot.end()) { + Ogre::String script = lot["cellScript"].get(); + strncpy(text_buffer, script.c_str(), sizeof(text_buffer)); + } + if (ImGui::InputTextMultiline(("Cells Script##" + lotLabel).c_str(), + text_buffer, IM_ARRAYSIZE(text_buffer), + ImVec2(1000, + ImGui::GetTextLineHeight() * 20), + ImGuiInputTextFlags_AllowTabInput)) { + lot["cellScript"] = Ogre::String(text_buffer); + changed = true; + } + if (ImGui::SmallButton(("Execute script...##" + lotLabel).c_str())) { + CellsScript script(lot["cellScript"].get(), + lot["cells"]); + script.run(); + changed = true; + } + for (const auto &cell : lot["cells"]) + cells.push_back(cell); + if (cells.size() == 0) { + Ogre::String createCellsLabel = "Create cells...##" + lotLabel; + if (ImGui::SmallButton(createCellsLabel.c_str())) { + nlohmann::json cell; + cell["x"] = 0; + cell["y"] = 0; + cell["z"] = 0; + cell["flags"] = 0U; + cell["id"] = makeCellKey(cell); + lot["cells"].push_back(cell); + changed = true; + } + } else { + int cellCount = 0; + for (auto &cell : cells) { + Ogre::String cellLabel = + lotLabel + "cell" + + Ogre::StringConverter::toString(cellCount); + ImGui::Text("x = %d", cell["x"].get()); + ImGui::Text("y = %d", cell["y"].get()); + ImGui::Text("z = %d", cell["z"].get()); + ImGui::Text("flags = %016lx", + cell["flags"].get()); + changed = changed || editCell(cellLabel, cell); + ImGui::Separator(); + auto makeCreateButton = [&](const Ogre::String &label, + int offsetX, int offsetY, + int offsetZ) { + if (ImGui::SmallButton(label.c_str())) { + int currentX = cell["x"].get(); + int currentY = cell["y"].get(); + int currentZ = cell["z"].get(); + nlohmann::json newcell; + newcell["x"] = currentX + offsetX; + newcell["y"] = currentY + offsetY; + newcell["z"] = currentZ + offsetZ; + newcell["flags"] = 0U; + bool ok = true; + for (const auto &chk : cells) { + int64_t main_key = + makeCellKey(newcell); + int64_t chk_key = + makeCellKey(chk); + if (main_key == chk_key) { + ok = false; + break; + } + } + if (ok) { + newcell["id"] = + makeCellKey(newcell); + cells.push_back(newcell); + changed = true; + } + } + }; + struct CreateButtons { + Ogre::String label; + int x, y, z; + }; + struct CreateButtons cbuttons[] = { + { "NewX+##" + cellLabel, 1, 0, 0 }, + { "NewX-##" + cellLabel, -1, 0, 0 }, + { "NewY+##" + cellLabel, 0, 1, 0 }, + { "NewY-##" + cellLabel, 0, -1, 0 }, + { "NewZ+##" + cellLabel, 0, 0, 1 }, + { "NewZ-##" + cellLabel, 0, 0, -1 }, + }; + int i; + for (i = 0; i < sizeof(cbuttons) / sizeof(cbuttons[0]); + i++) { + if (i > 0) + ImGui::SameLine(); + makeCreateButton(cbuttons[i].label, + cbuttons[i].x, cbuttons[i].y, + cbuttons[i].z); + } + Ogre::String cellDeleteLabel = "Delete##" + cellLabel; + + if (ImGui::SmallButton(cellDeleteLabel.c_str())) { + cells.erase(cellCount); + changed = true; + } + if (changed) { + lot["cells"] = cells; + break; + } + cellCount++; + } + } + return changed; +} +bool editDistrict(const Ogre::String &districtLabel, nlohmann::json &district) +{ + bool changed = false; + nlohmann::json lots = nlohmann::json::array(); + for (const auto &lot : district["lots"]) + lots.push_back(lot); + int lotCount = 0; + for (auto &lot : lots) { + Ogre::String lotLabel = + districtLabel + "_lot" + + Ogre::StringConverter::toString(lotCount); + ImGui::Text("%s", lotLabel.c_str()); + changed = changed || editLot(lotLabel, lot); + ImGui::Separator(); + if (ImGui::SmallButton(("Lot Delete##" + lotLabel).c_str())) { + lots.erase(lotCount); + break; + } + lotCount++; + } + ImGui::Separator(); + if (ImGui::SmallButton("Add lot")) { + nlohmann::json l; + l["angle"] = 0.0f; + l["width"] = 10; + l["depth"] = 10; + l["elevation"] = 0.0f; + l["objects"] = nlohmann::json::array(); + lots.push_back(l); + changed = true; + } + district["lots"] = lots; + bool plazza = false; + if (district.find("plazza") != district.end()) + plazza = district["plazza"].get(); + if (ImGui::Checkbox("Plazza", &plazza)) { + changed = true; + district["plazza"] = plazza; + } + float elevation = 0.0f, height = 0.2f; + if (district.find("elevation") != district.end()) + elevation = district["elevation"].get(); + if (district.find("height") != district.end()) + height = district["height"].get(); + if (ImGui::SliderFloat("Height", &height, 0.1f, 10.0f)) { + district["height"] = height; + changed = true; + } + if (ImGui::SliderFloat("Elevation", &elevation, -10.0f, 10.0f)) { + district["elevation"] = elevation; + changed = true; + } + return changed; +} void createTownPopup(const std::pair item) { Ogre::String prop = StaticGeometryModule::getItemProperties(item.first); @@ -53,65 +785,18 @@ void createTownPopup(const std::pair item) districts.push_back(district); count = 0; for (auto &district : districts) { - ImGui::Separator(); - Ogre::String districtLabel = - "district" + Ogre::StringConverter::toString(count); - ImGui::Text("%s", districtLabel.c_str()); - nlohmann::json lots = nlohmann::json::array(); - for (const auto &lot : district["lots"]) - lots.push_back(lot); - int lotCount = 0; - for (auto &lot : lots) { - Ogre::String lotLabel = - "lot" + - Ogre::StringConverter::toString(lotCount); - ImGui::Text("%s", lotLabel.c_str()); - ImGui::Separator(); - if (ImGui::SmallButton("Delete")) { - lots.erase(lotCount); - break; - } - lotCount++; - } - ImGui::Separator(); - if (ImGui::SmallButton("Add lot")) { - nlohmann::json l; - l["angle"] = 0.0f; - l["width"] = 10.0f; - l["depth"] = 10.0f; - l["elevation"] = 0.0f; - lots.push_back(l); - changed = true; - } - district["lots"] = lots; - bool plazza = false; - if (district.find("plazza") != district.end()) - plazza = district["plazza"].get(); - if (ImGui::Checkbox("Plazza", &plazza)) { - changed = true; - district["plazza"] = plazza; - } - float elevation = 0.0f, height = 0.2f; - if (district.find("elevation") != district.end()) - elevation = district["elevation"].get(); - if (district.find("height") != district.end()) - height = district["height"].get(); - if (ImGui::SliderFloat("Height", &height, 0.1f, 10.0f)) { - district["height"] = height; - changed = true; - } - if (ImGui::SliderFloat("Elevation", &elevation, -10.0f, - 10.0f)) { - district["elevation"] = elevation; - changed = true; - } - ImGui::Separator(); - if (ImGui::SmallButton("Delete")) { - districts.erase(count); - changed = true; - break; - } - count++; + ImGui::Separator(); + Ogre::String districtLabel = + "district" + Ogre::StringConverter::toString(count); + ImGui::Text("%s", districtLabel.c_str()); + changed = changed || editDistrict(districtLabel, district); + ImGui::Separator(); + if (ImGui::SmallButton("Delete")) { + districts.erase(count); + changed = true; + break; + } + count++; } ImGui::Separator(); if (ImGui::SmallButton("Add district")) { @@ -160,7 +845,11 @@ void createTown(flecs::entity e, Ogre::SceneNode *sceneNode, Ogre::ColourValue normalYellow(0.8f, 0.6f, 0, 1); Ogre::ColourValue roadBrown(0.4f, 0.3f, 0.3f, 1); Ogre::ColourValue bollardGrey(0.2f, 0.2f, 0.2f, 1); - drawAtlas.setRectangle(Ogre::RealRect(0.0f, 0.0f, 0.4f, 1.0f)) + Ogre::ColourValue floorRed(0.5f, 0.2f, 0.2f, 1); + Ogre::ColourValue ceilingWhite(0.8f, 0.8f, 0.85f, 1); + Ogre::ColourValue wallYellow(0.8f, 0.6f, 0, 1); + Ogre::ColourValue intwallBlue(0.6f, 0.6f, 0.8f, 1); + drawAtlas.setRectangle(Ogre::RealRect(0.0f, 0.0f, 0.4f, 1.0f)) .setColour(normalYellow) .process(); drawAtlas.setRectangle(Ogre::RealRect(0.2f, 0.0f, 0.3f, 1.0f)) @@ -169,7 +858,19 @@ void createTown(flecs::entity e, Ogre::SceneNode *sceneNode, drawAtlas.setRectangle(Ogre::RealRect(0.4f, 0.0f, 1.0f, 1.0f)) .setColour(roadBrown) .process(); - Ogre::TexturePtr pierTexture = colorAtlas.createTexture( + drawAtlas.setRectangle(Ogre::RealRect(0.5f, 0.0f, 0.6f, 0.1f)) + .setColour(floorRed) + .process(); + drawAtlas.setRectangle(Ogre::RealRect(0.6f, 0.0f, 0.7f, 0.1f)) + .setColour(ceilingWhite) + .process(); + drawAtlas.setRectangle(Ogre::RealRect(0.7f, 0.0f, 0.8f, 0.1f)) + .setColour(wallYellow) + .process(); + drawAtlas.setRectangle(Ogre::RealRect(0.8f, 0.0f, 0.9f, 0.1f)) + .setColour(intwallBlue) + .process(); + Ogre::TexturePtr pierTexture = colorAtlas.createTexture( "proceduralTextureTown" + Ogre::StringConverter::toString(e.id())); colorAtlas.saveImage("tmp4.png"); @@ -210,14 +911,19 @@ void createTown(flecs::entity e, Ogre::SceneNode *sceneNode, Ogre::Vector3 worldPosition = sceneNode->_getDerivedPosition(); Ogre::Quaternion worldOrientation = sceneNode->_getDerivedOrientation(); + int index = 0; for (const auto &jdistrict : jp["districts"]) { - createTownPlazza(e, jdistrict, sceneNode, geo); - } + createTownPlazza(e, jdistrict, index, sceneNode, geo); + createTownLots(e, jdistrict, index, sceneNode, geo); + createCells(e, jdistrict, index, sceneNode, geo); + index++; + } } geo->build(); } void createTownPlazza(flecs::entity e, const nlohmann::json &jdistrict, - Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo) + int index, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo) { Ogre::MaterialPtr townMaterial; townMaterial = Ogre::MaterialManager::getSingleton().getByName( @@ -275,8 +981,9 @@ void createTownPlazza(flecs::entity e, const nlohmann::json &jdistrict, v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.4f, 0.5f); v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); } - Ogre::String meshName = - "plazzaMesh" + Ogre::StringConverter::toString(e.id()); + Ogre::String meshName = "plazzaMesh" + + Ogre::StringConverter::toString(index) + "_" + + Ogre::StringConverter::toString(e.id()); Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().getByName(meshName); if (mesh) @@ -289,7 +996,853 @@ void createTownPlazza(flecs::entity e, const nlohmann::json &jdistrict, pathEnt->setMaterial(townMaterial); geo->addEntity(pathEnt, worldPlazzaCenter, worldOrientation * localRotation, - Ogre::Vector3(1, 1, 1)); + Ogre::Vector3(1, 1, 1)); +} +struct BitSet { + uint64_t bit; + float sizeX; + float sizeY; + Ogre::Vector3 normal, offset; + Procedural::TriangleBuffer *tb; +}; + +struct ProcessCells { + const float cellHeight = 4.0f; + const float cornerWidth = 0.2f; + Procedural::TriangleBuffer floortb; + Procedural::TriangleBuffer ceilingtb; + Procedural::TriangleBuffer extwalltb; + Procedural::TriangleBuffer intwalltb; + std::vector bits_ext_corners; + std::vector bits_solid; + std::vector bits_doors; + std::vector bits_windows; + std::vector bits_int_corners1; + std::vector bits_int_corners2; + ProcessCells() + { + bits_ext_corners = { + { 4 | 16, // external wall + 4.0f, + 0.2f, + Ogre::Vector3::NEGATIVE_UNIT_X, + { -1.0 - 0.2f, 2.0f, 1.0f + 0.1f }, + &extwalltb }, + { 4 | 16, // external wall + 4.0f, + 0.2f, + Ogre::Vector3::UNIT_Z, + { -1.0 - 0.1f, 2.0f, 1.0f + 0.2f }, + &extwalltb }, + { 4 | 32, // external wall + 4.0f, + 0.2f, + Ogre::Vector3::NEGATIVE_UNIT_X, + { -1.0 - 0.2f, 2.0f, -1.0f - 0.1f }, + &extwalltb }, + { 4 | 32, // external wall + 4.0f, + 0.2f, + Ogre::Vector3::NEGATIVE_UNIT_Z, + { -1.0 - 0.1f, 2.0f, -1.0f - 0.2f }, + &extwalltb }, + { 8 | 16, // external wall + 4.0f, + 0.2f, + Ogre::Vector3::UNIT_X, + { 1.0f + 0.2f, 2.0f, 1.0f + 0.1f }, + &extwalltb }, + { 8 | 16, // external wall + 4.0f, + 0.2f, + Ogre::Vector3::UNIT_Z, + { 1.0f + 0.1f, 2.0f, 1.0f + 0.2f }, + &extwalltb }, + { 8 | 32, // external wall + 4.0f, + 0.2f, + Ogre::Vector3::UNIT_X, + { 1.0f + 0.2f, 2.0f, -1.0f - 0.1f }, + &extwalltb }, + { 8 | 32, // external wall + 4.0f, + 0.2f, + Ogre::Vector3::NEGATIVE_UNIT_Z, + { 1.0f + 0.1f, 2.0f, -1.0f - 0.2f }, + &extwalltb }, + }; + float solidCellHeight = 4.0f; + float solidExtOffset = 0.0f; + float solidExtHeight = solidCellHeight - solidExtOffset; + float solidIntOffset = 0.1f; + float solidIntHeight = solidCellHeight - 0.3f - solidExtOffset; + + bits_solid = { + { 1ULL << 0, // floor + 2.0f, + 2.0f, + Ogre::Vector3::UNIT_Y, + { 0, 0.1f, 0 }, + &floortb }, + { 1ULL << 1, // ceiling + 2.0f, + 2.0f, + Ogre::Vector3::NEGATIVE_UNIT_Y, + { 0, 3.7f, 0 }, + &ceilingtb }, + { 1ULL << 2, // external wall + solidExtHeight, + 2.0f, + Ogre::Vector3::NEGATIVE_UNIT_X, + { -1.0 - 0.2f, solidExtHeight / 2.0f + solidExtOffset, + 0 }, + &extwalltb }, + { 1ULL << 3, // external wall + solidExtHeight, + 2.0f, + Ogre::Vector3::UNIT_X, + { 1.0 + 0.2f, solidExtHeight / 2.0f + solidExtOffset, + 0 }, + &extwalltb }, + { 1ULL << 4, // external wall + solidExtHeight, + 2.0f, + Ogre::Vector3::UNIT_Z, + { 0, solidExtHeight / 2.0f + solidExtOffset, + 1.0f + 0.2f }, + &extwalltb }, + { 1ULL << 5, // external wall + solidExtHeight, + 2.0f, + Ogre::Vector3::NEGATIVE_UNIT_Z, + { 0, solidExtHeight / 2.0f + solidExtOffset, + -1.0f - 0.2f }, + &extwalltb }, + { 1ULL << 14, // internal wall + solidIntHeight, + 1.8f, + Ogre::Vector3::UNIT_X, + { -1.0 + 0.1f, solidIntHeight / 2.0f + solidIntOffset, + 0 }, + &intwalltb }, + { 1ULL << 15, // internal wall + solidIntHeight, + 1.8f, + Ogre::Vector3::NEGATIVE_UNIT_X, + { 1.0 - 0.1f, solidIntHeight / 2.0f + solidIntOffset, + 0 }, + &intwalltb }, + { 1ULL << 16, // internal wall + solidIntHeight, + 1.8f, + Ogre::Vector3::NEGATIVE_UNIT_Z, + { 0, solidIntHeight / 2.0f + solidIntOffset, + 1.0f - 0.1f }, + &intwalltb }, + { 1ULL << 17, // internal wall + solidIntHeight, + 1.8f, + Ogre::Vector3::UNIT_Z, + { 0, solidIntHeight / 2.0f + solidIntOffset, + -1.0f + 0.1f }, + &intwalltb }, + }; + bits_int_corners1 = { + { 1ULL << 14, // internal wall corner + solidIntHeight, + 0.1f, + Ogre::Vector3::UNIT_X, + { -1.0f + 0.1f, + solidIntHeight / 2.0f + solidIntOffset, + (1.8f + 0.1f) / 2.0f }, + &intwalltb }, + { 1ULL << 15, // internal wall + solidIntHeight, + 0.1f, + Ogre::Vector3::NEGATIVE_UNIT_X, + { 1.0 - 0.1f, solidIntHeight / 2.0f + solidIntOffset, + (1.8f + 0.1f) / 2.0f }, + &intwalltb }, + { 1ULL << 16, // internal wall + solidIntHeight, + 0.1f, + Ogre::Vector3::NEGATIVE_UNIT_Z, + { (1.8f + 0.1f) / 2.0f, + solidIntHeight / 2.0f + solidIntOffset, + 1.0f - 0.1f }, + &intwalltb }, + { 1ULL << 17, // internal wall + solidIntHeight, + 0.1f, + Ogre::Vector3::UNIT_Z, + { (1.8f + 0.1f) / 2.0f, + solidIntHeight / 2.0f + solidIntOffset, + -1.0f + 0.1f }, + &intwalltb }, + }; + bits_int_corners2 = { + { 1ULL << 14, // internal wall corner + solidIntHeight, + 0.1f, + Ogre::Vector3::UNIT_X, + { -1.0f + 0.1f, + solidIntHeight / 2.0f + solidIntOffset, + (-1.8f - 0.1f) / 2.0f }, + &intwalltb }, + { 1ULL << 15, // internal wall + solidIntHeight, + 0.1f, + Ogre::Vector3::NEGATIVE_UNIT_X, + { 1.0 - 0.1f, solidIntHeight / 2.0f + solidIntOffset, + -(1.8f + 0.1f) / 2.0f }, + &intwalltb }, + { 1ULL << 16, // internal wall + solidIntHeight, + 0.1f, + Ogre::Vector3::NEGATIVE_UNIT_Z, + { -(1.8f + 0.1f) / 2.0f, + solidIntHeight / 2.0f + solidIntOffset, + 1.0f - 0.1f }, + &intwalltb }, + { 1ULL << 17, // internal wall + solidIntHeight, + 0.1f, + Ogre::Vector3::UNIT_Z, + { -(1.8f + 0.1f) / 2.0f, + solidIntHeight / 2.0f + solidIntOffset, + -1.0f + 0.1f }, + &intwalltb }, + }; + struct BitSet doorbits[] = { + { 1ULL << 6, // external door + 3.0f, + 0.4f, + Ogre::Vector3::NEGATIVE_UNIT_X, + { -1.0 - 0.2f, 1.5f, 0 }, + &extwalltb }, + { 1ULL << 7, // external door + 3.0f, + 0.4f, + Ogre::Vector3::UNIT_X, + { 1.0 + 0.2f, 1.5f, 0 }, + &extwalltb }, + { 1ULL << 8, // external door + 3.0f, + 0.4f, + Ogre::Vector3::UNIT_Z, + { 0, 1.5f, 1.0f + 0.2f }, + &extwalltb }, + { 1ULL << 9, // external door + 3.0f, + 0.4f, + Ogre::Vector3::NEGATIVE_UNIT_Z, + { 0, 1.5f, -1.0f - 0.2f }, + &extwalltb }, + { 1ULL << 18, // internal door + 3.0f, + 0.4f, + Ogre::Vector3::UNIT_X, + { -1.0 + 0.1f, 1.5f, 0 }, + &intwalltb }, + { 1ULL << 19, // internal door + 3.0f, + 0.4f, + Ogre::Vector3::NEGATIVE_UNIT_X, + { 1.0 - 0.1f, 1.5f, 0 }, + &intwalltb }, + { 1ULL << 20, // internal door + 3.0f, + 0.4f, + Ogre::Vector3::NEGATIVE_UNIT_Z, + { 0, 1.5f, 1.0f - 0.1f }, + &intwalltb }, + { 1ULL << 21, // internal door + 3.0f, + 0.4f, + Ogre::Vector3::UNIT_Z, + { 0, 1.5f, -1.0f + 0.1f }, + &intwalltb }, + }; + // const float doorm = 0.8f; + const float doorWidth = 1.4f; + const float doorHeightBase = 3.0f; + float doorHeight = doorHeightBase - solidExtOffset; + float baseOffsetY = solidExtOffset; + float doorTopHeight = solidExtHeight - doorHeight; + for (const struct BitSet &bits : doorbits) { + float sideWidth = (2.0f - doorWidth) / 2.0f; + float moffset = (2.0f - sideWidth) / 2.0f; + if (bits.tb == &intwalltb) { + sideWidth = (1.8f - doorWidth) / 2.0f; + moffset = (1.8f - sideWidth) / 2.0f; + baseOffsetY = solidIntOffset; + doorHeight = doorHeightBase - solidIntOffset; + doorTopHeight = solidIntHeight - doorHeight; + } + if (bits.offset.x == 0.0f) { //z+ or z- + struct BitSet pbits = bits; + pbits.sizeY = sideWidth; + pbits.offset.x = -moffset; + pbits.offset.y = + baseOffsetY + doorHeight / 2.0f; + bits_doors.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.offset.x = moffset; + pbits.offset.y = + baseOffsetY + doorHeight / 2.0f; + bits_doors.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.offset.x = -moffset; + pbits.sizeX = doorTopHeight; + pbits.offset.y = baseOffsetY + doorHeight + + doorTopHeight / 2.0f; + bits_doors.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.offset.x = moffset; + pbits.sizeX = doorTopHeight; + pbits.offset.y = baseOffsetY + doorHeight + + doorTopHeight / 2.0f; + bits_doors.push_back(pbits); + pbits.offset.x = 0; + pbits.sizeX = doorTopHeight; + pbits.sizeY = doorWidth; + pbits.offset.y = baseOffsetY + doorHeight + + doorTopHeight / 2.0f; + bits_doors.push_back(pbits); + } else if (bits.offset.z == 0.0f) { + struct BitSet pbits = bits; + pbits.sizeY = sideWidth; + pbits.offset.z = -moffset; + pbits.offset.y = + baseOffsetY + doorHeight / 2.0f; + bits_doors.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.offset.z = moffset; + pbits.offset.y = + baseOffsetY + doorHeight / 2.0f; + bits_doors.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.offset.z = -moffset; + pbits.sizeX = doorTopHeight; + pbits.offset.y = baseOffsetY + doorHeight + + doorTopHeight / 2.0f; + bits_doors.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.offset.z = moffset; + pbits.sizeX = doorTopHeight; + pbits.offset.y = baseOffsetY + doorHeight + + doorTopHeight / 2.0f; + bits_doors.push_back(pbits); + pbits.offset.z = 0; + pbits.sizeX = doorTopHeight; + pbits.sizeY = doorWidth; + pbits.offset.y = baseOffsetY + doorHeight + + doorTopHeight / 2.0f; + bits_doors.push_back(pbits); + } + } + struct BitSet windowbits[] = { + { 1ULL << 10, // external window + 2.0f, + 0.2f, + Ogre::Vector3::NEGATIVE_UNIT_X, + { -1.0 - 0.2f, 1.5f, 0 }, + &extwalltb }, + { 1ULL << 11, // external window + 2.0f, + 0.2f, + Ogre::Vector3::UNIT_X, + { 1.0 + 0.2f, 1.5f, 0 }, + &extwalltb }, + { 1ULL << 12, // external window + 2.0f, + 0.2f, + Ogre::Vector3::UNIT_Z, + { 0, 1.5f, 1.0f + 0.2f }, + &extwalltb }, + { 1ULL << 13, // external window + 2.0f, + 0.2f, + Ogre::Vector3::NEGATIVE_UNIT_Z, + { 0, 1.5f, -1.0f - 0.2f }, + &extwalltb }, + { 1ULL << 22, // internal window + 2.0f, + 0.2f, + Ogre::Vector3::UNIT_X, + { -1.0 + 0.1f, 1.5f, 0 }, + &intwalltb }, + { 1ULL << 23, // internal window + 2.0f, + 0.2f, + Ogre::Vector3::NEGATIVE_UNIT_X, + { 1.0 - 0.1f, 1.5f, 0 }, + &intwalltb }, + { 1ULL << 24, // internal window + 2.0f, + 0.2f, + Ogre::Vector3::NEGATIVE_UNIT_Z, + { 0, 1.5f, 1.0f - 0.1f }, + &intwalltb }, + { 1ULL << 25, // internal window + 2.0f, + 0.2f, + Ogre::Vector3::UNIT_Z, + { 0, 1.5f, -1.0f + 0.1f }, + &intwalltb }, + }; + const float windowWidth = 1.6f; + for (const struct BitSet &bits : windowbits) { + float sideWidth = (2.0f - windowWidth) / 2.0f; + float moffset = (2.0f - sideWidth) / 2.0f; + float midSize = 2.0f; + float bottomSize = 0.5f - solidExtOffset; + float topOffset = 3.0f; + float topSize = solidExtHeight - midSize - bottomSize; + float offsetY = solidExtOffset; + if (bits.tb == &intwalltb) { + bottomSize = 0.5f - solidIntOffset; + topSize = solidIntHeight - midSize - bottomSize; + sideWidth = (1.8f - windowWidth) / 2.0f; + moffset = (1.8f - sideWidth) / 2.0f; + offsetY = solidIntOffset; + } + if (bits.offset.x == 0.0f) { + struct BitSet pbits = bits; + pbits.sizeY = sideWidth; + pbits.sizeX = bottomSize; + pbits.offset.x = -moffset; + pbits.offset.y = bottomSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.sizeX = bottomSize; + pbits.offset.x = moffset; + pbits.offset.y = bottomSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.sizeX = midSize; + pbits.offset.x = -moffset; + pbits.offset.y = + bottomSize + midSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.sizeX = midSize; + pbits.offset.x = moffset; + pbits.offset.y = + bottomSize + midSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.sizeX = topSize; + pbits.offset.x = -moffset; + pbits.offset.y = bottomSize + midSize + + topSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.sizeX = topSize; + pbits.offset.x = moffset; + pbits.offset.y = bottomSize + midSize + + topSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + + pbits.sizeY = windowWidth; + pbits.sizeX = bottomSize; + pbits.offset.x = 0; + pbits.offset.y = bottomSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + + pbits.sizeY = windowWidth; + pbits.sizeX = topSize; + pbits.offset.x = 0; + pbits.offset.y = bottomSize + midSize + + topSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + } else if (bits.offset.z == 0.0f) { + struct BitSet pbits = bits; + pbits.sizeY = sideWidth; + pbits.sizeX = bottomSize; + pbits.offset.z = -moffset; + pbits.offset.y = bottomSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.sizeX = bottomSize; + pbits.offset.z = moffset; + pbits.offset.y = bottomSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.sizeX = midSize; + pbits.offset.z = -moffset; + pbits.offset.y = + bottomSize + midSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.sizeX = midSize; + pbits.offset.z = moffset; + pbits.offset.y = + bottomSize + midSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.sizeX = topSize; + pbits.offset.z = -moffset; + pbits.offset.y = bottomSize + midSize + + topSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + pbits.sizeY = sideWidth; + pbits.sizeX = topSize; + pbits.offset.z = moffset; + pbits.offset.y = bottomSize + midSize + + topSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + + pbits.sizeY = windowWidth; + pbits.sizeX = bottomSize; + pbits.offset.z = 0; + pbits.offset.y = bottomSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + + pbits.sizeY = windowWidth; + pbits.sizeX = topSize; + pbits.offset.z = 0; + pbits.offset.y = bottomSize + midSize + + topSize / 2.0f + offsetY; + bits_windows.push_back(pbits); + } + } + } + void process(const Ogre::Vector3 &cellOffset, uint64_t flags, + Procedural::TriangleBuffer &cellTb) + { + auto gen = [cellOffset](float sizeX, float sizeY, + const Ogre::Vector3 &normal, + const Ogre::Vector3 offset, + Procedural::TriangleBuffer &tb) { + int nsegY = 8; + if (sizeY < 1.0f) + nsegY = 4; + Procedural::PlaneGenerator() + .setNormal(normal) + .setSizeX(sizeX) + .setSizeY(sizeY) + .setNumSegX(8) + .setNumSegY(nsegY) + .setEnableNormals(true) + .setPosition(cellOffset + offset) + .addToTriangleBuffer(tb); + }; + uint64_t corners_flags = 0; + corners_flags |= ((flags >> 0) & 0x3c); + corners_flags |= ((flags >> 4) & 0x3c); + corners_flags |= ((flags >> 8) & 0x3c); + // corners_flags |= ((flags >> 12) & 0x3c); + uint64_t corners_flags2 = 0; + corners_flags2 |= ((flags >> 0) & 0x3c000); + corners_flags2 |= ((flags >> 4) & 0x3c000); + corners_flags2 |= ((flags >> 8) & 0x3c000); + for (struct BitSet &bit : bits_ext_corners) { + if ((corners_flags & bit.bit) == bit.bit) + gen(bit.sizeX, bit.sizeY, bit.normal, + bit.offset, *bit.tb); + } + for (struct BitSet &bit : bits_solid) { + if ((flags & bit.bit) == bit.bit) + gen(bit.sizeX, bit.sizeY, bit.normal, + bit.offset, *bit.tb); + } + for (struct BitSet &bit : bits_doors) { + if ((flags & bit.bit) == bit.bit) + gen(bit.sizeX, bit.sizeY, bit.normal, + bit.offset, *bit.tb); + } + for (struct BitSet &bit : bits_windows) { + if ((flags & bit.bit) == bit.bit) + gen(bit.sizeX, bit.sizeY, bit.normal, + bit.offset, *bit.tb); + } + for (struct BitSet &bit : bits_int_corners1) { + if ((corners_flags2 & bit.bit) == bit.bit) { + if (bit.bit == (1ULL << 14) && + (corners_flags2 & (1ULL << 16))) + continue; + if (bit.bit == (1ULL << 15) && + (corners_flags2 & (1ULL << 16))) + continue; + if (bit.bit == (1ULL << 16) && + (corners_flags2 & (1ULL << 15))) + continue; + if (bit.bit == (1ULL << 17) && + (corners_flags2 & (1ULL << 15))) + continue; + gen(bit.sizeX, bit.sizeY, bit.normal, + bit.offset, *bit.tb); + } + } + for (struct BitSet &bit : bits_int_corners2) { + if ((corners_flags2 & bit.bit) == bit.bit) { + if (bit.bit == (1ULL << 14) && + (corners_flags2 & (1ULL << 17))) + continue; + if (bit.bit == (1ULL << 15) && + (corners_flags2 & (1ULL << 17))) + continue; + if (bit.bit == (1ULL << 16) && + (corners_flags2 & (1ULL << 14))) + continue; + if (bit.bit == (1ULL << 17) && + (corners_flags2 & (1ULL << 14))) + continue; + gen(bit.sizeX, bit.sizeY, bit.normal, + bit.offset, *bit.tb); + } + } + for (auto &v : floortb.getVertices()) { + // red floor color + v.mUV *= 0.08f; + v.mUV.x += 0.51f; + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.5f, 0.6f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + for (auto &v : ceilingtb.getVertices()) { + // ceiling color + v.mUV *= 0.08f; + v.mUV.x += 0.61f; + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.6f, 0.7f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + for (auto &v : extwalltb.getVertices()) { + // yellow wall color + v.mUV *= 0.08f; + v.mUV.x += 0.71f; + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.7f, 0.8f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + for (auto &v : intwalltb.getVertices()) { + // light blue int wall color + v.mUV *= 0.08f; + v.mUV.x += 0.81f; + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.8f, 0.9f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + for (auto &tb : std::vector( + { &floortb, &ceilingtb, &extwalltb, + &intwalltb })) { + if ((*tb).getVertices().size() > 0) + cellTb.append(*tb); + } + } +}; + +void createCells(flecs::entity e, const nlohmann::json &jdistrict, int index, + Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo) +{ + Ogre::MaterialPtr townMaterial; + townMaterial = Ogre::MaterialManager::getSingleton().getByName( + "proceduralMaterialTown" + + Ogre::StringConverter::toString(e.id())); + nlohmann::json jlots = nlohmann::json::array(); + if (jdistrict.find("lots") != jdistrict.end()) + jlots = jdistrict["lots"]; + Ogre::Vector3 centerPosition = sceneNode->_getDerivedPosition(); + Ogre::Quaternion centerOrientation = + sceneNode->_getDerivedOrientation(); + int count = 0; + float baseHeight = 4.0f; + const nlohmann::json &jp = jdistrict; + Ogre::Vector3 localPosition(0, 0, 0); + Ogre::Quaternion localRotation = Ogre::Quaternion::IDENTITY; + float delevation = 0.0f; + float radius = 50.0f; + if (jp.find("elevation") != jp.end()) + delevation = jp["elevation"].get(); + if (jp.find("radius") != jp.end()) + radius = jp["radius"].get(); + from_json(jp["position"], localPosition); + from_json(jp["rotation"], localRotation); + centerPosition = centerPosition + localPosition + + Ogre::Vector3(0, delevation, 0); + centerOrientation = centerOrientation * localRotation; + for (const auto &jb : jlots) { + float angle = 0.0f; + int depth = 10; + int width = 10; + float distance = radius; + float elevation = 0.0f; + std::cout << jb.dump() << std::endl; + if (jb.find("angle") != jb.end()) + angle = jb["angle"].get(); + if (jb.find("depth") != jb.end()) + depth = jb["depth"].get(); + if (jb.find("width") != jb.end()) + width = jb["width"].get(); + if (jb.find("elevation") != jb.end()) + elevation = jb["elevation"].get(); + + OgreAssert(width > 1 && depth > 1 && baseHeight > 1, + "Bad stuff happen"); + + Ogre::Quaternion rotation = Ogre::Quaternion( + Ogre::Degree(angle), Ogre::Vector3::UNIT_Y); + Ogre::Vector3 offset = centerOrientation * rotation * + (Ogre::Vector3::UNIT_Z * distance); + Ogre::Vector3 worldCenterPosition = + centerPosition + offset + + Ogre::Vector3(0, elevation, 0); + Ogre::Quaternion worldCenterOrientation = + centerOrientation * rotation; + if (jb.find("cells") != jb.end()) { + Procedural::TriangleBuffer cellTb; + for (auto &jcell : jb["cells"]) { + struct ProcessCells pcells; + int x = jcell["x"].get(); + int y = jcell["y"].get(); + int z = jcell["z"].get(); + uint64_t flags = jcell["flags"].get(); + Ogre::Vector3 cellOffset(x * 2.0f, y * 4.0f, + z * 2.0f); + if (flags == 0) { + Procedural::BoxGenerator() + .setSizeX(2.0f + 0.4f) + .setSizeY(0.2f) + .setSizeZ(2.0f + 0.4f) + .setNumSegY(8) + .setNumSegX(8) + .setNumSegZ(8) + .setEnableNormals(true) + .setPosition(cellOffset) + .addToTriangleBuffer( + pcells.floortb); + cellTb.append(pcells.floortb); + + } else + pcells.process(cellOffset, flags, + cellTb); + } + if (cellTb.getVertices().size() > 0) { + Ogre::String meshName = + "lotCells" + + Ogre::StringConverter::toString(count) + + "_" + + Ogre::StringConverter::toString( + e.id()) + + "_" + + Ogre::StringConverter::toString(index); + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton() + .getByName(meshName); + if (mesh) + Ogre::MeshManager::getSingleton().remove( + mesh); + mesh = cellTb.transformToMesh(meshName); + /* debug save mesh */ + // serializeMesh(mesh, meshName); + Ogre::LodConfig config(mesh); + setupLods(config); + Ogre::Entity *ent = + ECS::get() + .mScnMgr->createEntity( + "Ent" + meshName, mesh); + ent->setMaterial(townMaterial); + geo->addEntity(ent, worldCenterPosition, + worldCenterOrientation, + Ogre::Vector3::UNIT_SCALE); + ECS::get().mScnMgr->destroyEntity( + ent); + } + count++; + } + } +} +void createTownLots(flecs::entity e, const nlohmann::json &jdistrict, int index, + Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo) +{ + Ogre::MaterialPtr townMaterial; + townMaterial = Ogre::MaterialManager::getSingleton().getByName( + "proceduralMaterialTown" + + Ogre::StringConverter::toString(e.id())); + nlohmann::json jlots = nlohmann::json::array(); + if (jdistrict.find("lots") != jdistrict.end()) + jlots = jdistrict["lots"]; + Ogre::Vector3 centerPosition = sceneNode->_getDerivedPosition(); + Ogre::Quaternion centerOrientation = + sceneNode->_getDerivedOrientation(); + int count = 0; + float baseHeight = 4.0f; + const nlohmann::json &jp = jdistrict; + Ogre::Vector3 localPosition(0, 0, 0); + Ogre::Quaternion localRotation = Ogre::Quaternion::IDENTITY; + float delevation = 0.0f; + float radius = 50.0f; + if (jp.find("elevation") != jp.end()) + delevation = jp["elevation"].get(); + if (jp.find("radius") != jp.end()) + radius = jp["radius"].get(); + from_json(jp["position"], localPosition); + from_json(jp["rotation"], localRotation); + centerPosition = centerPosition + localPosition + + Ogre::Vector3(0, delevation, 0); + centerOrientation = centerOrientation * localRotation; + for (const auto &jb : jlots) { + Procedural::TriangleBuffer tb; + float angle = 0.0f; + int depth = 10; + int width = 10; + float distance = radius; + float elevation = 0.0f; + std::cout << jb.dump() << std::endl; + if (jb.find("angle") != jb.end()) + angle = jb["angle"].get(); + if (jb.find("depth") != jb.end()) + depth = jb["depth"].get(); + if (jb.find("width") != jb.end()) + width = jb["width"].get(); + if (jb.find("elevation") != jb.end()) + elevation = jb["elevation"].get(); + + OgreAssert(width > 1 && depth > 1 && baseHeight > 1, + "Bad stuff happen"); + + Ogre::Quaternion rotation = Ogre::Quaternion( + Ogre::Degree(angle), Ogre::Vector3::UNIT_Y); + Ogre::Vector3 offset = centerOrientation * rotation * + (Ogre::Vector3::UNIT_Z * distance); + Procedural::BoxGenerator() + .setSizeX(4.0f * (float)width) + .setSizeY(baseHeight) + .setSizeZ(4.0f * (float)depth) + .setNumSegY(8) + .setNumSegX(8) + .setNumSegZ(8) + .setEnableNormals(true) + .setPosition(Ogre::Vector3( + 0.0f, -baseHeight / 2.0f + elevation - 0.01f, + 0.0f)) + .addToTriangleBuffer(tb); + OgreAssert(tb.getVertices().size() > 8, "bad box"); + for (auto &v : tb.getVertices()) { + v.mUV *= 0.08f; + v.mUV.x += 0.41f; + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.4f, 0.5f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + Ogre::String meshName = + "lotbase" + Ogre::StringConverter::toString(count) + + "_" + Ogre::StringConverter::toString(e.id()) + "_" + + Ogre::StringConverter::toString(index); + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton().getByName(meshName); + if (mesh) + Ogre::MeshManager::getSingleton().remove(mesh); + mesh = tb.transformToMesh(meshName); + Ogre::LodConfig config(mesh); + setupLods(config); + Ogre::Entity *ent = + ECS::get().mScnMgr->createEntity( + "Ent" + meshName, mesh); + ent->setMaterial(townMaterial); + geo->addEntity(ent, centerPosition + offset, + centerOrientation * rotation, + Ogre::Vector3::UNIT_SCALE); + ECS::get().mScnMgr->destroyEntity(ent); + count++; + } +} } } -} \ No newline at end of file diff --git a/src/gamedata/items/town.h b/src/gamedata/items/town.h index 2856456..754c9f9 100644 --- a/src/gamedata/items/town.h +++ b/src/gamedata/items/town.h @@ -12,10 +12,16 @@ void createTownPopup(const std::pair item); } namespace Geometry { +void createCells(flecs::entity e, const nlohmann::json &jdistrict, int index, + Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); void createTown(flecs::entity e, Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); void createTownPlazza(flecs::entity e, const nlohmann::json &jdistrict, - Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); + int index, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo); +void createTownLots(flecs::entity e, const nlohmann::json &jdistrict, + int index, Ogre::SceneNode *sceneNode, + Ogre::StaticGeometry *geo); } } -#endif \ No newline at end of file +#endif diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index ca62ed5..028aa20 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -895,8 +895,14 @@ public: msp.ScaleToMass(mass); bodySettings.mMassPropertiesOverride = msp; } - return createBody(bodySettings, listener); - } + JPH::BodyID id = createBody(bodySettings, listener); + if (shape->GetType() == JPH::EShapeType::HeightField) { + JPH::BodyInterface &body_interface = + physics_system.GetBodyInterface(); + body_interface.SetFriction(id, 1.0f); + } + return id; + } JPH::BodyID createBody(const JPH::Shape *shape, float mass, Ogre::SceneNode *node, JPH::EMotionType motion, JPH::ObjectLayer layer, @@ -906,20 +912,8 @@ public: const Ogre::Quaternion &rotation = node->_getDerivedOrientation(); std::cout << "body position: " << position << std::endl; - JPH::BodyCreationSettings bodySettings( - shape, JoltPhysics::convert(position), - JoltPhysics::convert(rotation), motion, layer); - if (mass > 0.001f) { - JPH::MassProperties msp; - msp.ScaleToMass(mass); - bodySettings.mMassPropertiesOverride = msp; - } - JPH::BodyID id = createBody(bodySettings, listener); - if (shape->GetType() == JPH::EShapeType::HeightField) { - JPH::BodyInterface &body_interface = - physics_system.GetBodyInterface(); - body_interface.SetFriction(id, 1.0f); - } + JPH::BodyID id = createBody(shape, mass, position, rotation, + motion, layer, listener); id2node[id] = node; node2id[node] = id; return id;