From c2a1db5a65efbf95cdc2a61cc9dae0d17f32e37e Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Wed, 15 Apr 2026 04:28:30 +0300 Subject: [PATCH] The furniture is batched now --- .../editScene/systems/CellGridSystem.cpp | 134 +++++++++++++----- .../editScene/systems/CellGridSystem.hpp | 3 + 2 files changed, 105 insertions(+), 32 deletions(-) diff --git a/src/features/editScene/systems/CellGridSystem.cpp b/src/features/editScene/systems/CellGridSystem.cpp index 197d7b9..3d3647f 100644 --- a/src/features/editScene/systems/CellGridSystem.cpp +++ b/src/features/editScene/systems/CellGridSystem.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -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( diff --git a/src/features/editScene/systems/CellGridSystem.hpp b/src/features/editScene/systems/CellGridSystem.hpp index f2989f2..0189011 100644 --- a/src/features/editScene/systems/CellGridSystem.hpp +++ b/src/features/editScene/systems/CellGridSystem.hpp @@ -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);