Furniture placement

This commit is contained in:
2026-01-09 22:27:51 +03:00
parent 272e202774
commit f86e7fd96c
11 changed files with 1089 additions and 326 deletions

View File

@@ -1372,8 +1372,81 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
cursorPosition);
modified = false;
}
}
ImGui::EndMenuBar();
}
if (ImGui::BeginMenu("Furniture")) {
if (ImGui::BeginMenu("Create New Furniture")) {
static char nameBuffer[32];
static int current_mesh = 0;
static std::vector<Ogre::String>
glb_names;
const std::vector<Ogre::String> &groups =
Ogre::ResourceGroupManager::
getSingleton()
.getResourceGroups();
if (glb_names.size() == 0) {
int i;
glb_names.push_back("");
for (i = 0; i < groups.size();
i++) {
std::vector<Ogre::String> names =
*Ogre::ResourceGroupManager::getSingleton()
.findResourceNames(
groups[i],
"furniture-*.glb");
glb_names.insert(
glb_names.end(),
names.begin(),
names.end());
}
}
ImGui::InputText(
"Furniture Name", nameBuffer,
IM_ARRAYSIZE(nameBuffer));
if (glb_names.size() > 0) {
if (ImGui::BeginCombo(
"Furniture Mesh",
glb_names[current_mesh]
.c_str())) {
int i;
for (i = 0;
i <
glb_names.size();
i++) {
bool isSelected =
i ==
current_mesh;
if (ImGui::Selectable(
(glb_names[i] +
"##select" +
Ogre::StringConverter::
toString(
i))
.c_str(),
isSelected)) {
current_mesh =
i;
}
if (isSelected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
} else
ImGui::Text(
"No furniture meshes found");
if (ImGui::MenuItem(
"Create Furniture")) {
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Edit Furniture")) {
if (ImGui::MenuItem("Edit Furniture")) {
}
ImGui::EndMenu();
}
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
ImGui::Spacing();
ImGui::BeginChild("WorldMap...", ImVec2(480, 480),

View File

@@ -19,13 +19,15 @@ namespace ECS
{
static bool itemsLoaded = false;
static bool furnitureLoaded = false;
static std::list<std::pair<long, long> > addQueue;
StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
{
ecs.module<StaticGeometryModule>();
ecs.component<TerrainSlotParent>();
ecs.component<TerrainItem>();
ecs.component<TerrainItemNode>().on_remove([](flecs::entity e,
ecs.component<FurnitureItem>();
ecs.component<TerrainItemNode>().on_remove([](flecs::entity e,
TerrainItemNode &item) {
if (item.itemNode) {
item.itemNode->destroyAllChildrenAndObjects();
@@ -60,6 +62,10 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
itemsLoaded = true;
return;
}
if (!furnitureLoaded) {
loadFurniture();
furnitureLoaded = true;
}
std::list<std::pair<long, long> > output;
while (!addQueue.empty()) {
std::pair<long, long> item = addQueue.front();
@@ -271,93 +277,141 @@ void StaticGeometryModule::loadItems()
<< std::endl;
std::cout << "position: " << item.id() << " " << position
<< std::endl;
}
}
}
void StaticGeometryModule::saveFurniture()
{
/* No saving - furniture is generated by blender */
}
void StaticGeometryModule::loadFurniture()
{
ECS::get().delete_with<FurnitureItem>();
static std::vector<Ogre::String> glb_names;
const std::vector<Ogre::String> &groups =
Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
if (glb_names.size() == 0) {
int i;
for (i = 0; i < groups.size(); i++) {
std::vector<Ogre::String> names =
*Ogre::ResourceGroupManager::getSingleton()
.findResourceNames(
groups[i],
"furniture-*.glb.json");
glb_names.insert(glb_names.end(), names.begin(),
names.end());
}
}
for (auto &g : glb_names) {
Ogre::String group = Ogre::ResourceGroupManager::getSingleton()
.findGroupContainingResource(g);
Ogre::DataStreamPtr stream =
Ogre::ResourceGroupManager::getSingleton().openResource(
g, group);
Ogre::String json = stream->getAsString();
nlohmann::json jdata = nlohmann::json::parse(json);
std::vector<Ogre::String> tags;
for (auto &tag : jdata["tags"]) {
Ogre::String stag = tag.get<Ogre::String>();
tags.push_back(stag);
}
Ogre::String meshName = jdata["mesh"].get<Ogre::String>();
Ogre::MeshPtr mesh =
Ogre::MeshManager::getSingleton().getByName(meshName);
if (mesh) {
Ogre::LodConfig meshconf(mesh);
Geometry::setupLods(meshconf);
}
ECS::get().entity().set<FurnitureItem>({ json, tags });
std::cout << "path: " << g << std::endl;
}
}
void StaticGeometryModule::getItemPositionPerSlot(
long x, long y, std::list<Ogre::Vector3> *positions)
long x, long y, std::list<Ogre::Vector3> *positions)
{
std::pair<long, long> pos{ x, y };
if (!positions)
return;
flecs::entity slot =
ECS::get().query_builder<const TerrainSlotParent>().build().find(
[&](const TerrainSlotParent &slot) -> bool {
return slot.slot == pos;
std::pair<long, long> pos{ x, y };
if (!positions)
return;
flecs::entity slot =
ECS::get().query_builder<const TerrainSlotParent>().build().find(
[&](const TerrainSlotParent &slot) -> bool {
return slot.slot == pos;
});
if (!slot.is_valid())
return;
ECS::get()
.query_builder<const TerrainItem>()
.with(flecs::ChildOf, slot)
.build()
.each([&](flecs::entity e, const TerrainItem &item) {
positions->push_back(item.position);
});
if (!slot.is_valid())
return;
ECS::get()
.query_builder<const TerrainItem>()
.with(flecs::ChildOf, slot)
.build()
.each([&](flecs::entity e, const TerrainItem &item) {
positions->push_back(item.position);
});
}
void StaticGeometryModule::getItemPositions(std::list<Ogre::Vector3> *positions)
{
ECS::get().query_builder<const TerrainItem>().build().each(
[&](flecs::entity e, const TerrainItem &item) {
positions->push_back(item.position);
});
ECS::get().query_builder<const TerrainItem>().build().each(
[&](flecs::entity e, const TerrainItem &item) {
positions->push_back(item.position);
});
}
void StaticGeometryModule::getItemPositionAndRotation(
flecs::entity e, Ogre::Vector3 &position, Ogre::Quaternion &orientation)
flecs::entity e, Ogre::Vector3 &position, Ogre::Quaternion &orientation)
{
position = e.get<TerrainItem>().position;
orientation = e.get<TerrainItem>().orientation;
position = e.get<TerrainItem>().position;
orientation = e.get<TerrainItem>().orientation;
}
void StaticGeometryModule::getItemsProperties(
std::list<std::pair<flecs::entity, Ogre::String> > *items)
std::list<std::pair<flecs::entity, Ogre::String> > *items)
{
ECS::get().query_builder<const TerrainItem>().build().each(
[&](flecs::entity e, const TerrainItem &item) {
items->push_back({ e, item.properties });
});
ECS::get().query_builder<const TerrainItem>().build().each(
[&](flecs::entity e, const TerrainItem &item) {
items->push_back({ e, item.properties });
});
}
void StaticGeometryModule::createItemGeometry(flecs::entity e)
{
Geometry::createItemGeometry(e);
Geometry::createItemGeometry(e);
}
void StaticGeometryModule::destroyItemGeometry(flecs::entity e)
{
Geometry::destroyItemGeometry(e);
Geometry::destroyItemGeometry(e);
}
struct TiledMeshes {
struct Tile {
Ogre::String materialName;
std::shared_ptr<Ogre::VertexData> vertexData;
std::shared_ptr<Ogre::IndexData> indexData;
std::set<uint32_t> positions;
};
std::map<Ogre::String, Tile> tiles;
uint32_t packKey(const Ogre::Vector3i &position)
struct Tile {
Ogre::String materialName;
std::shared_ptr<Ogre::VertexData> vertexData;
std::shared_ptr<Ogre::IndexData> indexData;
std::set<uint32_t> positions;
};
std::map<Ogre::String, Tile> tiles;
uint32_t packKey(const Ogre::Vector3i &position)
{
uint32_t key = 0;
key |= (uint32_t)(position[2] + 512) << 20;
key |= (uint32_t)(position[1] + 512) << 10;
key |= (uint32_t)(position[0] + 512) << 0;
return key;
uint32_t key = 0;
key |= (uint32_t)(position[2] + 512) << 20;
key |= (uint32_t)(position[1] + 512) << 10;
key |= (uint32_t)(position[0] + 512) << 0;
return key;
}
void unpackKey(uint32_t key, Ogre::Vector3i &position)
void unpackKey(uint32_t key, Ogre::Vector3i &position)
{
uint32_t mask = 0x3ff;
position[0] = (int)(key & mask) - 512;
position[1] = (int)((key >> 10) & mask) - 512;
position[2] = (int)((key >> 20) & mask) - 512;
uint32_t mask = 0x3ff;
position[0] = (int)(key & mask) - 512;
position[1] = (int)((key >> 10) & mask) - 512;
position[2] = (int)((key >> 20) & mask) - 512;
}
void setTile(const Ogre::String &name, const Ogre::Vector3i &position)
void setTile(const Ogre::String &name, const Ogre::Vector3i &position)
{
if (tiles.find(name) == tiles.end())
return;
tiles[name].positions.insert(packKey(position));
if (tiles.find(name) == tiles.end())
return;
tiles[name].positions.insert(packKey(position));
}
void clearTile(const Ogre::String &name, const Ogre::Vector3i &position)
void clearTile(const Ogre::String &name, const Ogre::Vector3i &position)
{
if (tiles.find(name) == tiles.end())
return;
tiles[name].positions.erase(packKey(position));
if (tiles.find(name) == tiles.end())
return;
tiles[name].positions.erase(packKey(position));
#if 0
auto pos = std::find(tiles[name].positions.begin(),
tiles[name].positions.end(),
@@ -365,22 +419,22 @@ struct TiledMeshes {
if (pos != tiles[name].positions.end())
tiles[name].positions.erase(pos);
#endif
}
void addTile(const Ogre::String &name, Ogre::MeshPtr mesh)
{
if (mesh->getSubMeshes().size() != 1)
return;
Ogre::SubMesh *submesh = mesh->getSubMesh(0);
Ogre::VertexData *vertexData;
if (submesh->useSharedVertices)
vertexData = mesh->sharedVertexData->clone();
else
vertexData = submesh->vertexData->clone();
tiles[name] = { submesh->getMaterialName(),
std::shared_ptr<Ogre::VertexData>(vertexData),
std::shared_ptr<Ogre::IndexData>(
submesh->indexData->clone()),
{} };
}
void addTile(const Ogre::String &name, Ogre::MeshPtr mesh)
{
if (mesh->getSubMeshes().size() != 1)
return;
Ogre::SubMesh *submesh = mesh->getSubMesh(0);
Ogre::VertexData *vertexData;
if (submesh->useSharedVertices)
vertexData = mesh->sharedVertexData->clone();
else
vertexData = submesh->vertexData->clone();
tiles[name] = { submesh->getMaterialName(),
std::shared_ptr<Ogre::VertexData>(vertexData),
std::shared_ptr<Ogre::IndexData>(
submesh->indexData->clone()),
{} };
#if 0
std::vector<Ogre::Vector3> vertices;
std::vector<uint32_t> indices;
@@ -477,257 +531,256 @@ struct TiledMeshes {
currentVertexOffset = vertices.size();
}
#endif
}
struct buildSettings {
Ogre::String meshName;
Ogre::String materialName;
Ogre::MeshPtr mesh;
Ogre::SubMesh *sm;
int vertexCount, vertexOffset;
int indexCount, indexOffset;
Ogre::VertexDeclaration *vdecl;
Ogre::HardwareVertexBufferSharedPtr vbuf;
Ogre::AxisAlignedBox bounds;
bool setBounds;
};
void configureSettings(struct buildSettings &settings)
{
settings.mesh = Ogre::MeshManager::getSingleton().createManual(
settings.meshName,
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
settings.mesh->createVertexData();
settings.sm = settings.mesh->createSubMesh();
settings.vertexCount = 0;
settings.indexCount = 0;
settings.vdecl = nullptr;
for (const auto &tile : tiles) {
settings.vertexCount +=
tile.second.vertexData->vertexCount *
tile.second.positions.size();
settings.indexCount +=
tile.second.indexData->indexCount *
tile.second.positions.size();
if (!settings.vdecl) {
settings.vdecl =
tile.second.vertexData
->vertexDeclaration->clone();
settings.materialName =
tile.second.materialName;
}
struct buildSettings {
Ogre::String meshName;
Ogre::String materialName;
Ogre::MeshPtr mesh;
Ogre::SubMesh *sm;
int vertexCount, vertexOffset;
int indexCount, indexOffset;
Ogre::VertexDeclaration *vdecl;
Ogre::HardwareVertexBufferSharedPtr vbuf;
Ogre::AxisAlignedBox bounds;
bool setBounds;
};
void configureSettings(struct buildSettings &settings)
{
settings.mesh = Ogre::MeshManager::getSingleton().createManual(
settings.meshName,
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
settings.mesh->createVertexData();
settings.sm = settings.mesh->createSubMesh();
settings.vertexCount = 0;
settings.indexCount = 0;
settings.vdecl = nullptr;
for (const auto &tile : tiles) {
settings.vertexCount +=
tile.second.vertexData->vertexCount *
tile.second.positions.size();
settings.indexCount +=
tile.second.indexData->indexCount *
tile.second.positions.size();
if (!settings.vdecl) {
settings.vdecl =
tile.second.vertexData
->vertexDeclaration->clone();
settings.materialName =
tile.second.materialName;
}
}
settings.mesh->sharedVertexData->vertexStart = 0;
settings.mesh->sharedVertexData->vertexCount =
settings.vertexCount;
settings.mesh->sharedVertexData->vertexDeclaration =
settings.vdecl;
settings.vbuf =
Ogre::HardwareBufferManager::getSingleton()
.createVertexBuffer(
settings.vdecl->getVertexSize(0),
settings.vertexCount,
Ogre::HBU_GPU_ONLY);
settings.mesh->sharedVertexData->vertexBufferBinding->setBinding(
0, settings.vbuf);
settings.sm->indexData->indexStart = 0;
settings.sm->indexData->indexCount = settings.indexCount;
settings.sm->indexData->indexBuffer =
Ogre::HardwareBufferManager::getSingleton()
.createIndexBuffer(
Ogre::HardwareIndexBuffer::IT_32BIT,
settings.sm->indexData->indexCount * 8,
Ogre::HBU_GPU_ONLY);
settings.sm->setMaterialName(settings.materialName);
settings.setBounds = true;
}
void processIndex(struct buildSettings &settings,
const struct Tile &tile, unsigned int *dstIndices)
{
int j;
std::shared_ptr<Ogre::IndexData> srcIndexData = tile.indexData;
int srcIndexCount = srcIndexData->indexCount;
std::shared_ptr<Ogre::VertexData> srcVertexData =
tile.vertexData;
int srcVertexCount = srcVertexData->vertexCount;
Ogre::HardwareIndexBufferSharedPtr srcIbuf =
srcIndexData->indexBuffer;
Ogre::HardwareBufferLockGuard srcIndexLock(
srcIbuf, Ogre::HardwareBuffer::HBL_READ_ONLY);
if (srcIndexData->indexBuffer->getType() ==
Ogre::HardwareIndexBuffer::IT_32BIT) {
unsigned int *indices =
static_cast<unsigned int *>(srcIndexLock.pData);
for (j = 0; j < srcIndexCount; j++)
dstIndices[settings.indexOffset + j] =
indices[j] + settings.vertexOffset;
} else if (srcIndexData->indexBuffer->getType() ==
Ogre::HardwareIndexBuffer::IT_16BIT) {
unsigned short *indices = static_cast<unsigned short *>(
srcIndexLock.pData);
for (j = 0; j < srcIndexCount; j++)
dstIndices[settings.indexOffset + j] =
indices[j] + settings.vertexOffset;
}
}
void processSingleVertex(
struct buildSettings &settings,
const Ogre::VertexDeclaration::VertexElementList &srcElements,
uint32_t offset, unsigned char *srcData, unsigned char *dstData)
{
for (const auto &srcElement : srcElements) {
unsigned char *srcPtr, *dstPtr;
const Ogre::VertexElement *destElement =
settings.vdecl->findElementBySemantic(
srcElement.getSemantic(),
srcElement.getIndex());
if (!destElement)
goto out;
if (srcElement.getType() != destElement->getType() ||
srcElement.getSize() != destElement->getSize())
goto out;
srcPtr = srcData + srcElement.getOffset();
dstPtr = dstData + destElement->getOffset();
if (destElement->getSemantic() == Ogre::VES_POSITION) {
float *srcPositionData =
reinterpret_cast<float *>(srcPtr);
float *dstPositionData =
reinterpret_cast<float *>(dstPtr);
Ogre::Vector3 position(srcPositionData[0],
srcPositionData[1],
srcPositionData[2]);
Ogre::Vector3i offsetv;
unpackKey(offset, offsetv);
position.x += (float)offsetv[0];
position.y += (float)offsetv[1];
position.z += (float)offsetv[2];
dstPositionData[0] = position.x;
dstPositionData[1] = position.y;
dstPositionData[2] = position.z;
if (settings.setBounds) {
settings.bounds.setMinimum(position);
settings.bounds.setMaximum(position);
settings.setBounds = false;
settings.mesh->sharedVertexData->vertexStart = 0;
settings.mesh->sharedVertexData->vertexCount =
settings.vertexCount;
settings.mesh->sharedVertexData->vertexDeclaration =
settings.vdecl;
settings.vbuf =
Ogre::HardwareBufferManager::getSingleton()
.createVertexBuffer(
settings.vdecl->getVertexSize(0),
settings.vertexCount,
Ogre::HBU_GPU_ONLY);
settings.mesh->sharedVertexData->vertexBufferBinding->setBinding(
0, settings.vbuf);
settings.sm->indexData->indexStart = 0;
settings.sm->indexData->indexCount = settings.indexCount;
settings.sm->indexData->indexBuffer =
Ogre::HardwareBufferManager::getSingleton()
.createIndexBuffer(
Ogre::HardwareIndexBuffer::IT_32BIT,
settings.sm->indexData->indexCount * 8,
Ogre::HBU_GPU_ONLY);
settings.sm->setMaterialName(settings.materialName);
settings.setBounds = true;
}
void processIndex(struct buildSettings &settings,
const struct Tile &tile, unsigned int *dstIndices)
{
int j;
std::shared_ptr<Ogre::IndexData> srcIndexData = tile.indexData;
int srcIndexCount = srcIndexData->indexCount;
std::shared_ptr<Ogre::VertexData> srcVertexData =
tile.vertexData;
int srcVertexCount = srcVertexData->vertexCount;
Ogre::HardwareIndexBufferSharedPtr srcIbuf =
srcIndexData->indexBuffer;
Ogre::HardwareBufferLockGuard srcIndexLock(
srcIbuf, Ogre::HardwareBuffer::HBL_READ_ONLY);
if (srcIndexData->indexBuffer->getType() ==
Ogre::HardwareIndexBuffer::IT_32BIT) {
unsigned int *indices =
static_cast<unsigned int *>(srcIndexLock.pData);
for (j = 0; j < srcIndexCount; j++)
dstIndices[settings.indexOffset + j] =
indices[j] + settings.vertexOffset;
} else if (srcIndexData->indexBuffer->getType() ==
Ogre::HardwareIndexBuffer::IT_16BIT) {
unsigned short *indices = static_cast<unsigned short *>(
srcIndexLock.pData);
for (j = 0; j < srcIndexCount; j++)
dstIndices[settings.indexOffset + j] =
indices[j] + settings.vertexOffset;
}
}
void processSingleVertex(
struct buildSettings &settings,
const Ogre::VertexDeclaration::VertexElementList &srcElements,
uint32_t offset, unsigned char *srcData, unsigned char *dstData)
{
for (const auto &srcElement : srcElements) {
unsigned char *srcPtr, *dstPtr;
const Ogre::VertexElement *destElement =
settings.vdecl->findElementBySemantic(
srcElement.getSemantic(),
srcElement.getIndex());
if (!destElement)
goto out;
if (srcElement.getType() != destElement->getType() ||
srcElement.getSize() != destElement->getSize())
goto out;
srcPtr = srcData + srcElement.getOffset();
dstPtr = dstData + destElement->getOffset();
if (destElement->getSemantic() == Ogre::VES_POSITION) {
float *srcPositionData =
reinterpret_cast<float *>(srcPtr);
float *dstPositionData =
reinterpret_cast<float *>(dstPtr);
Ogre::Vector3 position(srcPositionData[0],
srcPositionData[1],
srcPositionData[2]);
Ogre::Vector3i offsetv;
unpackKey(offset, offsetv);
position.x += (float)offsetv[0];
position.y += (float)offsetv[1];
position.z += (float)offsetv[2];
dstPositionData[0] = position.x;
dstPositionData[1] = position.y;
dstPositionData[2] = position.z;
if (settings.setBounds) {
settings.bounds.setMinimum(position);
settings.bounds.setMaximum(position);
settings.setBounds = false;
} else
settings.bounds.merge(position);
} else if (destElement->getSemantic() ==
Ogre::VES_NORMAL) {
float *srcNormalData =
reinterpret_cast<float *>(srcPtr);
float *dstNormalData =
reinterpret_cast<float *>(dstPtr);
Ogre::Vector3 normal(srcNormalData[0],
srcNormalData[1],
srcNormalData[2]);
dstNormalData[0] = normal.x;
dstNormalData[1] = normal.y;
dstNormalData[2] = normal.z;
} else
memcpy(dstPtr, srcPtr, srcElement.getSize());
settings.bounds.merge(position);
} else if (destElement->getSemantic() ==
Ogre::VES_NORMAL) {
float *srcNormalData =
reinterpret_cast<float *>(srcPtr);
float *dstNormalData =
reinterpret_cast<float *>(dstPtr);
Ogre::Vector3 normal(srcNormalData[0],
srcNormalData[1],
srcNormalData[2]);
dstNormalData[0] = normal.x;
dstNormalData[1] = normal.y;
dstNormalData[2] = normal.z;
} else
memcpy(dstPtr, srcPtr, srcElement.getSize());
out:;
}
}
void processTile(struct buildSettings &settings,
const struct Tile &tile, uint32_t position,
unsigned char *dstpData)
{
std::shared_ptr<Ogre::VertexData> srcVertexData =
tile.vertexData;
const Ogre::VertexDeclaration *srcDecl =
srcVertexData->vertexDeclaration;
const Ogre::VertexBufferBinding *srcBind =
srcVertexData->vertexBufferBinding;
int srcVertexCount = srcVertexData->vertexCount;
Ogre::HardwareVertexBufferSharedPtr srcVbuf =
srcBind->getBuffer(0);
std::shared_ptr<Ogre::IndexData> srcIndexData = tile.indexData;
int srcIndexCount = srcIndexData->indexCount;
}
}
void processTile(struct buildSettings &settings,
const struct Tile &tile, uint32_t position,
unsigned char *dstpData)
{
std::shared_ptr<Ogre::VertexData> srcVertexData =
tile.vertexData;
const Ogre::VertexDeclaration *srcDecl =
srcVertexData->vertexDeclaration;
const Ogre::VertexBufferBinding *srcBind =
srcVertexData->vertexBufferBinding;
int srcVertexCount = srcVertexData->vertexCount;
Ogre::HardwareVertexBufferSharedPtr srcVbuf =
srcBind->getBuffer(0);
std::shared_ptr<Ogre::IndexData> srcIndexData = tile.indexData;
int srcIndexCount = srcIndexData->indexCount;
Ogre::HardwareBufferLockGuard srcVertexLock(
srcVbuf, 0, srcVertexCount * srcDecl->getVertexSize(0),
Ogre::HardwareBuffer::HBL_READ_ONLY);
const Ogre::VertexDeclaration::VertexElementList &srcElements =
srcDecl->getElements();
int j;
unsigned char *srcpData =
static_cast<unsigned char *>(srcVertexLock.pData);
Ogre::HardwareBufferLockGuard srcVertexLock(
srcVbuf, 0, srcVertexCount * srcDecl->getVertexSize(0),
Ogre::HardwareBuffer::HBL_READ_ONLY);
const Ogre::VertexDeclaration::VertexElementList &srcElements =
srcDecl->getElements();
int j;
unsigned char *srcpData =
static_cast<unsigned char *>(srcVertexLock.pData);
for (j = 0; j < srcVertexCount; j++) {
unsigned char *srcData =
srcpData + j * srcVbuf->getVertexSize();
unsigned char *dstData =
dstpData + (settings.vertexOffset +
j) * settings.vbuf->getVertexSize();
processSingleVertex(settings, srcElements, position,
srcData, dstData);
for (j = 0; j < srcVertexCount; j++) {
unsigned char *srcData =
srcpData + j * srcVbuf->getVertexSize();
unsigned char *dstData =
dstpData + (settings.vertexOffset +
j) * settings.vbuf->getVertexSize();
processSingleVertex(settings, srcElements, position,
srcData, dstData);
}
}
Ogre::MeshPtr build(const Ogre::String &meshName)
{
buildSettings settings;
settings.meshName = meshName;
configureSettings(settings);
}
Ogre::MeshPtr build(const Ogre::String &meshName)
{
buildSettings settings;
settings.meshName = meshName;
configureSettings(settings);
{
Ogre::HardwareBufferLockGuard vertexLock(
settings.vbuf, 0,
settings.vertexCount *
settings.vdecl->getVertexSize(0),
Ogre::HardwareBuffer::HBL_NO_OVERWRITE);
Ogre::HardwareBufferLockGuard indexLock(
settings.sm->indexData->indexBuffer,
Ogre::HardwareBuffer::HBL_NO_OVERWRITE);
settings.vertexOffset = 0;
settings.indexOffset = 0;
unsigned char *dstpData =
static_cast<unsigned char *>(vertexLock.pData);
unsigned int *dstIndices =
static_cast<unsigned int *>(indexLock.pData);
Ogre::HardwareBufferLockGuard vertexLock(
settings.vbuf, 0,
settings.vertexCount *
settings.vdecl->getVertexSize(0),
Ogre::HardwareBuffer::HBL_NO_OVERWRITE);
Ogre::HardwareBufferLockGuard indexLock(
settings.sm->indexData->indexBuffer,
Ogre::HardwareBuffer::HBL_NO_OVERWRITE);
settings.vertexOffset = 0;
settings.indexOffset = 0;
unsigned char *dstpData =
static_cast<unsigned char *>(vertexLock.pData);
unsigned int *dstIndices =
static_cast<unsigned int *>(indexLock.pData);
for (const auto &tile : tiles) {
std::shared_ptr<Ogre::IndexData> srcIndexData =
tile.second.indexData;
int srcIndexCount = srcIndexData->indexCount;
std::shared_ptr<Ogre::VertexData> srcVertexData =
tile.second.vertexData;
int srcVertexCount = srcVertexData->vertexCount;
for (const auto &position :
tile.second.positions) {
processTile(settings, tile.second,
position, dstpData);
processIndex(settings, tile.second,
dstIndices);
settings.vertexOffset += srcVertexCount;
settings.indexOffset += srcIndexCount;
Ogre::Vector3i vposition;
unpackKey(position, vposition);
std::cout << "position: " << position
<< " " << vposition
<< std::endl;
for (const auto &tile : tiles) {
std::shared_ptr<Ogre::IndexData> srcIndexData =
tile.second.indexData;
int srcIndexCount = srcIndexData->indexCount;
std::shared_ptr<Ogre::VertexData> srcVertexData =
tile.second.vertexData;
int srcVertexCount = srcVertexData->vertexCount;
for (const auto &position :
tile.second.positions) {
processTile(settings, tile.second,
position, dstpData);
processIndex(settings, tile.second,
dstIndices);
settings.vertexOffset += srcVertexCount;
settings.indexOffset += srcIndexCount;
Ogre::Vector3i vposition;
unpackKey(position, vposition);
std::cout << "position: " << position
<< " " << vposition
<< std::endl;
}
}
settings.mesh->_setBounds(settings.bounds);
}
Ogre::LodConfig config(settings.mesh);
// config.advanced.useCompression = false;
// config.advanced.useVertexNormals = true;
config.advanced.preventPunchingHoles = true;
config.advanced.preventBreakingLines = true;
config.createGeneratedLodLevel(2, 0.15f);
config.createGeneratedLodLevel(20, 0.49f);
}
settings.mesh->_setBounds(settings.bounds);
}
Ogre::LodConfig config(settings.mesh);
// config.advanced.useCompression = false;
// config.advanced.useVertexNormals = true;
config.advanced.preventPunchingHoles = true;
config.advanced.preventBreakingLines = true;
config.createGeneratedLodLevel(2, 0.15f);
config.createGeneratedLodLevel(20, 0.49f);
#if 0
config.createGeneratedLodLevel(15, 0.49f);
config.createGeneratedLodLevel(150, 0.75f);
#endif
config.advanced.useBackgroundQueue = false;
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(
config);
return settings.mesh;
}
void removeTile(const Ogre::String &name)
{
tiles.erase(name);
}
TiledMeshes()
{
}
config.advanced.useBackgroundQueue = false;
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(
config);
return settings.mesh;
}
void removeTile(const Ogre::String &name)
{
tiles.erase(name);
}
TiledMeshes()
{
}
};
}

View File

@@ -25,6 +25,11 @@ struct TerrainItemMeshNode {
Ogre::SceneNode *itemNode;
Ogre::StaticGeometry *geo;
};
struct FurnitureItem {
Ogre::String properties;
std::vector<Ogre::String> tags;
};
struct TownCollider {};
struct StaticGeometryModule {
@@ -39,6 +44,8 @@ struct StaticGeometryModule {
static const Ogre::String &getItemProperties(flecs::entity id);
static void saveItems();
static void loadItems();
static void saveFurniture();
static void loadFurniture();
static void getItemPositionPerSlot(long x, long y,
std::list<Ogre::Vector3> *positions);
static void getItemPositions(std::list<Ogre::Vector3> *positions);

View File

@@ -199,9 +199,9 @@ void setupLods(Ogre::LodConfig &config)
config.advanced.preventPunchingHoles = true;
config.advanced.preventBreakingLines = true;
config.createGeneratedLodLevel(10, 0.15f);
config.createGeneratedLodLevel(50, 0.25f);
config.createGeneratedLodLevel(100, 0.36f);
config.createGeneratedLodLevel(200, 0.50f);
// config.createGeneratedLodLevel(50, 0.25f);
// config.createGeneratedLodLevel(100, 0.36f);
// config.createGeneratedLodLevel(200, 0.50f);
config.createGeneratedLodLevel(500, 0.85f);
config.advanced.useBackgroundQueue = false;
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(config);

View File

@@ -19,7 +19,7 @@
#include "items.h"
#include "town.h"
/* TODO: Create roofs with the same Lua script as tiles.
/*
* TODO: Create doors and handle them via script.
* TODO: Handle doors direction.
* TODO: Hide hero mesh if camera is too close.
@@ -174,6 +174,7 @@ struct CellsScript {
Ogre::String cellScript;
nlohmann::json &lot;
nlohmann::json &cells;
nlohmann::json &fucells;
CellsScript(const Ogre::String &cellScript, nlohmann::json &lot)
: L(luaL_newstate())
, currentX(0)
@@ -182,6 +183,7 @@ struct CellsScript {
, cellScript(cellScript)
, lot(lot)
, cells(lot["cells"])
, fucells(lot["furniture_cells"])
{
lua_pushlightuserdata(L, this);
lua_pushcclosure(
@@ -277,6 +279,19 @@ struct CellsScript {
1);
lua_setglobal(L, "roof");
lua_pushlightuserdata(L, this);
lua_pushcclosure(
L,
[](lua_State *L) -> int {
CellsScript *_this = static_cast<CellsScript *>(
lua_touserdata(L, lua_upvalueindex(1)));
int room = lua_tointeger(L, 1);
Ogre::String tags = lua_tostring(L, 2);
_this->place_furniture(room, tags);
return 0;
},
1);
lua_setglobal(L, "place_furniture");
lua_pushlightuserdata(L, this);
lua_pushcclosure(
L,
[](lua_State *L) -> int {
@@ -292,6 +307,22 @@ struct CellsScript {
1);
lua_setglobal(L, "clear_area");
lua_pushlightuserdata(L, this);
lua_pushcclosure(
L,
[](lua_State *L) -> int {
CellsScript *_this = static_cast<CellsScript *>(
lua_touserdata(L, lua_upvalueindex(1)));
int minX = lua_tointeger(L, 1);
int minZ = lua_tointeger(L, 2);
int sizeX = lua_tointeger(L, 3);
int sizeZ = lua_tointeger(L, 4);
_this->clear_furniture_area(minX, minZ, sizeX,
sizeZ);
return 0;
},
1);
lua_setglobal(L, "clear_furniture_area");
lua_pushlightuserdata(L, this);
lua_pushcclosure(
L,
[](lua_State *L) -> int {
@@ -430,6 +461,11 @@ struct CellsScript {
for (auto &cell : cells)
cell["id"] = makeCellKey(cell);
}
void buildFCellIndex()
{
for (auto &fucell : fucells)
fucell["id"] = makeCellKey(fucell);
}
int findCell(int X, int Y, int Z)
{
int64_t key = makeCellKey(X, Y, Z);
@@ -444,6 +480,20 @@ struct CellsScript {
}
return result;
}
int findFCell(int X, int Y, int Z)
{
int64_t key = makeCellKey(X, Y, Z);
int result = -1;
int i;
for (i = 0; i < fucells.size(); i++) {
int64_t ckey = makeCellKey(fucells[i]);
if (key == ckey) {
result = i;
break;
}
}
return result;
}
void bitCmd(const Ogre::String &cmd, const Ogre::String &bit)
{
uint64_t flags = 0;
@@ -560,6 +610,22 @@ struct CellsScript {
clear();
}
}
void clear_furniture()
{
int index = findFCell(currentX, currentY, currentZ);
if (index >= 0)
fucells.erase(index);
}
void clear_furniture_area(int minX, int minZ, int sizeX, int sizeZ)
{
int i, j;
for (i = 0; i < sizeZ; i++)
for (j = 0; j < sizeX; j++) {
currentX = minX + j;
currentZ = minZ + i;
clear_furniture();
}
}
int room(int minX, int minZ, int sizeX, int sizeZ)
{
int i, j, ret;
@@ -621,6 +687,250 @@ struct CellsScript {
{
lot["roofs"] = nlohmann::json::array();
}
void fcell(const std::vector<Ogre::String> &tags,
nlohmann::json furniture, int rotation)
{
nlohmann::json jtags = nlohmann::json::array();
for (const auto &tag : tags)
jtags.push_back(tag);
if (findFCell(currentX, currentY, currentZ) == -1) {
nlohmann::json fucell;
buildFCellIndex();
fucell["x"] = currentX;
fucell["y"] = currentY;
fucell["z"] = currentZ;
fucell["tags"] = jtags;
fucell["id"] = makeCellKey(fucell);
fucell["furniture"] = furniture;
fucell["rotation"] = rotation;
fucells.push_back(fucell);
} else {
int index = findFCell(currentX, currentY, currentZ);
if (index >= 0) {
fucells[index]["tags"] = jtags;
fucells[index]["furniture"] = furniture;
fucells[index]["rotation"] = rotation;
}
}
}
nlohmann::json select_furniture(const std::vector<Ogre::String> &tags)
{
nlohmann::json adata = nlohmann::json::array();
ECS::get().query_builder<const FurnitureItem>().build().each(
[&](flecs::entity e, const FurnitureItem &item) {
bool apply = true;
for (auto &t : tags) {
if (std::find(item.tags.begin(),
item.tags.end(),
t) == item.tags.end()) {
apply = false;
break;
}
}
if (apply) {
nlohmann::json jdata =
nlohmann::json::parse(
item.properties);
adata.push_back(jdata);
}
});
// FIXME: use noise function
return adata[0];
}
void place_furniture(int room, Ogre::String tags)
{
std::vector<Ogre::String> atags = split_and_trim(tags, ',');
int i, j;
int minX = rooms[room].minX;
int minZ = rooms[room].minZ;
int sizeX = rooms[room].sizeX;
int sizeZ = rooms[room].sizeZ;
int midX = minX + sizeX / 2;
int midZ = minZ + sizeZ / 2;
std::cout << "room: " << room << " " << minX << " " << minZ
<< " " << sizeX << " " << sizeZ << std::endl;
clear_furniture_area(minX, minZ, sizeX, sizeZ);
currentX = midX;
currentZ = minZ;
bool placed = false;
if (isBit("iwallz-") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture = select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 2);
placed = true;
}
currentX = midX;
currentZ = minZ + sizeZ - 1;
if (isBit("iwallz+") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture = select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 0);
placed = true;
}
currentX = midX;
currentZ = midZ;
if (isBit("iwallx-") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture = select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 1);
placed = true;
}
currentX = midX + sizeX - 1;
currentZ = midZ;
if (isBit("iwallx+") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture = select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 3);
placed = true;
}
if (placed)
return;
if (isBit("windowz-") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture = select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 2);
placed = true;
}
currentX = midX;
currentZ = minZ + sizeZ - 1;
if (isBit("windowz+") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture = select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 0);
placed = true;
}
currentX = midX;
currentZ = midZ;
if (isBit("windowx-") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture = select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 1);
placed = true;
}
currentX = midX + sizeX - 1;
currentZ = midZ;
if (isBit("windowx+") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture = select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 3);
placed = true;
}
if (placed)
return;
for (i = 1; i < sizeX - 1; i++) {
currentX = minX + i;
currentZ = minZ;
if (isBit("iwallz-") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture =
select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 2);
placed = true;
break;
}
}
if (placed)
return;
for (i = 1; i < sizeX - 1; i++) {
currentX = minX + i;
currentZ = minZ + sizeZ - 1;
if (isBit("iwallz+") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture =
select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 0);
placed = true;
break;
}
}
if (placed)
return;
for (i = 1; i < sizeZ - 1; i++) {
currentX = minX;
currentZ = minZ + i;
if (isBit("iwallx-") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture =
select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 1);
placed = true;
break;
}
}
for (i = 1; i < sizeZ - 1; i++) {
currentX = minX + sizeX - 1;
currentZ = minZ + i;
if (isBit("iwallx+") && !isBit("idoorz+") &&
!isBit("idoorz-") && !isBit("idoorx+") &&
!isBit("idoorx-") && !placed) {
std::vector<Ogre::String> ptags = atags;
ptags.push_back("essential");
nlohmann::json furniture =
select_furniture(ptags);
std::cout << currentX << " " << currentY << " "
<< currentZ << std::endl;
fcell(ptags, furniture, 3);
placed = true;
break;
}
}
}
std::vector<std::pair<int, int> > roomEdge(int room)
{
std::vector<std::pair<int, int> > seg;
@@ -1235,16 +1545,21 @@ bool editLot(const Ogre::String &lotLabel, nlohmann::json &lot)
nlohmann::json cells = nlohmann::json::array();
static char text_buffer[16384];
strcpy(text_buffer, "");
/* copy script data from json to a buffer */
if (lot.find("cellScript") != lot.end()) {
Ogre::String script = lot["cellScript"].get<Ogre::String>();
strncpy(text_buffer, script.c_str(), sizeof(text_buffer));
}
/* edit a buffer and if changed, copy a buffer back to json */
if (ImGui::InputTextMultiline(("Cells Script##" + lotLabel).c_str(),
text_buffer, IM_ARRAYSIZE(text_buffer),
ImVec2(1000,
ImGui::GetTextLineHeight() * 20),
ImGuiInputTextFlags_AllowTabInput)) {
lot["cellScript"] = Ogre::String(text_buffer);
}
if (ImGui::IsItemDeactivatedAfterEdit()) {
lot["cellScript"] = Ogre::String(text_buffer);
changed = true;
}
if (ImGui::SmallButton(("Execute script...##" + lotLabel).c_str())) {
@@ -1252,6 +1567,7 @@ bool editLot(const Ogre::String &lotLabel, nlohmann::json &lot)
script.run();
changed = true;
}
for (const auto &cell : lot["cells"])
cells.push_back(cell);
if (ImGui::CollapsingHeader(("Cells...##" + lotLabel).c_str())) {
@@ -1380,11 +1696,15 @@ bool editDistrict(const Ogre::String &districtLabel, nlohmann::json &district)
districtLabel + "_lot" +
Ogre::StringConverter::toString(lotCount);
ImGui::Text("%s", lotLabel.c_str());
changed = changed || editLot(lotLabel, lot);
ImGui::Separator();
if (ImGui::SmallButton(("Lot Delete##" + lotLabel).c_str())) {
lots.erase(lotCount);
break;
if (ImGui::CollapsingHeader(
("Edit lot... ##" + lotLabel).c_str())) {
changed = changed || editLot(lotLabel, lot);
ImGui::Separator();
if (ImGui::SmallButton(
("Lot Delete##" + lotLabel).c_str())) {
lots.erase(lotCount);
break;
}
}
lotCount++;
}
@@ -1400,9 +1720,12 @@ bool editDistrict(const Ogre::String &districtLabel, nlohmann::json &district)
changed = true;
}
district["lots"] = lots;
float radius = 50.0f;
bool plazza = false;
if (district.find("plazza") != district.end())
plazza = district["plazza"].get<bool>();
if (district.find("radius") != district.end())
radius = district["radius"].get<float>();
if (ImGui::Checkbox("Plazza", &plazza)) {
changed = true;
district["plazza"] = plazza;
@@ -1412,6 +1735,10 @@ bool editDistrict(const Ogre::String &districtLabel, nlohmann::json &district)
elevation = district["elevation"].get<float>();
if (district.find("height") != district.end())
height = district["height"].get<float>();
if (ImGui::SliderFloat("Radius", &radius, 20.0f, 100.0f)) {
district["radius"] = radius;
changed = true;
}
if (ImGui::SliderFloat("Height", &height, 0.1f, 10.0f)) {
district["height"] = height;
changed = true;
@@ -1535,8 +1862,10 @@ void createTownPopup(const std::pair<flecs::entity, Ogre::String> item)
nlohmann::json colorRects = nlohmann::json::object();
if (j.find("colorRects") != j.end())
colorRects = j["colorRects"];
changed = changed || editColorRects(colorRects);
ImGui::Separator();
if (ImGui::CollapsingHeader("Edit Color Rects")) {
changed = changed || editColorRects(colorRects);
ImGui::Separator();
}
nlohmann::json districts = nlohmann::json::array();
for (auto &district : j["districts"])
districts.push_back(district);
@@ -2565,6 +2894,122 @@ void createTownDoors(flecs::entity e)
}
}
}
void createDecorateFurniture(flecs::entity e, const nlohmann::json &jdistrict,
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
Ogre::MaterialPtr townMaterial = createTownMaterial(e);
const nlohmann::json &jp = jdistrict;
nlohmann::json jlots = nlohmann::json::array();
float baseHeight = 4.0f;
Ogre::Vector3 localPosition(0, 0, 0);
Ogre::Quaternion localRotation = Ogre::Quaternion::IDENTITY;
Ogre::Vector3 centerPosition = sceneNode->_getDerivedPosition();
Ogre::Quaternion centerOrientation =
sceneNode->_getDerivedOrientation();
float delevation = 0.0f;
float radius = 50.0f;
if (jp.find("elevation") != jp.end())
delevation = jp["elevation"].get<float>();
if (jp.find("radius") != jp.end())
radius = jp["radius"].get<float>();
from_json(jp["position"], localPosition);
from_json(jp["rotation"], localRotation);
centerPosition = centerPosition + localPosition +
Ogre::Vector3(0, delevation, 0);
centerOrientation = centerOrientation * localRotation;
if (jdistrict.find("lots") != jdistrict.end())
jlots = jdistrict["lots"];
for (const auto &jb : jlots) {
float angle = 0.0f;
int depth = 10;
int width = 10;
float distance = radius;
float elevation = 0.0f;
std::cout << jb.dump() << std::endl;
if (jb.find("angle") != jb.end())
angle = jb["angle"].get<float>();
if (jb.find("depth") != jb.end())
depth = jb["depth"].get<int>();
if (jb.find("width") != jb.end())
width = jb["width"].get<int>();
if (jb.find("elevation") != jb.end())
elevation = jb["elevation"].get<float>();
OgreAssert(width > 1 && depth > 1 && baseHeight > 1,
"Bad stuff happen");
Ogre::Quaternion rotation = Ogre::Quaternion(
Ogre::Degree(angle), Ogre::Vector3::UNIT_Y);
Ogre::Vector3 offset = centerOrientation * rotation *
(Ogre::Vector3::UNIT_Z * distance);
Ogre::Vector3 worldCenterPosition =
centerPosition + offset +
Ogre::Vector3(0, elevation, 0);
Ogre::Quaternion worldCenterOrientation =
centerOrientation * rotation;
float outOffset = 1.05f;
if (jb.find("furniture_cells") != jb.end()) {
for (auto &jfcell : jb["furniture_cells"]) {
int x = jfcell["x"].get<int>();
int y = jfcell["y"].get<int>();
int z = jfcell["z"].get<int>();
nlohmann::json furniture = jfcell["furniture"];
Ogre::Vector3 cellOffset(x * 2.0f, y * 4.0f,
z * 2.0f);
Ogre::Vector3 offsetX = worldCenterOrientation *
Ogre::Vector3::UNIT_X *
(float)x * 2.0f;
Ogre::Vector3 offsetZ = worldCenterOrientation *
Ogre::Vector3::UNIT_Z *
(float)z * 2.0f;
Ogre::Vector3 offsetY(0, y * 4.0f, 0);
if (furniture.find("mesh") != furniture.end()) {
Ogre::String meshName =
furniture["mesh"]
.get<Ogre::String>();
Ogre::MeshPtr mesh =
Ogre::MeshManager::getSingleton()
.getByName(meshName);
if (!mesh) {
mesh = Ogre::MeshManager::getSingleton()
.load(meshName,
"General");
Ogre::LodConfig meshconf(mesh);
setupLods(meshconf);
}
int rotation = 2;
if (jfcell.find("rotation") !=
jfcell.end())
rotation = jfcell["rotation"]
.get<int>();
Ogre::Vector3 offset =
worldCenterOrientation *
Ogre::Vector3::UNIT_Z * 0.0f;
Ogre::Entity *ent =
ECS::get<EngineData>()
.mScnMgr->createEntity(
meshName);
geo->addEntity(
ent,
worldCenterPosition + offsetX +
offsetZ + offsetY +
offset,
worldCenterOrientation *
Ogre::Quaternion(
Ogre::Degree(
90.0f *
(float)rotation),
Ogre::Vector3::
UNIT_Y));
ECS::get<EngineData>()
.mScnMgr->destroyEntity(ent);
}
}
}
}
}
void createDecorateDoors(flecs::entity e, const nlohmann::json &jdistrict,
int index, Ogre::SceneNode *sceneNode,
@@ -3049,6 +3494,8 @@ void createTown(flecs::entity e, Ogre::SceneNode *sceneNode,
geo);
createDecorateDoors(e, jdistrict, index, sceneNode,
geo);
createDecorateFurniture(e, jdistrict, index, sceneNode,
geo);
index++;
}
}