Started town procedural generation code

This commit is contained in:
2025-12-28 06:23:29 +03:00
parent 5bb529bc31
commit d6d61229f8
2 changed files with 231 additions and 5 deletions

View File

@@ -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<flecs::entity, Ogre::String> 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<bool>();
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<float>();
if (district.find("height") != district.end())
height = district["height"].get<float>();
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<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion cursorOrientation =
ECS::get<EditorGizmo>()
.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<TerrainItem>().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<bool>();
if (!plazza)
return;
if (jp.find("radius") != jp.end())
radius = jp["radius"].get<float>();
if (jp.find("height") != jp.end())
height = jp["height"].get<float>();
if (jp.find("elevation") != jp.end())
elevation = jp["elevation"].get<float>();
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<EngineData>().mScnMgr->createEntity(mesh);
pathEnt->setMaterial(townMaterial);
geo->addEntity(pathEnt, worldPlazzaCenter,
worldOrientation * localRotation,
Ogre::Vector3(1, 1, 1));
}
}
}

View File

@@ -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