house generation almost complete

This commit is contained in:
2026-01-02 18:08:20 +03:00
parent 49fc547295
commit c031056e17

View File

@@ -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<CellsScript *>(
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<CellsScript *>(
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<CellsScript *>(
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<CellsScript *>(
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<CellsScript *>(
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<CellsScript *>(
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<Ogre::String> 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<Ogre::String> bits = split_and_trim(bit, ',');
int cellIndex = findCell(currentX, currentY, currentZ);
if (cellIndex >= 0)
flags = cells[cellIndex]["flags"].get<uint64_t>();
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<std::pair<int, int> > adjacentCells(int room, int other)
void adjacentCells(int room, int other,
std::vector<std::pair<int, int> > &ret1,
std::vector<std::pair<int, int> > &ret2)
{
std::vector<std::pair<int, int> > room_seg = roomEdge(room);
std::vector<std::pair<int, int> > other_seg = roomEdge(other);
std::vector<std::pair<int, int> > 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<std::pair<int, int> > 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<std::pair<int, int> > 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<struct BitSet> bits_ext_corners;
std::vector<struct BitSet> bits_solid;
std::vector<struct BitSet> 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<Procedural::TriangleBuffer *>(
{ &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<int>();
@@ -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<EngineData>().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<EngineData>()
.mScnMgr->createEntity(
"Ent" + meshName, mesh);
ent->setMaterial(townMaterial);
#if 1
geo->addEntity(ent, worldCenterPosition,
worldCenterOrientation,
Ogre::Vector3::UNIT_SCALE);
#endif
ECS::get<EngineData>().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<EngineData>()
.mScnMgr->createEntity(
"Ent" + meshName, mesh);
ent->setMaterial(townMaterial);
#if 1
geo->addEntity(ent, worldCenterPosition,
worldCenterOrientation,
Ogre::Vector3::UNIT_SCALE);
#endif
ECS::get<EngineData>().mScnMgr->destroyEntity(
ent);
}