|
|
|
|
@@ -216,7 +216,7 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
|
|
|
|
|
// Build geometry parts
|
|
|
|
|
Procedural::TriangleBuffer floorTb, ceilingTb, extWallTb, intWallTb,
|
|
|
|
|
extWindowsTb, intWindowsTb, extDoorsTb, intDoorsTb, roofTb;
|
|
|
|
|
extWindowsTb, intWindowsTb, extDoorsTb, intDoorsTb, roofTopTb, roofSideTb;
|
|
|
|
|
|
|
|
|
|
buildFloorsAndCeilings(grid, floorTb, ceilingTb);
|
|
|
|
|
buildWalls(grid, extWallTb, intWallTb, intWindowsTb);
|
|
|
|
|
@@ -224,7 +224,7 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
buildInternalCorners(grid, intWallTb);
|
|
|
|
|
buildDoors(grid, extDoorsTb, intDoorsTb);
|
|
|
|
|
buildWindows(grid, extWindowsTb, intWindowsTb);
|
|
|
|
|
buildRoofs(entity, grid, roofTb);
|
|
|
|
|
buildRoofs(entity, grid, roofTopTb, roofSideTb);
|
|
|
|
|
|
|
|
|
|
// Apply UV mapping for each part (use rect if specified, otherwise default)
|
|
|
|
|
Ogre::LogManager::getSingleton().logMessage(
|
|
|
|
|
@@ -243,7 +243,8 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
materialEntity);
|
|
|
|
|
applyUVMappingToBuffer(intDoorsTb, grid.intWallRectName,
|
|
|
|
|
materialEntity);
|
|
|
|
|
applyUVMappingToBuffer(roofTb, grid.extWallRectName, materialEntity);
|
|
|
|
|
applyUVMappingToBuffer(roofTopTb, grid.roofTopRectName, materialEntity);
|
|
|
|
|
applyUVMappingToBuffer(roofSideTb, grid.roofSideRectName, materialEntity);
|
|
|
|
|
|
|
|
|
|
// Generate unique base name
|
|
|
|
|
std::string baseName = "CellGrid_" + std::to_string(entity.id()) + "_" +
|
|
|
|
|
@@ -311,15 +312,25 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
meshData.entities.push_back(entity3d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Roof
|
|
|
|
|
if (roofTb.getVertices().size() >= 3) {
|
|
|
|
|
meshData.roofMesh = baseName + "_roof";
|
|
|
|
|
// Roof top pieces
|
|
|
|
|
if (roofTopTb.getVertices().size() >= 3) {
|
|
|
|
|
meshData.roofMesh = baseName + "_roofTop";
|
|
|
|
|
auto mesh =
|
|
|
|
|
convertToMesh(meshData.roofMesh, roofTb, materialName);
|
|
|
|
|
convertToMesh(meshData.roofMesh, roofTopTb, materialName);
|
|
|
|
|
auto entity3d = m_sceneMgr->createEntity(meshData.roofMesh);
|
|
|
|
|
transform.node->attachObject(entity3d);
|
|
|
|
|
meshData.entities.push_back(entity3d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Roof side pieces (trim/gable ends)
|
|
|
|
|
if (roofSideTb.getVertices().size() >= 3) {
|
|
|
|
|
meshData.roofSideMesh = baseName + "_roofSide";
|
|
|
|
|
auto mesh =
|
|
|
|
|
convertToMesh(meshData.roofSideMesh, roofSideTb, materialName);
|
|
|
|
|
auto entity3d = m_sceneMgr->createEntity(meshData.roofSideMesh);
|
|
|
|
|
transform.node->attachObject(entity3d);
|
|
|
|
|
meshData.entities.push_back(entity3d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// External doors
|
|
|
|
|
if (extDoorsTb.getVertices().size() >= 3) {
|
|
|
|
|
@@ -378,7 +389,8 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
|
|
|
|
|
std::to_string(extWindowsTb.getVertices().size()) +
|
|
|
|
|
" extDoors=" + std::to_string(extDoorsTb.getVertices().size()) +
|
|
|
|
|
" intDoors=" + std::to_string(intDoorsTb.getVertices().size()) +
|
|
|
|
|
" roof=" + std::to_string(roofTb.getVertices().size()));
|
|
|
|
|
" roofTop=" + std::to_string(roofTopTb.getVertices().size()) +
|
|
|
|
|
" roofSide=" + std::to_string(roofSideTb.getVertices().size()));
|
|
|
|
|
|
|
|
|
|
// Build window and door frames
|
|
|
|
|
try {
|
|
|
|
|
@@ -1734,9 +1746,60 @@ void CellGridSystem::buildWindows(const CellGridComponent &grid,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Deform roof side vertices to create triangular gable ends
|
|
|
|
|
*
|
|
|
|
|
* For Normal roof (deformXAxis=true): Deforms side pieces along X axis
|
|
|
|
|
* For Normal2 roof (deformXAxis=false): Deforms side pieces along Z axis
|
|
|
|
|
*/
|
|
|
|
|
static void deformRoofSideVertices(Procedural::TriangleBuffer &tb,
|
|
|
|
|
size_t startVertexIndex,
|
|
|
|
|
bool deformXAxis)
|
|
|
|
|
{
|
|
|
|
|
auto &vertices = tb.getVertices();
|
|
|
|
|
if (vertices.size() <= startVertexIndex)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Find min/max Y and coord (X or Z depending on axis)
|
|
|
|
|
float minY = std::numeric_limits<float>::max();
|
|
|
|
|
float maxY = std::numeric_limits<float>::lowest();
|
|
|
|
|
float minCoord = std::numeric_limits<float>::max();
|
|
|
|
|
float maxCoord = std::numeric_limits<float>::lowest();
|
|
|
|
|
|
|
|
|
|
for (size_t i = startVertexIndex; i < vertices.size(); ++i) {
|
|
|
|
|
const auto &v = vertices[i];
|
|
|
|
|
minY = std::min(minY, v.mPosition.y);
|
|
|
|
|
maxY = std::max(maxY, v.mPosition.y);
|
|
|
|
|
float coord = deformXAxis ? v.mPosition.x : v.mPosition.z;
|
|
|
|
|
minCoord = std::min(minCoord, coord);
|
|
|
|
|
maxCoord = std::max(maxCoord, coord);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float midCoord = minCoord + (maxCoord - minCoord) / 2.0f;
|
|
|
|
|
float coordRange = (maxCoord - minCoord) / 2.0f;
|
|
|
|
|
if (coordRange < 0.001f)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Deform vertices to create triangular shape
|
|
|
|
|
for (size_t i = startVertexIndex; i < vertices.size(); ++i) {
|
|
|
|
|
auto &v = vertices[i];
|
|
|
|
|
float md = maxY - v.mPosition.y;
|
|
|
|
|
float hm = (deformXAxis ? v.mPosition.x : v.mPosition.z) -
|
|
|
|
|
midCoord;
|
|
|
|
|
float he = (hm / coordRange) * md;
|
|
|
|
|
|
|
|
|
|
if (deformXAxis) {
|
|
|
|
|
v.mPosition.x = he + midCoord;
|
|
|
|
|
} else {
|
|
|
|
|
v.mPosition.z = he + midCoord;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
const CellGridComponent &grid,
|
|
|
|
|
Procedural::TriangleBuffer &roofTb)
|
|
|
|
|
Procedural::TriangleBuffer &roofTopTb,
|
|
|
|
|
Procedural::TriangleBuffer &roofSideTb)
|
|
|
|
|
{
|
|
|
|
|
// Get roof components from CellGrid's children
|
|
|
|
|
// Roof components are children of the CellGrid entity
|
|
|
|
|
@@ -1776,7 +1839,7 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
|
|
|
|
|
switch (roof.type) {
|
|
|
|
|
case RoofComponent::Flat: {
|
|
|
|
|
// Main roof box
|
|
|
|
|
// Main roof box -> roofTopTb
|
|
|
|
|
float baseY = origin.y + roof.baseHeight / 2.0f;
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
.setSizeX(width)
|
|
|
|
|
@@ -1788,11 +1851,12 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
.setEnableNormals(true)
|
|
|
|
|
.setPosition(Ogre::Vector3(
|
|
|
|
|
origin.x, baseY, origin.z))
|
|
|
|
|
.addToTriangleBuffer(roofTb);
|
|
|
|
|
.addToTriangleBuffer(roofTopTb);
|
|
|
|
|
|
|
|
|
|
// Edge trim pieces (Z+ edge)
|
|
|
|
|
// Edge trim pieces -> roofSideTb
|
|
|
|
|
float trimBaseY =
|
|
|
|
|
origin.y + roof.baseHeight / 2.0f;
|
|
|
|
|
// Z+ edge
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
.setSizeX(width)
|
|
|
|
|
.setSizeY(roof.baseHeight +
|
|
|
|
|
@@ -1806,7 +1870,7 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
origin.x, trimBaseY + EXTEND,
|
|
|
|
|
origin.z + depth / 2.0f +
|
|
|
|
|
EXTEND / 2.0f))
|
|
|
|
|
.addToTriangleBuffer(roofTb);
|
|
|
|
|
.addToTriangleBuffer(roofSideTb);
|
|
|
|
|
|
|
|
|
|
// Z- edge
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
@@ -1822,7 +1886,7 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
origin.x, trimBaseY + EXTEND,
|
|
|
|
|
origin.z - depth / 2.0f -
|
|
|
|
|
EXTEND / 2.0f))
|
|
|
|
|
.addToTriangleBuffer(roofTb);
|
|
|
|
|
.addToTriangleBuffer(roofSideTb);
|
|
|
|
|
|
|
|
|
|
// X+ edge
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
@@ -1838,7 +1902,7 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
origin.x + width / 2.0f +
|
|
|
|
|
EXTEND / 2.0f,
|
|
|
|
|
trimBaseY + EXTEND, origin.z))
|
|
|
|
|
.addToTriangleBuffer(roofTb);
|
|
|
|
|
.addToTriangleBuffer(roofSideTb);
|
|
|
|
|
|
|
|
|
|
// X- edge
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
@@ -1854,12 +1918,12 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
origin.x - width / 2.0f -
|
|
|
|
|
EXTEND / 2.0f,
|
|
|
|
|
trimBaseY + EXTEND, origin.z))
|
|
|
|
|
.addToTriangleBuffer(roofTb);
|
|
|
|
|
.addToTriangleBuffer(roofSideTb);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case RoofComponent::Normal: {
|
|
|
|
|
// Gable roof along X axis (ridge runs along Z)
|
|
|
|
|
// Two angled boxes forming a roof
|
|
|
|
|
// Two angled boxes -> roofTopTb
|
|
|
|
|
float q = width / 2.0f;
|
|
|
|
|
float m = 1.0f;
|
|
|
|
|
float d = Ogre::Math::Sqrt(2.0f) * (q + m);
|
|
|
|
|
@@ -1883,7 +1947,7 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
baseY + roof.baseHeight +
|
|
|
|
|
q / 2.0f - m / 2.0f,
|
|
|
|
|
origin.z))
|
|
|
|
|
.addToTriangleBuffer(roofTb);
|
|
|
|
|
.addToTriangleBuffer(roofTopTb);
|
|
|
|
|
|
|
|
|
|
// Second angled box
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
@@ -1903,11 +1967,48 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
baseY + roof.baseHeight +
|
|
|
|
|
q / 2.0f - m / 2.0f,
|
|
|
|
|
origin.z))
|
|
|
|
|
.addToTriangleBuffer(roofTb);
|
|
|
|
|
.addToTriangleBuffer(roofTopTb);
|
|
|
|
|
|
|
|
|
|
// Side trim pieces (gable ends) -> roofSideTb
|
|
|
|
|
size_t sideVertexStart = roofSideTb.getVertices().size();
|
|
|
|
|
float sideY = baseY + q / 2.0f;
|
|
|
|
|
float sideHeight = q + roof.baseHeight * 3.0f;
|
|
|
|
|
|
|
|
|
|
// Z+ edge
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
.setSizeX(width + EXTEND * 2.0f)
|
|
|
|
|
.setSizeY(sideHeight)
|
|
|
|
|
.setSizeZ(EXTEND)
|
|
|
|
|
.setNumSegX(3)
|
|
|
|
|
.setNumSegY(3)
|
|
|
|
|
.setNumSegZ(1)
|
|
|
|
|
.setEnableNormals(true)
|
|
|
|
|
.setPosition(Ogre::Vector3(
|
|
|
|
|
origin.x, sideY + roof.baseHeight,
|
|
|
|
|
origin.z + depth / 2.0f + EXTEND / 2.0f))
|
|
|
|
|
.addToTriangleBuffer(roofSideTb);
|
|
|
|
|
|
|
|
|
|
// Z- edge
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
.setSizeX(width + EXTEND * 2.0f)
|
|
|
|
|
.setSizeY(sideHeight)
|
|
|
|
|
.setSizeZ(EXTEND)
|
|
|
|
|
.setNumSegX(3)
|
|
|
|
|
.setNumSegY(3)
|
|
|
|
|
.setNumSegZ(1)
|
|
|
|
|
.setEnableNormals(true)
|
|
|
|
|
.setPosition(Ogre::Vector3(
|
|
|
|
|
origin.x, sideY + roof.baseHeight,
|
|
|
|
|
origin.z - depth / 2.0f - EXTEND / 2.0f))
|
|
|
|
|
.addToTriangleBuffer(roofSideTb);
|
|
|
|
|
|
|
|
|
|
// Apply vertex deformation to side pieces
|
|
|
|
|
deformRoofSideVertices(roofSideTb, sideVertexStart, true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case RoofComponent::Normal2: {
|
|
|
|
|
// Gable roof along Z axis (ridge runs along X)
|
|
|
|
|
// Two angled boxes -> roofTopTb
|
|
|
|
|
float q = depth / 2.0f;
|
|
|
|
|
float m = 1.0f;
|
|
|
|
|
float d = Ogre::Math::Sqrt(2.0f) * (q + m);
|
|
|
|
|
@@ -1931,7 +2032,7 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
q / 2.0f - m / 2.0f,
|
|
|
|
|
origin.z - depth / 2.0f +
|
|
|
|
|
q / 2.0f - m / 2.0f))
|
|
|
|
|
.addToTriangleBuffer(roofTb);
|
|
|
|
|
.addToTriangleBuffer(roofTopTb);
|
|
|
|
|
|
|
|
|
|
// Second angled box
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
@@ -1951,19 +2052,58 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
q / 2.0f - m / 2.0f,
|
|
|
|
|
origin.z - depth / 2.0f + q +
|
|
|
|
|
q / 2.0f + m / 2.0f))
|
|
|
|
|
.addToTriangleBuffer(roofTb);
|
|
|
|
|
.addToTriangleBuffer(roofTopTb);
|
|
|
|
|
|
|
|
|
|
// Side trim pieces (gable ends) -> roofSideTb
|
|
|
|
|
size_t sideVertexStart = roofSideTb.getVertices().size();
|
|
|
|
|
float sideY = baseY + q / 2.0f;
|
|
|
|
|
float sideHeight = q + roof.baseHeight * 3.0f;
|
|
|
|
|
float sideDepth = depth + 2.0f * roof.baseHeight * 3.0f;
|
|
|
|
|
|
|
|
|
|
// X+ edge
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
.setSizeX(EXTEND)
|
|
|
|
|
.setSizeY(sideHeight)
|
|
|
|
|
.setSizeZ(sideDepth)
|
|
|
|
|
.setNumSegX(2)
|
|
|
|
|
.setNumSegY(2)
|
|
|
|
|
.setNumSegZ(1)
|
|
|
|
|
.setEnableNormals(true)
|
|
|
|
|
.setPosition(Ogre::Vector3(
|
|
|
|
|
origin.x + width / 2.0f + EXTEND / 2.0f,
|
|
|
|
|
sideY + roof.baseHeight, origin.z))
|
|
|
|
|
.addToTriangleBuffer(roofSideTb);
|
|
|
|
|
|
|
|
|
|
// X- edge
|
|
|
|
|
Procedural::BoxGenerator()
|
|
|
|
|
.setSizeX(EXTEND)
|
|
|
|
|
.setSizeY(sideHeight)
|
|
|
|
|
.setSizeZ(sideDepth)
|
|
|
|
|
.setNumSegX(2)
|
|
|
|
|
.setNumSegY(2)
|
|
|
|
|
.setNumSegZ(1)
|
|
|
|
|
.setEnableNormals(true)
|
|
|
|
|
.setPosition(Ogre::Vector3(
|
|
|
|
|
origin.x - width / 2.0f - EXTEND / 2.0f,
|
|
|
|
|
sideY + roof.baseHeight, origin.z))
|
|
|
|
|
.addToTriangleBuffer(roofSideTb);
|
|
|
|
|
|
|
|
|
|
// Apply vertex deformation to side pieces
|
|
|
|
|
deformRoofSideVertices(roofSideTb, sideVertexStart, false);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case RoofComponent::Cone: {
|
|
|
|
|
// Cone -> roofTopTb
|
|
|
|
|
Procedural::ConeGenerator cone;
|
|
|
|
|
cone.setRadius(width / 2.0f);
|
|
|
|
|
cone.setHeight(roof.baseHeight + height);
|
|
|
|
|
cone.setPosition(Ogre::Vector3(
|
|
|
|
|
origin.x, origin.y, origin.z));
|
|
|
|
|
cone.addToTriangleBuffer(roofTb);
|
|
|
|
|
cone.addToTriangleBuffer(roofTopTb);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case RoofComponent::Cylinder: {
|
|
|
|
|
// Cylinder -> roofTopTb
|
|
|
|
|
Procedural::CylinderGenerator cyl;
|
|
|
|
|
cyl.setRadius(width / 2.0f);
|
|
|
|
|
cyl.setHeight(roof.baseHeight);
|
|
|
|
|
@@ -1971,7 +2111,7 @@ void CellGridSystem::buildRoofs(flecs::entity cellGridEntity,
|
|
|
|
|
origin.x,
|
|
|
|
|
origin.y + roof.baseHeight / 2.0f,
|
|
|
|
|
origin.z));
|
|
|
|
|
cyl.addToTriangleBuffer(roofTb);
|
|
|
|
|
cyl.addToTriangleBuffer(roofTopTb);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -2043,6 +2183,7 @@ void CellGridSystem::destroyCellGridMeshes(flecs::entity entity)
|
|
|
|
|
removeMesh(it->second.intWallMesh);
|
|
|
|
|
removeMesh(it->second.intWindowsMesh);
|
|
|
|
|
removeMesh(it->second.roofMesh);
|
|
|
|
|
removeMesh(it->second.roofSideMesh);
|
|
|
|
|
for (const auto &name : it->second.doorMeshes) {
|
|
|
|
|
removeMesh(name);
|
|
|
|
|
}
|
|
|
|
|
|