diff --git a/src/gamedata/items/town.cpp b/src/gamedata/items/town.cpp index fc657f9..a2517c3 100644 --- a/src/gamedata/items/town.cpp +++ b/src/gamedata/items/town.cpp @@ -270,13 +270,84 @@ struct CellsScript { lua_touserdata(L, lua_upvalueindex(1))); int r1 = lua_tointeger(L, 1); int r2 = lua_tointeger(L, 2); - _this->connect_rooms(r1, r2); + _this->connectRooms(r1, r2); std::cout << "connect rooms: " << r1 << " " << r2 << std::endl; return 0; }, 1); lua_setglobal(L, "connect_rooms"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + int room = lua_tointeger(L, 1); + _this->createExit0(room); + return 0; + }, + 1); + lua_setglobal(L, "create_exit0"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + int room = lua_tointeger(L, 1); + _this->createExit1(room); + return 0; + }, + 1); + lua_setglobal(L, "create_exit1"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + int room = lua_tointeger(L, 1); + _this->createExit2(room); + return 0; + }, + 1); + lua_setglobal(L, "create_exit2"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + int room = lua_tointeger(L, 1); + _this->createExit3(room); + return 0; + }, + 1); + lua_setglobal(L, "create_exit3"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + int room = lua_tointeger(L, 1); + _this->createWindows(room); + return 0; + }, + 1); + lua_setglobal(L, "create_windows"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) -> int { + CellsScript *_this = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + _this->createExterior(); + return 0; + }, + 1); + lua_setglobal(L, "create_exterior"); } std::string trim(const std::string &str) { @@ -364,6 +435,33 @@ struct CellsScript { } cell(flags); } + bool isBit(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, ','); + int cellIndex = findCell(currentX, currentY, currentZ); + if (cellIndex >= 0) + flags = cells[cellIndex]["flags"].get(); + uint64_t bitset = 0; + for (auto &sbit : bits) { + auto loc = + std::find(bitconv.begin(), bitconv.end(), sbit); + if (loc != bitconv.end()) { + int index = std::distance(bitconv.begin(), loc); + bitset |= (1ULL << (uint64_t)index); + } + } + return (flags & bitset) == bitset; + } void cell(uint64_t flags) { if (findCell(currentX, currentY, currentZ) == -1) { @@ -457,22 +555,256 @@ struct CellsScript { int dz = std::abs(c1.second - c2.second); return (dx == 0 && dz == 1) || (dx == 1 && dz == 0); } - std::vector > adjacentCells(int room, int other) + void adjacentCells(int room, int other, + std::vector > &ret1, + std::vector > &ret2) { 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); + if (adjacent(cell, ocell)) { + ret1.push_back(cell); + ret2.push_back(ocell); + } } - return ret; } - void connect_rooms(int r1, int r2) + void createExit0(int room) { - std::vector > seg1 = adjacentCells(r1, r2), - seg2 = adjacentCells(r2, r1); + int posX = rooms[room].minX; + int posZ = rooms[room].minZ; + int i; + int sumX = -1; + int count = 0; + for (i = 0; i < rooms[room].sizeX; i++) { + currentX = posX + i; + currentZ = posZ; + if (findCell(posX + i, currentY, posZ - 1) != -1) + continue; + if (isBit("iwallz-")) { + if (sumX == -1) + sumX = posX + i; + else + sumX += posX + i; + count++; + } + } + if (count > 0) { + int rposX = sumX / count; + currentX = rposX; + currentZ = posZ; + bitCmd("clear", "iwallz-"); + bitCmd("set", "idoorz-"); + } + } + void createExit1(int room) + { + int posX = rooms[room].minX; + int posZ = rooms[room].minZ + rooms[room].sizeZ - 1; + int i; + int sumX = -1; + int count = 0; + for (i = 0; i < rooms[room].sizeX; i++) { + currentX = posX + i; + currentZ = posZ; + if (findCell(posX + i, currentY, posZ + 1) != -1) + continue; + if (isBit("iwallz+")) { + if (sumX == -1) + sumX = posX + i; + else + sumX += posX + i; + count++; + } + } + if (count > 0) { + int rposX = sumX / count; + currentX = rposX; + currentZ = posZ; + bitCmd("clear", "iwallz+"); + bitCmd("set", "idoorz+"); + } + } + void createExit2(int room) + { + int posX = rooms[room].minX + rooms[room].sizeX - 1; + int posZ = rooms[room].minZ; + int i; + int sumZ = -1; + int count = 0; + for (i = 0; i < rooms[room].sizeZ; i++) { + currentX = posX; + currentZ = posZ + i; + if (findCell(posX + 1, currentY, posZ + i) != -1) + continue; + if (isBit("iwallx+")) { + if (sumZ == -1) + sumZ = posZ + i; + else + sumZ += posZ + i; + count++; + } + } + if (count > 0) { + int rposZ = sumZ / count; + currentX = posX; + currentZ = rposZ; + bitCmd("clear", "iwallx+"); + bitCmd("set", "idoorx+"); + } + } + void createExit3(int room) + { + int posX = rooms[room].minX; + int posZ = rooms[room].minZ; + int i; + int sumZ = -1; + int count = 0; + for (i = 0; i < rooms[room].sizeZ; i++) { + currentX = posX; + currentZ = posZ + i; + if (findCell(posX - 1, currentY, posZ + i) != -1) + continue; + if (isBit("iwallx-")) { + if (sumZ == -1) + sumZ = posZ + i; + else + sumZ += posZ + i; + count++; + } + } + if (count > 0) { + int rposZ = sumZ / count; + currentX = posX; + currentZ = rposZ; + bitCmd("clear", "iwallx-"); + bitCmd("set", "idoorx-"); + } + } + void createWindows(int room) + { + int posX = rooms[room].minX; + int posZ = rooms[room].minZ; + int i; + for (i = 0; i < rooms[room].sizeX; i++) { + currentX = posX + i; + currentZ = posZ; + if (findCell(posX + i, currentY, posZ - 1) != -1) + continue; + if (isBit("iwallz-")) { + bitCmd("clear", "iwallz-"); + bitCmd("set", "iwindowz-"); + } + } + posX = rooms[room].minX; + posZ = rooms[room].minZ + rooms[room].sizeZ - 1; + for (i = 0; i < rooms[room].sizeX; i++) { + currentX = posX + i; + currentZ = posZ; + if (findCell(posX + i, currentY, posZ + 1) != -1) + continue; + if (isBit("iwallz+")) { + bitCmd("clear", "iwallz+"); + bitCmd("set", "iwindowz+"); + } + } + posX = rooms[room].minX + rooms[room].sizeX - 1; + posZ = rooms[room].minZ; + for (i = 0; i < rooms[room].sizeZ; i++) { + currentX = posX; + currentZ = posZ + i; + if (findCell(posX + 1, currentY, posZ + i) != -1) + continue; + if (isBit("iwallx+")) { + bitCmd("clear", "iwallx+"); + bitCmd("set", "iwindowx+"); + } + } + posX = rooms[room].minX; + posZ = rooms[room].minZ; + for (i = 0; i < rooms[room].sizeZ; i++) { + currentX = posX; + currentZ = posZ + i; + if (findCell(posX - 1, currentY, posZ + i) != -1) + continue; + if (isBit("iwallx-")) { + bitCmd("clear", "iwallx-"); + bitCmd("set", "iwindowx-"); + } + } + } + void createExterior() + { + int room; + for (room = 0; room < rooms.size(); room++) { + int posX = rooms[room].minX; + int posZ = rooms[room].minZ; + int i; + for (i = 0; i < rooms[room].sizeX; i++) { + currentX = posX + i; + currentZ = posZ; + if (findCell(posX + i, currentY, posZ - 1) != + -1) + continue; + if (isBit("iwallz-")) + bitCmd("set", "wallz-"); + if (isBit("idoorz-")) + bitCmd("set", "doorz-"); + if (isBit("iwindowz-")) + bitCmd("set", "windowz-"); + } + posX = rooms[room].minX; + posZ = rooms[room].minZ + rooms[room].sizeZ - 1; + for (i = 0; i < rooms[room].sizeX; i++) { + currentX = posX + i; + currentZ = posZ; + if (findCell(posX + i, currentY, posZ + 1) != + -1) + continue; + if (isBit("iwallz+")) + bitCmd("set", "wallz+"); + if (isBit("idoorz+")) + bitCmd("set", "doorz+"); + if (isBit("iwindowz+")) + bitCmd("set", "windowz+"); + } + posX = rooms[room].minX + rooms[room].sizeX - 1; + posZ = rooms[room].minZ; + for (i = 0; i < rooms[room].sizeZ; i++) { + currentX = posX; + currentZ = posZ + i; + if (findCell(posX + 1, currentY, posZ + i) != + -1) + continue; + if (isBit("iwallx+")) + bitCmd("set", "wallx+"); + if (isBit("idoorx+")) + bitCmd("set", "doorx+"); + if (isBit("iwindowx+")) + bitCmd("set", "windowx+"); + } + posX = rooms[room].minX; + posZ = rooms[room].minZ; + for (i = 0; i < rooms[room].sizeZ; i++) { + currentX = posX; + currentZ = posZ + i; + if (findCell(posX - 1, currentY, posZ + i) != + -1) + continue; + if (isBit("iwallx-")) + bitCmd("set", "wallx-"); + if (isBit("idoorx-")) + bitCmd("set", "doorx-"); + if (isBit("iwindowx-")) + bitCmd("set", "windowx-"); + } + } + } + void connectRooms(int r1, int r2) + { + std::vector > seg1, seg2; + adjacentCells(r1, r2, seg1, seg2); for (auto &cell : seg1) { std::cout << "seg1: " << cell.first << " " << cell.second << std::endl; @@ -481,82 +813,91 @@ struct CellsScript { std::cout << "seg2: " << cell.first << " " << cell.second << std::endl; } + if (seg1.size() == 0 || seg2.size() == 0) + return; int sumX = 0, sumZ = 0; - int sumOX = 0, sumOZ = 0; int count = 0; - for (auto &cell : seg1) { - sumX += cell.first; - sumZ += cell.second; - count++; + for (count = 0; count < seg1.size(); count++) { + sumX += seg1[count].first; + sumZ += seg1[count].second; } - if (count == 0) - return; - sumX /= count; - sumZ /= count; - count = 0; - for (auto &cell : seg2) { - sumOX += cell.first; - sumOZ += cell.second; - count++; + sumX /= seg1.size(); + sumZ /= seg1.size(); + int distance = -1; + int index = -1; + for (count = 0; count < seg1.size(); count++) { + int mdx = seg1[count].first - sumX; + int mdz = seg1[count].second - sumZ; + if (count == 0) { + index = 0; + distance = mdx * mdx + mdz * mdz; + } else { + if (distance > mdx * mdx + mdz * mdz) { + distance = mdx * mdx + mdz * mdz; + index = count; + } + } } - if (count == 0) - return; - sumOX /= count; - sumOZ /= count; - int dx = sumX - sumOX; - int dz = sumZ - sumOZ; + int dx = seg1[index].first - seg2[index].first; + int dz = seg1[index].second - seg2[index].second; std::cout << dx << " " << dz << std::endl; + if (dx == 0 && dz == 0) { + std::cerr << "can't connect rooms" << std::endl; + return; + } OgreAssert(std::abs(dx) == 1 && dz == 0 || dx == 0 && std::abs(dz) == 1, "shit happens"); if (dz < 0) { - currentX = sumX; - currentZ = sumZ; + currentX = seg1[index].first; + currentZ = seg1[index].second; bitCmd("clear", "iwallz+"); bitCmd("set", "idoorz+"); - currentX = sumOX; - currentZ = sumOZ; + currentX = seg2[index].first; + currentZ = seg2[index].second; bitCmd("clear", "iwallz-"); bitCmd("set", "idoorz-"); } if (dz > 0) { - currentX = sumX; - currentZ = sumZ; + currentX = seg1[index].first; + currentZ = seg1[index].second; bitCmd("clear", "iwallz-"); bitCmd("set", "idoorz-"); - currentX = sumOX; - currentZ = sumOZ; + currentX = seg2[index].first; + currentZ = seg2[index].second; bitCmd("clear", "iwallz+"); bitCmd("set", "idoorz+"); } if (dx < 0) { - currentX = sumX; - currentZ = sumZ; + currentX = seg1[index].first; + currentZ = seg1[index].second; bitCmd("clear", "iwallx+"); bitCmd("set", "idoorx+"); - currentX = sumOX; - currentZ = sumOZ; + currentX = seg2[index].first; + currentZ = seg2[index].second; bitCmd("clear", "iwallx-"); bitCmd("set", "idoorx-"); } if (dx > 0) { - currentX = sumX; - currentZ = sumZ; + currentX = seg1[index].first; + currentZ = seg1[index].second; bitCmd("clear", "iwallx-"); bitCmd("set", "idoorx-"); - currentX = sumOX; - currentZ = sumOZ; + currentX = seg2[index].first; + currentZ = seg2[index].second; bitCmd("clear", "iwallx+"); bitCmd("set", "idoorx+"); } - int cell1 = findCell(sumX, currentY, sumZ); - int cell2 = findCell(sumOX, currentY, sumOZ); + /* + int cell1 = findCell(seg1[index].first, currentY, seg1[index].second); + int cell2 = findCell(seg2[index].first, currentY, seg2[index].second); std::cout << sumX << " " << sumZ << "..." << sumOX << " " << sumOZ << std::endl; std::cout << dx << " " << dz << " " << cell1 << " " << cell2 << std::endl; // OgreAssert(false, "eeeeeh"); // OgreAssert(false, "eeeeeh"); + */ } virtual ~CellsScript() { @@ -1013,6 +1354,7 @@ struct ProcessCells { Procedural::TriangleBuffer ceilingtb; Procedural::TriangleBuffer extwalltb; Procedural::TriangleBuffer intwalltb; + Procedural::TriangleBuffer intwindowstb; std::vector bits_ext_corners; std::vector bits_solid; std::vector bits_doors; @@ -1371,25 +1713,25 @@ struct ProcessCells { 0.2f, Ogre::Vector3::UNIT_X, { -1.0 + 0.1f, 1.5f, 0 }, - &intwalltb }, + &intwindowstb }, { 1ULL << 23, // internal window 2.0f, 0.2f, Ogre::Vector3::NEGATIVE_UNIT_X, { 1.0 - 0.1f, 1.5f, 0 }, - &intwalltb }, + &intwindowstb }, { 1ULL << 24, // internal window 2.0f, 0.2f, Ogre::Vector3::NEGATIVE_UNIT_Z, { 0, 1.5f, 1.0f - 0.1f }, - &intwalltb }, + &intwindowstb }, { 1ULL << 25, // internal window 2.0f, 0.2f, Ogre::Vector3::UNIT_Z, { 0, 1.5f, -1.0f + 0.1f }, - &intwalltb }, + &intwindowstb }, }; const float windowWidth = 1.6f; for (const struct BitSet &bits : windowbits) { @@ -1400,7 +1742,7 @@ struct ProcessCells { float topOffset = 3.0f; float topSize = solidExtHeight - midSize - bottomSize; float offsetY = solidExtOffset; - if (bits.tb == &intwalltb) { + if (bits.tb == &intwindowstb) { bottomSize = 0.5f - solidIntOffset; topSize = solidIntHeight - midSize - bottomSize; sideWidth = (1.8f - windowWidth) / 2.0f; @@ -1509,7 +1851,9 @@ struct ProcessCells { } } void process(const Ogre::Vector3 &cellOffset, uint64_t flags, - Procedural::TriangleBuffer &cellTb) + Procedural::TriangleBuffer &cellTb, + Procedural::TriangleBuffer &intwinTb, + Procedural::TriangleBuffer &exteriorTb) { auto gen = [cellOffset](float sizeX, float sizeY, const Ogre::Vector3 &normal, @@ -1621,12 +1965,22 @@ struct ProcessCells { 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 &v : intwindowstb.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 })) { + { &floortb, &ceilingtb, &intwalltb })) { if ((*tb).getVertices().size() > 0) cellTb.append(*tb); } + if (intwindowstb.getVertices().size() > 0) + intwinTb.append(intwindowstb); + if (extwalltb.getVertices().size() > 0) + exteriorTb.append(extwalltb); } }; @@ -1689,6 +2043,8 @@ void createCells(flecs::entity e, const nlohmann::json &jdistrict, int index, centerOrientation * rotation; if (jb.find("cells") != jb.end()) { Procedural::TriangleBuffer cellTb; + Procedural::TriangleBuffer intwinTb; + Procedural::TriangleBuffer exteriorTb; for (auto &jcell : jb["cells"]) { struct ProcessCells pcells; int x = jcell["x"].get(); @@ -1713,7 +2069,8 @@ void createCells(flecs::entity e, const nlohmann::json &jdistrict, int index, } else pcells.process(cellOffset, flags, - cellTb); + cellTb, intwinTb, + exteriorTb); } if (cellTb.getVertices().size() > 0) { Ogre::String meshName = @@ -1730,6 +2087,9 @@ void createCells(flecs::entity e, const nlohmann::json &jdistrict, int index, if (mesh) Ogre::MeshManager::getSingleton().remove( mesh); + std::cout << "vertex count: " + << cellTb.getVertices().size() + << std::endl; mesh = cellTb.transformToMesh(meshName); /* debug save mesh */ // serializeMesh(mesh, meshName); @@ -1740,9 +2100,85 @@ void createCells(flecs::entity e, const nlohmann::json &jdistrict, int index, .mScnMgr->createEntity( "Ent" + meshName, mesh); ent->setMaterial(townMaterial); +#if 1 geo->addEntity(ent, worldCenterPosition, worldCenterOrientation, Ogre::Vector3::UNIT_SCALE); +#endif + ECS::get().mScnMgr->destroyEntity( + ent); + } + if (intwinTb.getVertices().size() > 0) { + Ogre::String meshName = + "lotCells" + + Ogre::StringConverter::toString(count) + + "_" + + Ogre::StringConverter::toString( + e.id()) + + "_" + + Ogre::StringConverter::toString(index) + + "_intwin"; + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton() + .getByName(meshName); + if (mesh) + Ogre::MeshManager::getSingleton().remove( + mesh); + std::cout << "vertex count: " + << intwinTb.getVertices().size() + << std::endl; + mesh = intwinTb.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); +#if 1 + geo->addEntity(ent, worldCenterPosition, + worldCenterOrientation, + Ogre::Vector3::UNIT_SCALE); +#endif + ECS::get().mScnMgr->destroyEntity( + ent); + } + if (exteriorTb.getVertices().size() > 0) { + Ogre::String meshName = + "lotCells" + + Ogre::StringConverter::toString(count) + + "_" + + Ogre::StringConverter::toString( + e.id()) + + "_" + + Ogre::StringConverter::toString(index) + + "_exterior"; + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton() + .getByName(meshName); + if (mesh) + Ogre::MeshManager::getSingleton().remove( + mesh); + std::cout << "vertex count: " + << exteriorTb.getVertices().size() + << std::endl; + mesh = exteriorTb.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); +#if 1 + geo->addEntity(ent, worldCenterPosition, + worldCenterOrientation, + Ogre::Vector3::UNIT_SCALE); +#endif ECS::get().mScnMgr->destroyEntity( ent); }