diff --git a/src/gamedata/items/town.cpp b/src/gamedata/items/town.cpp index b563aea..053d494 100644 --- a/src/gamedata/items/town.cpp +++ b/src/gamedata/items/town.cpp @@ -30,11 +30,7 @@ void createTownItem() nlohmann::json j = nlohmann::json::parse(prop); j["districts"] = nlohmann::json::array(); StaticGeometryModule::setItemProperties(e, j.dump()); - // setHarbourSurface(); StaticGeometryModule::saveItems(); - // updateWorldTexture(); - // updateHeightmap(); - // TerrainModule::save_heightmap(); } void createTownMenu() { @@ -44,16 +40,103 @@ void createTownMenu() void createTownPopup(const std::pair item) { Ogre::String prop = StaticGeometryModule::getItemProperties(item.first); + Ogre::Vector3 townPosition; + Ogre::Quaternion townRotation; + StaticGeometryModule::getItemPositionAndRotation( + item.first, townPosition, townRotation); nlohmann::json j = nlohmann::json::parse(prop); bool changed = false; + int count = 0; + ImGui::Text("Town"); + nlohmann::json districts = nlohmann::json::array(); + for (auto &district : j["districts"]) + districts.push_back(district); + count = 0; + for (auto &district : districts) { + ImGui::Separator(); + Ogre::String districtLabel = + "district" + Ogre::StringConverter::toString(count); + ImGui::Text("%s", districtLabel.c_str()); + nlohmann::json lots = nlohmann::json::array(); + for (const auto &lot : district["lots"]) + lots.push_back(lot); + int lotCount = 0; + for (auto &lot : lots) { + Ogre::String lotLabel = + "lot" + + Ogre::StringConverter::toString(lotCount); + ImGui::Text("%s", lotLabel.c_str()); + ImGui::Separator(); + if (ImGui::SmallButton("Delete")) { + lots.erase(lotCount); + break; + } + lotCount++; + } + ImGui::Separator(); + if (ImGui::SmallButton("Add lot")) { + nlohmann::json l; + l["angle"] = 0.0f; + l["width"] = 10.0f; + l["depth"] = 10.0f; + l["elevation"] = 0.0f; + lots.push_back(l); + changed = true; + } + district["lots"] = lots; + bool plazza = false; + if (district.find("plazza") != district.end()) + plazza = district["plazza"].get(); + if (ImGui::Checkbox("Plazza", &plazza)) { + changed = true; + district["plazza"] = plazza; + } + float elevation = 0.0f, height = 0.2f; + if (district.find("elevation") != district.end()) + elevation = district["elevation"].get(); + if (district.find("height") != district.end()) + height = district["height"].get(); + if (ImGui::SliderFloat("Height", &height, 0.1f, 10.0f)) { + district["height"] = height; + changed = true; + } + if (ImGui::SliderFloat("Elevation", &elevation, -10.0f, + 10.0f)) { + district["elevation"] = elevation; + changed = true; + } + ImGui::Separator(); + if (ImGui::SmallButton("Delete")) { + districts.erase(count); + changed = true; + break; + } + count++; + } + ImGui::Separator(); if (ImGui::SmallButton("Add district")) { + Ogre::Vector3 cursorPosition = + ECS::get().sceneNode->_getDerivedPosition(); + Ogre::Quaternion cursorOrientation = + ECS::get() + .sceneNode->_getDerivedOrientation(); + Ogre::Vector3 localPosition = cursorPosition - townPosition; + Ogre::Quaternion localRotation = + townRotation.Inverse() * cursorOrientation; nlohmann::json d; d["radius"] = 50.0f; d["lots"] = nlohmann::json::array(); - j["districts"].push_back(d); + to_json(d["position"], localPosition); + to_json(d["rotation"], localRotation); + d["elevation"] = 0.0f; + d["plazza"] = false; + districts.push_back(d); changed = true; } + ImGui::Separator(); + ImGui::Text("%s", j.dump(4).c_str()); if (changed) { + j["districts"] = districts; StaticGeometryModule::setItemProperties(item.first, j.dump()); StaticGeometryModule::saveItems(); StaticGeometryModule::destroyItemGeometry(item.first); @@ -66,6 +149,147 @@ namespace Geometry void createTown(flecs::entity e, Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo) { + std::cout << "createTown " << e.id() << std::endl; + Ogre::MaterialPtr townMaterial; + townMaterial = Ogre::MaterialManager::getSingleton().getByName( + "proceduralMaterialTown" + + Ogre::StringConverter::toString(e.id())); + if (!townMaterial) { + Procedural::TextureBuffer colorAtlas(1024); + Procedural::RectangleTexture drawAtlas(&colorAtlas); + Ogre::ColourValue normalYellow(0.8f, 0.6f, 0, 1); + Ogre::ColourValue roadBrown(0.4f, 0.3f, 0.3f, 1); + Ogre::ColourValue bollardGrey(0.2f, 0.2f, 0.2f, 1); + drawAtlas.setRectangle(Ogre::RealRect(0.0f, 0.0f, 0.4f, 1.0f)) + .setColour(normalYellow) + .process(); + drawAtlas.setRectangle(Ogre::RealRect(0.2f, 0.0f, 0.3f, 1.0f)) + .setColour(bollardGrey) + .process(); + drawAtlas.setRectangle(Ogre::RealRect(0.4f, 0.0f, 1.0f, 1.0f)) + .setColour(roadBrown) + .process(); + Ogre::TexturePtr pierTexture = colorAtlas.createTexture( + "proceduralTextureTown" + + Ogre::StringConverter::toString(e.id())); + colorAtlas.saveImage("tmp4.png"); + townMaterial = Ogre::MaterialManager::getSingletonPtr()->create( + "proceduralMaterialTown" + + Ogre::StringConverter::toString(e.id()), + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + townMaterial->getTechnique(0)->getPass(0)->setShininess(0); + townMaterial->getTechnique(0)->getPass(0)->setDiffuse( + Ogre::ColourValue::White); + townMaterial->getTechnique(0)->getPass(0)->setSpecular( + Ogre::ColourValue(1.0f, 1.0f, 0.9f)); + townMaterial->getTechnique(0) + ->getPass(0) + ->createTextureUnitState( + "proceduralTextureTown" + + Ogre::StringConverter::toString(e.id())); + if (Ogre::RTShader::ShaderGenerator::initialize()) { + townMaterial->prepare(); + Ogre::RTShader::ShaderGenerator *mShaderGenerator = + Ogre::RTShader::ShaderGenerator:: + getSingletonPtr(); + mShaderGenerator->createShaderBasedTechnique( + *townMaterial, + Ogre::MaterialManager::DEFAULT_SCHEME_NAME, + Ogre::RTShader::ShaderGenerator:: + DEFAULT_SCHEME_NAME); + Ogre::RTShader::RenderState *pMainRenderState = + mShaderGenerator->getRenderState( + Ogre::RTShader::ShaderGenerator:: + DEFAULT_SCHEME_NAME, + *townMaterial); + } + } + { + Ogre::String props = e.get().properties; + nlohmann::json jp = nlohmann::json::parse(props); + Ogre::Vector3 worldPosition = sceneNode->_getDerivedPosition(); + Ogre::Quaternion worldOrientation = + sceneNode->_getDerivedOrientation(); + for (const auto &jdistrict : jp["districts"]) { + createTownPlazza(e, jdistrict, sceneNode, geo); + } + } + geo->build(); +} +void createTownPlazza(flecs::entity e, const nlohmann::json &jdistrict, + Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo) +{ + Ogre::MaterialPtr townMaterial; + townMaterial = Ogre::MaterialManager::getSingleton().getByName( + "proceduralMaterialTown" + + Ogre::StringConverter::toString(e.id())); + Ogre::Vector3 worldPosition = sceneNode->_getDerivedPosition(); + Ogre::Quaternion worldOrientation = sceneNode->_getDerivedOrientation(); + const nlohmann::json &jp = jdistrict; + Procedural::TriangleBuffer tb; + float radius = 5.0f; + float height = 0.2f; + float elevation = 0.0f; + bool plazza = false; + Ogre::Vector3 localPosition(0, 0, 0); + Ogre::Quaternion localRotation = Ogre::Quaternion::IDENTITY; + if (jp.find("plazza") != jp.end()) + plazza = jp["plazza"].get(); + if (!plazza) + return; + if (jp.find("radius") != jp.end()) + radius = jp["radius"].get(); + if (jp.find("height") != jp.end()) + height = jp["height"].get(); + if (jp.find("elevation") != jp.end()) + elevation = jp["elevation"].get(); + from_json(jp["position"], localPosition); + from_json(jp["rotation"], localRotation); + if (height < 0.1f) + height = 0.1f; + if (radius < 5.0f) + radius = 5.0f; + Ogre::Vector3 worldPlazzaCenter = worldPosition + localPosition; + float mh = 4.0f; + Procedural::Shape *plazzaShape = new Procedural::Shape(); + plazzaShape->addPoint(0, -height - mh - mh); + plazzaShape->addPoint(radius * 0.5f + mh, -height - mh - mh); + plazzaShape->addPoint(radius + mh, -height - mh); + plazzaShape->addPoint(radius, -height); + plazzaShape->addPoint(radius, 0.0f); + plazzaShape->addPoint(radius - 0.1f, 0.1f); + plazzaShape->addPoint(radius - mh + 0.1f, height); + plazzaShape->addPoint(radius - mh, height + 0.1f); + plazzaShape->addPoint(radius * 0.5f + mh, height); + plazzaShape->addPoint(0, height); + Procedural::Lathe() + .setShapeToExtrude(plazzaShape) + .setEnableNormals(true) + .setPosition( + Ogre::Vector3(0.0f, height / 2.0f + elevation, 0.0f)) + .setNumSeg(24) + .addToTriangleBuffer(tb); + for (auto &v : tb.getVertices()) { + v.mUV *= 0.08f; + v.mUV.x += 0.41f; + v.mUV.x = Ogre::Math::Clamp(v.mUV.x, 0.4f, 0.5f); + v.mUV.y = Ogre::Math::Clamp(v.mUV.y, 0.0f, 0.1f); + } + Ogre::String meshName = + "plazzaMesh" + Ogre::StringConverter::toString(e.id()); + Ogre::MeshPtr mesh = + Ogre::MeshManager::getSingleton().getByName(meshName); + if (mesh) + Ogre::MeshManager::getSingleton().remove(mesh); + mesh = tb.transformToMesh(meshName); + Ogre::LodConfig config(mesh); + setupLods(config); + Ogre::Entity *pathEnt = + ECS::get().mScnMgr->createEntity(mesh); + pathEnt->setMaterial(townMaterial); + geo->addEntity(pathEnt, worldPlazzaCenter, + worldOrientation * localRotation, + Ogre::Vector3(1, 1, 1)); } } } \ No newline at end of file diff --git a/src/gamedata/items/town.h b/src/gamedata/items/town.h index af70d76..2856456 100644 --- a/src/gamedata/items/town.h +++ b/src/gamedata/items/town.h @@ -14,6 +14,8 @@ namespace Geometry { void createTown(flecs::entity e, Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); +void createTownPlazza(flecs::entity e, const nlohmann::json &jdistrict, + Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo); } } #endif \ No newline at end of file