Adjusted frame geometry

This commit is contained in:
2026-04-07 11:21:01 +03:00
parent 7d64ba30cb
commit 9f2f0be4a3

View File

@@ -1715,6 +1715,73 @@ void CellGridSystem::buildRoofs(flecs::entity lotEntity,
if (!lotEntity.has<LotComponent>())
return;
// Get material for roofs (prefer ProceduralMaterial from Lot/District/Town)
std::string materialName;
flecs::entity materialEntity = flecs::entity::null();
// Look for ProceduralMaterial in parent hierarchy
flecs::entity parent = lotEntity.parent();
while (parent.is_alive()) {
if (parent.has<LotComponent>()) {
auto &lot = parent.get<LotComponent>();
if (lot.proceduralMaterialEntity.is_alive() &&
lot.proceduralMaterialEntity
.has<ProceduralMaterialComponent>()) {
const auto &mat =
lot.proceduralMaterialEntity.get<
ProceduralMaterialComponent>();
if (mat.created && !mat.materialName.empty()) {
materialName = mat.materialName;
materialEntity =
lot.proceduralMaterialEntity;
break;
}
}
}
if (parent.has<DistrictComponent>()) {
auto &district = parent.get<DistrictComponent>();
if (district.proceduralMaterialEntity.is_alive() &&
district.proceduralMaterialEntity
.has<ProceduralMaterialComponent>()) {
const auto &mat =
district.proceduralMaterialEntity.get<
ProceduralMaterialComponent>();
if (mat.created && !mat.materialName.empty()) {
materialName = mat.materialName;
materialEntity =
district.proceduralMaterialEntity;
break;
}
}
}
if (parent.has<TownComponent>()) {
auto &town = parent.get<TownComponent>();
if (town.proceduralMaterialEntity.is_alive() &&
town.proceduralMaterialEntity
.has<ProceduralMaterialComponent>()) {
const auto &mat =
town.proceduralMaterialEntity.get<
ProceduralMaterialComponent>();
if (mat.created && !mat.materialName.empty()) {
materialName = mat.materialName;
materialEntity =
town.proceduralMaterialEntity;
break;
}
}
// Fall back to generated material
if (!town.materialName.empty()) {
materialName = town.materialName;
break;
}
}
parent = parent.parent();
}
// Get roof rect name for UV mapping
std::string roofRectName =
grid.extWallRectName; // Default to exterior wall color
// Get roof components from lot's children
lotEntity.children([&](flecs::entity child) {
if (child.has<RoofComponent>()) {
@@ -1728,38 +1795,187 @@ void CellGridSystem::buildRoofs(flecs::entity lotEntity,
float depth = roof.sizeZ * grid.cellSize;
float height = roof.maxHeight - roof.baseHeight;
// EXTEND constant for roof edges (like old code)
const float EXTEND = 0.2f;
switch (roof.type) {
case RoofComponent::Flat: {
Procedural::BoxGenerator box;
box.setSizeX(width);
box.setSizeY(roof.baseHeight);
box.setSizeZ(depth);
box.setPosition(Ogre::Vector3(
origin.x + width / 2.0f -
grid.cellSize / 2.0f,
origin.y + roof.baseHeight / 2.0f,
origin.z + depth / 2.0f -
grid.cellSize / 2.0f));
box.addToTriangleBuffer(roofTb);
// Main roof box
float baseY = origin.y + roof.baseHeight / 2.0f;
Procedural::BoxGenerator()
.setSizeX(width)
.setSizeY(roof.baseHeight)
.setSizeZ(depth)
.setNumSegY(1)
.setNumSegX(1)
.setNumSegZ(1)
.setEnableNormals(true)
.setPosition(Ogre::Vector3(
origin.x, baseY, origin.z))
.addToTriangleBuffer(roofTb);
// Edge trim pieces (Z+ edge)
float trimBaseY =
origin.y + roof.baseHeight / 2.0f;
Procedural::BoxGenerator()
.setSizeX(width)
.setSizeY(roof.baseHeight +
EXTEND * 2.0f)
.setSizeZ(EXTEND)
.setNumSegY(1)
.setNumSegX(1)
.setNumSegZ(1)
.setEnableNormals(true)
.setPosition(Ogre::Vector3(
origin.x, trimBaseY + EXTEND,
origin.z + depth / 2.0f +
EXTEND / 2.0f))
.addToTriangleBuffer(roofTb);
// Z- edge
Procedural::BoxGenerator()
.setSizeX(width)
.setSizeY(roof.baseHeight +
EXTEND * 2.0f)
.setSizeZ(EXTEND)
.setNumSegY(1)
.setNumSegX(1)
.setNumSegZ(1)
.setEnableNormals(true)
.setPosition(Ogre::Vector3(
origin.x, trimBaseY + EXTEND,
origin.z - depth / 2.0f -
EXTEND / 2.0f))
.addToTriangleBuffer(roofTb);
// X+ edge
Procedural::BoxGenerator()
.setSizeX(EXTEND)
.setSizeY(roof.baseHeight +
EXTEND * 2.0f)
.setSizeZ(depth + EXTEND * 2.0f)
.setNumSegY(1)
.setNumSegX(1)
.setNumSegZ(1)
.setEnableNormals(true)
.setPosition(Ogre::Vector3(
origin.x + width / 2.0f +
EXTEND / 2.0f,
trimBaseY + EXTEND, origin.z))
.addToTriangleBuffer(roofTb);
// X- edge
Procedural::BoxGenerator()
.setSizeX(EXTEND)
.setSizeY(roof.baseHeight +
EXTEND * 2.0f)
.setSizeZ(depth + EXTEND * 2.0f)
.setNumSegY(1)
.setNumSegX(1)
.setNumSegZ(1)
.setEnableNormals(true)
.setPosition(Ogre::Vector3(
origin.x - width / 2.0f -
EXTEND / 2.0f,
trimBaseY + EXTEND, origin.z))
.addToTriangleBuffer(roofTb);
break;
}
case RoofComponent::Normal: {
// Gable roof along X axis (ridge runs along Z)
// Two angled boxes forming a roof
float q = width / 2.0f;
float m = 1.0f;
float d = Ogre::Math::Sqrt(2.0f) * (q + m);
float baseY = origin.y;
// First angled box
Procedural::BoxGenerator()
.setSizeX(d)
.setSizeY(roof.baseHeight / 2.0f)
.setSizeZ(depth)
.setNumSegY(1)
.setNumSegX(1)
.setNumSegZ(1)
.setEnableNormals(true)
.setOrientation(Ogre::Quaternion(
Ogre::Degree(45),
Ogre::Vector3::NEGATIVE_UNIT_Z))
.setPosition(Ogre::Vector3(
origin.x - width / 2.0f + q +
q / 2.0f + m / 2.0f,
baseY + roof.baseHeight +
q / 2.0f - m / 2.0f,
origin.z))
.addToTriangleBuffer(roofTb);
// Second angled box
Procedural::BoxGenerator()
.setSizeX(d)
.setSizeY(roof.baseHeight / 2.0f)
.setSizeZ(depth)
.setNumSegY(1)
.setNumSegX(1)
.setNumSegZ(1)
.setEnableNormals(true)
.setOrientation(Ogre::Quaternion(
Ogre::Degree(-45),
Ogre::Vector3::NEGATIVE_UNIT_Z))
.setPosition(Ogre::Vector3(
origin.x - width / 2.0f +
q / 2.0f - m / 2.0f,
baseY + roof.baseHeight +
q / 2.0f - m / 2.0f,
origin.z))
.addToTriangleBuffer(roofTb);
break;
}
case RoofComponent::Normal:
case RoofComponent::Normal2: {
// Gable roof using two rotated boxes or a prism
// Simplified as a box for now
Procedural::BoxGenerator box;
box.setSizeX(width);
box.setSizeY(roof.baseHeight + height / 2.0f);
box.setSizeZ(depth);
box.setPosition(Ogre::Vector3(
origin.x + width / 2.0f -
grid.cellSize / 2.0f,
origin.y + (roof.baseHeight +
height / 2.0f) /
2.0f,
origin.z + depth / 2.0f -
grid.cellSize / 2.0f));
box.addToTriangleBuffer(roofTb);
// Gable roof along Z axis (ridge runs along X)
float q = depth / 2.0f;
float m = 1.0f;
float d = Ogre::Math::Sqrt(2.0f) * (q + m);
float baseY = origin.y;
// First angled box
Procedural::BoxGenerator()
.setSizeX(width)
.setSizeY(roof.baseHeight / 2.0f)
.setSizeZ(d)
.setNumSegY(1)
.setNumSegX(1)
.setNumSegZ(1)
.setEnableNormals(true)
.setOrientation(Ogre::Quaternion(
Ogre::Degree(45),
Ogre::Vector3::NEGATIVE_UNIT_X))
.setPosition(Ogre::Vector3(
origin.x,
baseY + roof.baseHeight +
q / 2.0f - m / 2.0f,
origin.z - depth / 2.0f +
q / 2.0f - m / 2.0f))
.addToTriangleBuffer(roofTb);
// Second angled box
Procedural::BoxGenerator()
.setSizeX(width)
.setSizeY(roof.baseHeight / 2.0f)
.setSizeZ(d)
.setNumSegX(1)
.setNumSegY(1)
.setNumSegZ(1)
.setEnableNormals(true)
.setOrientation(Ogre::Quaternion(
Ogre::Degree(-45),
Ogre::Vector3::NEGATIVE_UNIT_X))
.setPosition(Ogre::Vector3(
origin.x,
baseY + roof.baseHeight +
q / 2.0f - m / 2.0f,
origin.z - depth / 2.0f + q +
q / 2.0f + m / 2.0f))
.addToTriangleBuffer(roofTb);
break;
}
case RoofComponent::Cone: {
@@ -2846,7 +3062,7 @@ void CellGridSystem::createDoorFrameMeshes(const CellGridComponent &grid,
// Create external door frame mesh
Procedural::TriangleBuffer extFrameTb;
float stepDepth = frameDepth * 1.3f;
float stepDepth = frameDepth * 1.2f;
// Left frame with step
Procedural::BoxGenerator()
@@ -2893,16 +3109,28 @@ void CellGridSystem::createDoorFrameMeshes(const CellGridComponent &grid,
float stepWidth = doorWidth + frameThickness * 4;
Procedural::BoxGenerator()
.setSizeX(stepWidth)
.setSizeY(frameThickness)
.setSizeY(frameThickness * 2.0f)
.setSizeZ(stepDepth)
.setNumSegX(2)
.setNumSegY(1)
.setNumSegZ(1)
.setPosition(
Ogre::Vector3(0, frameThickness / 2 + 0.1f,
Ogre::Vector3(0, frameThickness,
(stepDepth - frameDepth) / 2 + 0.05f))
.setEnableNormals(true)
.addToTriangleBuffer(extFrameTb);
Procedural::BoxGenerator()
.setSizeX(stepWidth)
.setSizeY(frameThickness)
.setSizeZ(stepDepth)
.setNumSegX(2)
.setNumSegY(1)
.setNumSegZ(1)
.setPosition(Ogre::Vector3(0, frameThickness * 0.5f,
(stepDepth - frameDepth) / 2 +
0.05f + stepDepth))
.setEnableNormals(true)
.addToTriangleBuffer(extFrameTb);
applyUVMappingToBuffer(extFrameTb, grid.extDoorFrameRectName,
materialEntity);