The furniture is batched now
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user