The furniture is batched now

This commit is contained in:
2026-04-15 04:28:30 +03:00
parent 77f93659d5
commit c2a1db5a65
2 changed files with 105 additions and 32 deletions

View File

@@ -17,6 +17,7 @@
#include <OgreTechnique.h>
#include <OgrePass.h>
#include <OgreTextureManager.h>
#include <OgreMeshLodGenerator.h>
#include <ProceduralTriangleBuffer.h>
#include <ProceduralBoxGenerator.h>
#include <ProceduralPlaneGenerator.h>
@@ -487,7 +488,19 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
" roofTop=" + std::to_string(roofTopTb.getVertices().size()) +
" roofSide=" + std::to_string(roofSideTb.getVertices().size()));
// Build furniture
// Build window and door frames (creates StaticGeometry region)
try {
buildFrames(entity, grid, materialName);
} catch (const std::exception &e) {
Ogre::LogManager::getSingleton().logMessage(
"CellGrid: Error building frames: " +
std::string(e.what()));
} catch (...) {
Ogre::LogManager::getSingleton().logMessage(
"CellGrid: Unknown error building frames");
}
// Build furniture (non-isolated items go into the same StaticGeometry)
try {
buildFurniture(entity, grid);
} catch (const std::exception &e) {
@@ -499,16 +512,10 @@ void CellGridSystem::buildCellGrid(flecs::entity entity,
"CellGrid: Unknown error building furniture");
}
// Build window and door frames
try {
buildFrames(entity, grid, materialName);
} catch (const std::exception &e) {
Ogre::LogManager::getSingleton().logMessage(
"CellGrid: Error building frames: " +
std::string(e.what()));
} catch (...) {
Ogre::LogManager::getSingleton().logMessage(
"CellGrid: Unknown error building frames");
// Build combined static geometry (frames + batched furniture)
auto sgIt = m_entityMeshes.find(entity.id());
if (sgIt != m_entityMeshes.end() && sgIt->second.frameStaticGeometry) {
sgIt->second.frameStaticGeometry->build();
}
// Store texture dependency for automatic rebuild when texture changes
@@ -2250,6 +2257,7 @@ Ogre::MeshPtr CellGridSystem::convertToMesh(const std::string &name,
"CellGrid: convertToMesh '" + name + "' vertices=" +
std::to_string(tb.getVertices().size()) +
" material=" + materialName);
generateLodForMesh(mesh);
if (!materialName.empty() && mesh->getNumSubMeshes() > 0) {
mesh->getSubMesh(0)->setMaterialName(materialName);
Ogre::LogManager::getSingleton().logMessage(
@@ -2279,6 +2287,14 @@ void CellGridSystem::buildFurniture(flecs::entity entity,
FurnitureLibrary::getInstance().loadAll();
auto &meshData = m_entityMeshes[entity.id()];
Ogre::StaticGeometry *staticGeom = meshData.frameStaticGeometry;
Ogre::Vector3 parentPos = transform.node->_getDerivedPosition();
Ogre::Quaternion parentRot = transform.node->_getDerivedOrientation();
Ogre::Vector3 parentScale = transform.node->_getDerivedScale();
int batchedCount = 0;
for (const auto &fcell : grid.furnitureCells) {
const FurnitureDefinition *def =
FurnitureLibrary::getInstance().findByName(
@@ -2317,31 +2333,66 @@ void CellGridSystem::buildFurniture(flecs::entity entity,
continue;
}
Ogre::Entity *ent =
m_sceneMgr->createEntity(def->meshName);
if (!ent)
continue;
generateLodForMesh(mesh);
bool isolated = false;
for (const auto &tag : def->tags) {
if (tag == "isolated") {
isolated = true;
break;
}
}
Ogre::SceneNode *fnode =
transform.node->createChildSceneNode();
Ogre::Vector3 pos = grid.cellToWorld(fcell.x, fcell.y,
fcell.z);
// Apply small Y offset so furniture sits on floor
pos.y += 0.05f;
fnode->setPosition(pos);
fnode->setOrientation(Ogre::Quaternion(
Ogre::Quaternion localRot(
Ogre::Degree(90.0f * fcell.rotation),
Ogre::Vector3::UNIT_Y));
fnode->attachObject(ent);
ent->setRenderingDistance(100.0f);
Ogre::Vector3::UNIT_Y);
// Try to set material if mesh has submesh material
if (!mesh->getSubMesh(0)->getMaterialName().empty()) {
ent->setMaterialName(
mesh->getSubMesh(0)->getMaterialName());
if (!isolated && staticGeom) {
Ogre::Vector3 worldPos = parentPos +
(parentRot * (pos * parentScale));
Ogre::Quaternion worldRot = parentRot * localRot;
Ogre::Entity *tempEnt =
m_sceneMgr->createEntity(def->meshName);
if (!mesh->getSubMesh(0)->getMaterialName().empty()) {
tempEnt->setMaterialName(
mesh->getSubMesh(0)->getMaterialName());
}
staticGeom->addEntity(tempEnt, worldPos, worldRot,
parentScale);
m_sceneMgr->destroyEntity(tempEnt);
batchedCount++;
} else {
Ogre::Entity *ent =
m_sceneMgr->createEntity(def->meshName);
if (!ent)
continue;
Ogre::SceneNode *fnode =
transform.node->createChildSceneNode();
fnode->setPosition(pos);
fnode->setOrientation(localRot);
fnode->attachObject(ent);
ent->setRenderingDistance(100.0f);
if (!mesh->getSubMesh(0)->getMaterialName().empty()) {
ent->setMaterialName(
mesh->getSubMesh(0)->getMaterialName());
}
meshData.furnitureEntities.push_back(ent);
}
}
meshData.furnitureEntities.push_back(ent);
if (batchedCount > 0) {
Ogre::LogManager::getSingleton().logMessage(
"CellGrid: Batched " +
std::to_string(batchedCount) +
" furniture items into StaticGeometry");
}
}
@@ -2367,6 +2418,24 @@ void CellGridSystem::destroyFurniture(flecs::entity entity)
it->second.furnitureEntities.clear();
}
void CellGridSystem::generateLodForMesh(Ogre::MeshPtr mesh)
{
if (!mesh || !mesh->isLoaded())
return;
try {
Ogre::LodConfig config(mesh);
config.advanced.useVertexNormals = true;
config.advanced.preventPunchingHoles = true;
config.advanced.preventBreakingLines = true;
config.createGeneratedLodLevel(10.0f, 0.15f);
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(config);
} catch (const std::exception &e) {
Ogre::LogManager::getSingleton().logMessage(
"CellGrid: LOD generation failed for " +
mesh->getName() + ": " + e.what());
}
}
void CellGridSystem::destroyCellGridMeshes(CellGridComponent &grid)
{
// This is called from buildCellGrid which uses the entity ID as key in m_entityMeshes
@@ -3262,12 +3331,9 @@ void CellGridSystem::buildFrames(flecs::entity entity,
placeWindowFramesInStaticGeometry(entity, grid, parentPos, parentRot, parentScale, staticGeom, frameCount);
placeDoorFramesInStaticGeometry(entity, grid, parentPos, parentRot, parentScale, staticGeom, frameCount);
// Build the static geometry
staticGeom->build();
Ogre::LogManager::getSingleton().logMessage(
"CellGrid: Batched " + std::to_string(frameCount) +
" frames into StaticGeometry");
"CellGrid: Queued " + std::to_string(frameCount) +
" frames for StaticGeometry batching");
// Store reference
if (it != m_entityMeshes.end()) {
@@ -3366,6 +3432,7 @@ void CellGridSystem::createWindowFrameMeshes(const CellGridComponent &grid,
if (!materialName.empty() && extMesh->getNumSubMeshes() > 0) {
extMesh->getSubMesh(0)->setMaterialName(materialName);
}
generateLodForMesh(extMesh);
// Create internal window frame mesh (simpler, no sill)
Procedural::TriangleBuffer intFrameTb;
@@ -3417,6 +3484,7 @@ void CellGridSystem::createWindowFrameMeshes(const CellGridComponent &grid,
if (!materialName.empty() && intMesh->getNumSubMeshes() > 0) {
intMesh->getSubMesh(0)->setMaterialName(materialName);
}
generateLodForMesh(intMesh);
}
void CellGridSystem::createDoorFrameMeshes(const CellGridComponent &grid,
@@ -3521,6 +3589,7 @@ void CellGridSystem::createDoorFrameMeshes(const CellGridComponent &grid,
if (!materialName.empty() && extMesh->getNumSubMeshes() > 0) {
extMesh->getSubMesh(0)->setMaterialName(materialName);
}
generateLodForMesh(extMesh);
// Create internal door frame (simpler)
Procedural::TriangleBuffer intFrameTb;
@@ -3568,6 +3637,7 @@ void CellGridSystem::createDoorFrameMeshes(const CellGridComponent &grid,
if (!materialName.empty() && intMesh->getNumSubMeshes() > 0) {
intMesh->getSubMesh(0)->setMaterialName(materialName);
}
generateLodForMesh(intMesh);
}
void CellGridSystem::placeWindowFrames(

View File

@@ -87,6 +87,9 @@ private:
// Convert triangle buffer to mesh
Ogre::MeshPtr convertToMesh(const std::string& name, Procedural::TriangleBuffer& tb, const std::string& materialName);
// Generate LOD levels for a mesh (shared settings for all procedural editor meshes)
void generateLodForMesh(Ogre::MeshPtr mesh);
// Apply UV mapping from color rects
void applyUVMapping(Procedural::TriangleBuffer& tb, flecs::entity entity, const std::string& rectName);