Generating path from shore to pier

This commit is contained in:
2025-12-15 01:41:44 +03:00
parent 3f99099919
commit 9bb9e2c09b
3 changed files with 391 additions and 322 deletions

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <algorithm>
#include <nlohmann/json.hpp>
#include <OgreTerrainGroup.h>
#include <OgreFileSystemLayer.h>
@@ -743,73 +744,93 @@ out:;
{
}
};
void StaticGeometryModule::createHarbour(flecs::entity e,
Ogre::SceneNode *sceneNode)
void StaticGeometryModule::createBridge(flecs::entity e,
Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
std::cout << "createHarbour " << e.id() << std::endl;
harbourMaker hm(e);
Ogre::StaticGeometry *geo =
ECS::get<EngineData>().mScnMgr->createStaticGeometry(
"pier_" + Ogre::StringConverter::toString(e.id()));
geo->setRegionDimensions(Ogre::Vector3(140, 140, 140));
Ogre::Vector3 geoposition = sceneNode->_getDerivedPosition();
geoposition.y = 0.0f;
geo->setOrigin(geoposition);
#if 1
Ogre::MaterialPtr pierMaterial;
pierMaterial = Ogre::MaterialManager::getSingleton().getByName(
"proceduralMaterialPier" +
Procedural::TriangleBuffer tb;
Ogre::MaterialPtr harbourMaterial;
harbourMaterial = Ogre::MaterialManager::getSingleton().getByName(
"proceduralMaterialHarbour" +
Ogre::StringConverter::toString(e.id()));
if (!pierMaterial) {
Procedural::TextureBuffer wood(128);
Procedural::Colours(&wood)
.setColourBase(Ogre::ColourValue(0.8f, 0.6f, 0, 1))
.setColourPercent(Ogre::ColourValue(0.15f, 0.1f, 0, 1))
.process();
// Procedural::RectangleTexture woodDraw(&wood);
Ogre::TexturePtr pierTexture = wood.createTexture(
"proceduralTexturePier" +
Ogre::StringConverter::toString(e.id()));
pierMaterial = Ogre::MaterialManager::getSingletonPtr()->create(
"proceduralMaterialPier" +
Ogre::StringConverter::toString(e.id()),
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
pierMaterial->getTechnique(0)->getPass(0)->setShininess(0);
pierMaterial->getTechnique(0)->getPass(0)->setDiffuse(
Ogre::ColourValue::White);
pierMaterial->getTechnique(0)->getPass(0)->setSpecular(
Ogre::ColourValue(1.0f, 1.0f, 0.9f));
pierMaterial->getTechnique(0)
->getPass(0)
->createTextureUnitState(
"proceduralTexturePier" +
Ogre::StringConverter::toString(e.id()));
if (Ogre::RTShader::ShaderGenerator::initialize()) {
pierMaterial->prepare();
Ogre::RTShader::ShaderGenerator *mShaderGenerator =
Ogre::RTShader::ShaderGenerator::
getSingletonPtr();
mShaderGenerator->createShaderBasedTechnique(
*pierMaterial,
Ogre::MaterialManager::DEFAULT_SCHEME_NAME,
Ogre::RTShader::ShaderGenerator::
DEFAULT_SCHEME_NAME);
Ogre::RTShader::RenderState *pMainRenderState =
mShaderGenerator->getRenderState(
Ogre::RTShader::ShaderGenerator::
DEFAULT_SCHEME_NAME,
*pierMaterial);
}
}
#endif
float stepWidth = 12.0f;
float stepHeight = 0.15f;
float stepDepth = 0.25f;
float stairsHeight = 0.0f;
float stairsOffset = 0.0f;
Ogre::String props = e.get<TerrainItem>().properties;
nlohmann::json jp = nlohmann::json::parse(props);
if (jp.find("stairsHeight") != jp.end())
stairsHeight = jp["stairsHeight"].get<float>();
if (jp.find("stairsOffset") != jp.end())
stairsOffset = jp["stairsOffset"].get<float>();
if (jp.find("stepHeight") != jp.end())
stepHeight = jp["stepHeight"].get<float>();
if (jp.find("stepDepth") != jp.end())
stepDepth = jp["stepDepth"].get<float>();
float rampLength = stairsHeight / Ogre::Math::Sin(Ogre::Degree(30.0f));
float rampOffset = Ogre::Math::Sin(rampLength * rampLength -
stairsHeight * stairsHeight);
Procedural::BoxGenerator()
.setSizeX(4.0f)
.setSizeY(0.5f)
.setSizeZ(rampLength)
.setOrientation(Ogre::Quaternion(Ogre::Degree(30.0f),
Ogre::Vector3::UNIT_X))
.setEnableNormals(true)
.setTextureRectangle(Ogre::RealRect(0.4f, 0.0f, 0.1f, 0.1f))
.setPosition(Ogre::Vector3(0.0f, 0.8f + stairsHeight / 2.0f,
4.0f + rampOffset / 2.0f +
stairsOffset / 2.0f))
.addToTriangleBuffer(tb);
Procedural::BoxGenerator()
.setSizeX(4.0f)
.setSizeY(0.5f)
.setSizeZ(stairsOffset + 5.0f)
.setEnableNormals(true)
.setTextureRectangle(Ogre::RealRect(0.4f, 0.0f, 0.1f, 0.1f))
.setPosition(Ogre::Vector3(0.0f, 0.8f + stairsHeight,
-(stairsOffset + 5.0f) / 2.0f))
.addToTriangleBuffer(tb);
Ogre::String meshName =
"elevator" + Ogre::StringConverter::toString(e.id());
Ogre::MeshPtr mesh = tb.transformToMesh(meshName);
Ogre::LodConfig config(mesh);
// config.advanced.useCompression = false;
// config.advanced.useVertexNormals = true;
config.advanced.preventPunchingHoles = true;
config.advanced.preventBreakingLines = true;
config.createGeneratedLodLevel(10, 0.15f);
config.createGeneratedLodLevel(30, 0.25f);
config.createGeneratedLodLevel(60, 0.36f);
config.createGeneratedLodLevel(150, 0.65f);
config.advanced.useBackgroundQueue = false;
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(config);
Ogre::Entity *ent = ECS::get<EngineData>().mScnMgr->createEntity(mesh);
ent->setMaterial(harbourMaterial);
float xofft = 0.0f;
Ogre::Vector3 worldPosition = sceneNode->_getDerivedPosition() +
sceneNode->_getDerivedOrientation() *
Ogre::Vector3::UNIT_Z * 0.0f;
Ogre::Quaternion worldOrientation = sceneNode->_getDerivedOrientation();
Ogre::Vector3 xoffset =
worldOrientation * (Ogre::Vector3::UNIT_X * xofft);
geo->addEntity(ent, worldPosition + xoffset, worldOrientation,
Ogre::Vector3(1, 1, 1));
}
void StaticGeometryModule::createPier(flecs::entity e,
Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
Ogre::MaterialPtr harbourMaterial;
harbourMaterial = Ogre::MaterialManager::getSingleton().getByName(
"proceduralMaterialHarbour" +
Ogre::StringConverter::toString(e.id()));
harbourMaker hm(e);
Ogre::Vector3 position = sceneNode->_getDerivedPosition();
Ogre::String props = e.get<TerrainItem>().properties;
nlohmann::json jp = nlohmann::json::parse(props);
float pierHeight = 0.0f, pierOffset = 0.0f, pierLength = 6.0f,
pierDepth = 6.0f;
if (jp.find("pierOffset") != jp.end())
pierOffset = jp["pierOffset"].get<float>();
float pierHeight = 0.0f, pierLength = 6.0f, pierDepth = 6.0f;
if (jp.find("pierLength") != jp.end())
pierLength = jp["pierLength"].get<float>();
if (jp.find("pierDepth") != jp.end())
@@ -819,13 +840,15 @@ void StaticGeometryModule::createHarbour(flecs::entity e,
Procedural::TriangleBuffer tb;
float plankLength = 2.0f;
float plankWidth = 4.01f;
float plankHeight = 0.3f;
const float beamLength = 6.0f;
const float beamWidth = 5.5f;
float beamHeight = 0.3f;
if (pierLength < 12.0f)
pierLength = 12.0f;
auto processGrid = [&sceneNode, &geo](float stepLength, float length,
float zoffset, float xofft,
Ogre::Entity *ent) {
float zoffset, float yofft,
float xofft, Ogre::Entity *ent) {
float step = 0.0f;
while (step < length) {
Ogre::Vector3 worldPosition =
@@ -837,7 +860,9 @@ void StaticGeometryModule::createHarbour(flecs::entity e,
sceneNode->_getDerivedOrientation();
Ogre::Vector3 xoffset = worldOrientation *
(Ogre::Vector3::UNIT_X * xofft);
geo->addEntity(ent, worldPosition + xoffset,
Ogre::Vector3 yoffset = worldOrientation *
(Ogre::Vector3::UNIT_Y * yofft);
geo->addEntity(ent, worldPosition + xoffset + yoffset,
worldOrientation,
Ogre::Vector3(1, 1, 1));
step += stepLength;
@@ -846,8 +871,8 @@ void StaticGeometryModule::createHarbour(flecs::entity e,
float xofftPlanks;
for (xofftPlanks = -plankWidth; xofftPlanks <= plankWidth;
xofftPlanks += plankWidth)
processGrid(plankLength, pierLength,
pierOffset + plankLength / 2.0f, xofftPlanks,
processGrid(plankLength, pierLength, plankLength / 2.0f,
plankHeight / 2.0f + beamHeight / 2.0f, xofftPlanks,
hm.planks);
{
float step = 0.0f;
@@ -897,7 +922,6 @@ void StaticGeometryModule::createHarbour(flecs::entity e,
step -= 12.0f;
}
// beams
float beamHeight = 0.3f;
Procedural::BoxGenerator()
.setSizeX(0.5f)
.setSizeY(beamHeight)
@@ -939,177 +963,114 @@ void StaticGeometryModule::createHarbour(flecs::entity e,
config);
Ogre::Entity *ent =
ECS::get<EngineData>().mScnMgr->createEntity(mesh);
Ogre::SceneNode *pierNode = sceneNode->createChildSceneNode();
ent->setMaterial(harbourMaterial);
float xofft = 0.0f;
Ogre::Vector3 worldPosition =
sceneNode->_getDerivedPosition() +
sceneNode->_getDerivedOrientation() *
Ogre::Vector3::UNIT_Z * 0.0f;
Ogre::Quaternion worldOrientation =
sceneNode->_getDerivedOrientation();
Ogre::Vector3 xoffset =
worldOrientation * (Ogre::Vector3::UNIT_X * xofft);
geo->addEntity(ent, worldPosition + xoffset, worldOrientation,
Ogre::Vector3(1, 1, 1));
}
std::cout << meshName << std::endl;
}
void StaticGeometryModule::createHarbour(flecs::entity e,
Ogre::SceneNode *sceneNode)
{
std::cout << "createHarbour " << e.id() << std::endl;
Ogre::MaterialPtr harbourMaterial;
harbourMaterial = Ogre::MaterialManager::getSingleton().getByName(
"proceduralMaterialHarbour" +
Ogre::StringConverter::toString(e.id()));
if (!harbourMaterial) {
Procedural::TextureBuffer wood(128);
Procedural::Colours(&wood)
.setColourBase(Ogre::ColourValue(0.8f, 0.6f, 0, 1))
.setColourPercent(Ogre::ColourValue(0.15f, 0.1f, 0, 1))
.process();
// Procedural::RectangleTexture woodDraw(&wood);
Ogre::TexturePtr pierTexture = wood.createTexture(
"proceduralTextureHarbour" +
Ogre::StringConverter::toString(e.id()));
harbourMaterial =
Ogre::MaterialManager::getSingletonPtr()->create(
"proceduralMaterialHarbour" +
Ogre::StringConverter::toString(e.id()),
Ogre::ResourceGroupManager::
DEFAULT_RESOURCE_GROUP_NAME);
harbourMaterial->getTechnique(0)->getPass(0)->setShininess(0);
harbourMaterial->getTechnique(0)->getPass(0)->setDiffuse(
Ogre::ColourValue::White);
harbourMaterial->getTechnique(0)->getPass(0)->setSpecular(
Ogre::ColourValue(1.0f, 1.0f, 0.9f));
harbourMaterial->getTechnique(0)
->getPass(0)
->createTextureUnitState(
"proceduralTextureHarbour" +
Ogre::StringConverter::toString(e.id()));
if (Ogre::RTShader::ShaderGenerator::initialize()) {
harbourMaterial->prepare();
Ogre::RTShader::ShaderGenerator *mShaderGenerator =
Ogre::RTShader::ShaderGenerator::
getSingletonPtr();
mShaderGenerator->createShaderBasedTechnique(
*harbourMaterial,
Ogre::MaterialManager::DEFAULT_SCHEME_NAME,
Ogre::RTShader::ShaderGenerator::
DEFAULT_SCHEME_NAME);
Ogre::RTShader::RenderState *pMainRenderState =
mShaderGenerator->getRenderState(
Ogre::RTShader::ShaderGenerator::
DEFAULT_SCHEME_NAME,
*harbourMaterial);
}
}
Ogre::StaticGeometry *geo =
ECS::get<EngineData>().mScnMgr->createStaticGeometry(
"pier_" + Ogre::StringConverter::toString(e.id()));
geo->setRegionDimensions(Ogre::Vector3(140, 140, 140));
Ogre::Vector3 geoposition = sceneNode->_getDerivedPosition();
geoposition.y = 0.0f;
geo->setOrigin(geoposition);
{
Ogre::String props = e.get<TerrainItem>().properties;
nlohmann::json jp = nlohmann::json::parse(props);
float pierOffset = 0.0f;
if (jp.find("pierOffset") != jp.end())
pierOffset = jp["pierOffset"].get<float>();
Ogre::Vector3 worldPosition =
sceneNode->_getDerivedPosition() +
sceneNode->_getDerivedOrientation() *
Ogre::Vector3::UNIT_Z * (pierOffset);
float xofft = 0.0f;
float stairLengthZ = worldPosition.y;
float stairsOffset = 0.0f;
stairsOffset = stairLengthZ;
jp["stairsHeight"] = worldPosition.y;
jp["stairsOffset"] = stairsOffset;
e.get_mut<TerrainItem>().properties = jp.dump();
e.modified<TerrainItem>();
worldPosition.y = 0.0f;
Ogre::Quaternion worldOrientation =
sceneNode->_getDerivedOrientation();
Ogre::Vector3 xoffset =
worldOrientation * (Ogre::Vector3::UNIT_X * xofft);
pierNode->_setDerivedPosition(worldPosition + xoffset);
ent->setMaterial(pierMaterial);
//pierNode->attachObject(ent);
geo->addEntity(ent, worldPosition + xoffset, worldOrientation,
Ogre::Vector3(1, 1, 1));
Ogre::Vector3 zoffset =
worldOrientation *
(Ogre::Vector3::UNIT_Z * (stairsOffset + 1));
Ogre::SceneNode *elevatorNode =
sceneNode->createChildSceneNode();
elevatorNode->_setDerivedPosition(worldPosition + xoffset);
Ogre::SceneNode *pierNode = sceneNode->createChildSceneNode();
pierNode->_setDerivedPosition(worldPosition + zoffset +
xoffset);
createBridge(e, elevatorNode, geo);
createPier(e, pierNode, geo);
}
geo->build();
std::cout << meshName << std::endl;
#if 0
float step = 0.0f;
float h = Ogre::Math::Sin(step + position.z * 60.0f +
position.x * 60.0f * 60.0f) *
0.1f;
if (pierLength < 12.0f)
pierLength = 12.0f;
if (pierHeight > 0.0f) {
Procedural::BoxGenerator()
.setSizeX(10.0f)
.setSizeY(0.5f)
.setSizeZ(pierHeight)
.setOrientation(Ogre::Quaternion(
Ogre::Degree(-45), Ogre::Vector3(1, 0, 0)))
.setTextureRectangle(
Ogre::RealRect(0.0f, 0.0f, 0.1f, 0.1f))
.setPosition(Ogre::Vector3(
0.0f,
pierHeight + 0.5f -
pierHeight *
Ogre::Math::Sin(
Ogre::Degree(45)) /
2.0f,
-pierHeight / 2.0f *
Ogre::Math::Cos(Ogre::Degree(45))))
.addToTriangleBuffer(tb);
}
while (step < pierOffset - 2.0f) {
Procedural::BoxGenerator()
.setSizeX(10.0f)
.setSizeY(0.4f)
.setSizeZ(0.8f)
.setTextureRectangle(
Ogre::RealRect(0.1f, 0.0f, 0.1f, 0.1f))
.setPosition(Ogre::Vector3(0.0f, 0.5f + h + pierHeight,
step))
.addToTriangleBuffer(tb);
h = Ogre::Math::Sin(step + position.z * 60.0f +
position.x * 60.0f * 60.0f) *
0.1f;
step += 1.0f;
}
step = 0.0f;
while (step < pierLength) {
h = Ogre::Math::Sin(step + pierOffset + position.z * 60.0f +
position.x * 60.0f * 60.0f) *
0.1f;
// pillars
Procedural::BoxGenerator()
.setSizeX(0.5f)
.setSizeY(pierDepth)
.setSizeZ(0.5f)
.setEnableNormals(true)
.setTextureRectangle(
Ogre::RealRect(0.2f, 0.0f, 0.1f, 0.1f))
.setPosition(Ogre::Vector3(
-4.0f, -position.y - pierDepth / 2.0f + 0.5f,
step + pierOffset))
.addToTriangleBuffer(tb);
Procedural::BoxGenerator()
.setSizeX(0.5f)
.setSizeY(pierDepth)
.setSizeZ(0.5f)
.setEnableNormals(true)
.setTextureRectangle(
Ogre::RealRect(0.2f, 0.0f, 0.1f, 0.1f))
.setPosition(Ogre::Vector3(
4.0f, -position.y - pierDepth / 2.0f + 0.5f,
step + pierOffset))
.addToTriangleBuffer(tb);
step += 6.0f;
}
step = 0.0f;
#endif
#if 0
while (step < pierLength) {
h = Ogre::Math::Sin(step + pierOffset + position.z * 60.0f +
position.x * 60.0f * 60.0f) *
0.01f;
Ogre::Vector3 worldPosition =
sceneNode->_getDerivedPosition() +
sceneNode->_getDerivedOrientation() *
Ogre::Vector3::UNIT_Z *
(step + pierOffset + plankLength / 2.0f);
Ogre::Quaternion worldOrientation =
sceneNode->_getDerivedOrientation();
float xofft;
for (xofft = -plankWidth - plankLength / 2.0f;
xofft <= plankWidth + plankWidth / 2.0f;
xofft += plankWidth) {
Ogre::Vector3 xoffset = worldOrientation *
(Ogre::Vector3::UNIT_X * xofft);
geo->addEntity(planks, worldPosition + xoffset,
worldOrientation,
Ogre::Vector3(1, 1, 1));
}
step += plankLength;
}
#endif
#if 0
float xofftBeam;
for (xofftBeam = -beamWidth; xofftBeam <= beamWidth;
xofftBeam += beamWidth)
processGrid(beamLength, pierLength,
pierOffset + beamLength / 2.0f, xofftBeam, hm.beam);
#endif
#if 0
step = 0.0f;
while (step < pierLength) {
h = Ogre::Math::Sin(step + pierOffset + position.z * 60.0f +
position.x * 60.0f * 60.0f) *
0.01f;
Ogre::Vector3 worldPosition =
sceneNode->_getDerivedPosition() +
sceneNode->_getDerivedOrientation() *
Ogre::Vector3::UNIT_Z *
(step + pierOffset + beamLength / 2.0f);
Ogre::Quaternion worldOrientation =
sceneNode->_getDerivedOrientation();
float xofft;
for (xofft = -beamWidth - beamWidth / 2.0f;
xofft <= beamWidth + beamWidth / 2.0f;
xofft += beamWidth) {
Ogre::Vector3 xoffset = worldOrientation *
(Ogre::Vector3::UNIT_X * xofft);
geo->addEntity(beam, worldPosition + xoffset,
worldOrientation,
Ogre::Vector3(1, 1, 1));
}
step += beamLength;
}
#endif
#if 0
Procedural::BoxGenerator()
.setSizeX(0.5f)
.setSizeY(0.5f)
.setSizeZ(pierLength)
.setTextureRectangle(Ogre::RealRect(0.4f, 0.0f, 0.1f, 0.1f))
.setEnableNormals(true)
.setPosition(Ogre::Vector3(-4.0f, -position.y + 0.5f,
pierOffset + pierLength / 2.0f))
.addToTriangleBuffer(tb);
Procedural::BoxGenerator()
.setSizeX(0.5f)
.setSizeY(0.5f)
.setSizeZ(pierLength)
.setTextureRectangle(Ogre::RealRect(0.4f, 0.0f, 0.1f, 0.1f))
.setEnableNormals(true)
.setPosition(Ogre::Vector3(4.0f, -position.y + 0.5f,
pierOffset + pierLength / 2.0f))
.addToTriangleBuffer(tb);
#endif
}
}