Creating pier

This commit is contained in:
2025-12-14 06:59:12 +03:00
parent 81a78990ce
commit 3f99099919
13 changed files with 1581 additions and 259 deletions

View File

@@ -16,10 +16,11 @@
#include "CharacterModule.h"
#include "SunModule.h"
#include "PhysicsModule.h"
#include "StaticGeometryModule.h"
#include "TerrainModule.h"
#define TERRAIN_SIZE 129
#define TERRAIN_WORLD_SIZE 1000.0f
#define TERRAIN_SIZE 65
#define TERRAIN_WORLD_SIZE 500.0f
#define ENDLESS_TERRAIN_FILE_PREFIX Ogre::String("EndlessWorldTerrain")
#define ENDLESS_TERRAIN_FILE_SUFFIX Ogre::String("dat")
@@ -32,6 +33,12 @@
#define ENDLESS_PAGE_MAX_Y 0x7FFF
namespace ECS
{
class DummyPageProvider;
/* Components */
struct TerrainPrivate {
DummyPageProvider *mDummyPageProvider;
Ogre::Timer mSunUpdate;
};
#define BRUSH_SIZE 64
struct HeightData {
@@ -83,15 +90,17 @@ struct HeightData {
}
int get_img_x(float world_x)
{
float world_img_x = world_x + img.getWidth() * BRUSH_SIZE / 2;
int ret = world_img_x / BRUSH_SIZE;
float world_img_x = world_x + (float)img.getWidth() *
(float)BRUSH_SIZE / 2.0f;
int ret = (world_img_x + BRUSH_SIZE - 1) / BRUSH_SIZE;
// ret = Ogre::Math::Clamp(ret, 0, (int)img.getWidth() - 1);
return ret;
}
int get_img_y(float world_z)
{
float world_img_y = world_z + img.getHeight() * BRUSH_SIZE / 2;
int ret = world_img_y / BRUSH_SIZE;
float world_img_y = world_z + (float)img.getHeight() *
(float)BRUSH_SIZE / 2.0f;
int ret = (world_img_y + BRUSH_SIZE - 1) / BRUSH_SIZE;
// ret = Ogre::Math::Clamp(ret, 0, (int)img.getHeight() - 1);
return ret;
}
@@ -234,6 +243,7 @@ class FlatTerrainDefiner
long y;
};
std::deque<struct gen_collider> collider_queue;
std::deque<struct gen_collider> colliderRemove_queue;
public:
FlatTerrainDefiner(Ogre::SceneManager *
@@ -247,10 +257,13 @@ public:
}
private:
std::mutex mtx;
public:
void createTerrainChunk(Ogre::TerrainGroup *terrainGroup, long x,
long y)
{
std::lock_guard<std::mutex> guard(mtx);
Ogre::Terrain *terrain = terrainGroup->getTerrain(x, y);
float minH = terrain->getMinHeight();
float maxH = terrain->getMaxHeight();
@@ -276,6 +289,7 @@ public:
}
void define(Ogre::TerrainGroup *terrainGroup, long x, long y) override
{
std::lock_guard<std::mutex> guard(mtx);
uint16_t terrainSize = terrainGroup->getTerrainSize();
float *heightMap = OGRE_ALLOC_T(float, terrainSize *terrainSize,
MEMCATEGORY_GEOMETRY);
@@ -295,19 +309,9 @@ public:
long world_y = (long)(worldPos.z + i -
(terrainSize - 1) / 2);
float height = 0.0f;
int k, l;
for (l = -1; l < 2; l++)
for (k = -1; k < 2; k++) {
height +=
HeightData::get_singleton()
->get_height(
terrainGroup,
world_x +
4 * k,
world_y +
4 * l);
}
height /= 9.0f;
height +=
HeightData::get_singleton()->get_height(
terrainGroup, world_x, world_y);
// height = -2.0f;
heightMap[i * terrainSize + j] = height;
@@ -421,6 +425,9 @@ public:
what->setOrientation(item.rotation);
what->setPosition(item.position);
}
/* Spawn items */
StaticGeometryModule::addGeometryForSlot(x, y);
} else {
output.push_back(collider_queue.front());
collider_queue.pop_front();
@@ -453,6 +460,10 @@ public:
bool unloadProceduralPage(Ogre::Page *page,
Ogre::PagedWorldSection *section)
{
long x, y;
ECS::get<Terrain>().mTerrainGroup->unpackIndex(page->CHUNK_ID,
&x, &y);
StaticGeometryModule::removeGeometryForSlot(x, y);
return true;
}
bool unprepareProceduralPage(Ogre::Page *page,
@@ -461,20 +472,6 @@ public:
return true;
}
};
struct TerrainPrivate {
DummyPageProvider *mDummyPageProvider;
Ogre::Timer mSunUpdate;
};
struct TerrainSlotParent {
std::pair<long, long> slot;
};
struct TerrainItem {
Ogre::Vector3 position;
Ogre::Quaternion orientation;
Ogre::String properties;
};
TerrainModule::TerrainModule(flecs::world &ecs)
{
struct CanSetPlayerPosition {};
@@ -482,12 +479,11 @@ TerrainModule::TerrainModule(flecs::world &ecs)
ecs.component<CanSetPlayerPosition>().add(flecs::Singleton);
ecs.component<Terrain>().add(flecs::Singleton);
ecs.component<TerrainPrivate>().add(flecs::Singleton);
ecs.component<TerrainSlotParent>();
ecs.component<TerrainItem>();
ecs.component<PlacementObjects>();
ecs.component<TerrainReady>().add(flecs::Singleton);
ecs.import <CharacterModule>();
ecs.import <SunModule>();
ecs.import <StaticGeometryModule>();
ecs.set<TerrainPrivate>({ nullptr, {} });
ecs.system<const EngineData, const Camera, const Sun, Terrain,
TerrainPrivate>("SetupUpdateTerrain")
@@ -523,11 +519,11 @@ TerrainModule::TerrainModule(flecs::world &ecs)
terrain.mTerrainGroup->setOrigin(
terrain.mTerrainPos);
// Configure global
terrain.mTerrainGlobals->setMaxPixelError(0);
terrain.mTerrainGlobals->setMaxPixelError(1);
// testing composite map
// mTerrainGlobals->setCompositeMapDistance(30);
terrain.mTerrainGlobals->setCompositeMapDistance(
500);
300);
//mTerrainGlobals->setUseRayBoxDistanceCalculation(true);
terrain.mTerrainGlobals
->getDefaultMaterialGenerator()
@@ -547,7 +543,8 @@ TerrainModule::TerrainModule(flecs::world &ecs)
defaultimp.terrainSize = TERRAIN_SIZE;
defaultimp.worldSize = TERRAIN_WORLD_SIZE;
defaultimp.inputScale = 1.0f;
defaultimp.minBatchSize = 33;
// defaultimp.minBatchSize = 33;
defaultimp.minBatchSize = 5;
defaultimp.maxBatchSize = 65;
Ogre::Image combined;
combined.loadTwoImagesAsRGBA(
@@ -575,24 +572,33 @@ TerrainModule::TerrainModule(flecs::world &ecs)
terrain.mPageManager);
terrain.mPagedWorld =
terrain.mPageManager->createWorld();
#if 0
terrain.mTerrainGroup->setAutoUpdateLod(
Ogre::TerrainAutoUpdateLodFactory::
getAutoUpdateLod(
Ogre::BY_DISTANCE));
#endif
terrain.mTerrainPagedWorldSection =
terrain.mTerrainPaging
->createWorldSection(
terrain.mPagedWorld,
terrain.mTerrainGroup,
300, 800,
300, 500,
ENDLESS_PAGE_MIN_X,
ENDLESS_PAGE_MIN_Y,
ENDLESS_PAGE_MAX_X,
ENDLESS_PAGE_MAX_Y);
terrain.definer = OGRE_NEW FlatTerrainDefiner(
eng.mScnMgr /*, eng.mWorld */);
terrain.mTerrainPagedWorldSection->setDefiner(
OGRE_NEW FlatTerrainDefiner(
eng.mScnMgr /*, eng.mWorld */));
terrain.definer);
terrain.mTerrainGroup->freeTemporaryResources();
std::cout << "Terrain setup done\n";
ECS::get().set<PlacementObjects>({});
terrain.mTerrainGroup->loadAllTerrains(true);
}
if (sun.mSun &&
priv.mSunUpdate.getMilliseconds() > 1000) {
@@ -607,6 +613,7 @@ TerrainModule::TerrainModule(flecs::world &ecs)
.getPitch()
<< "\n";
priv.mSunUpdate.reset();
//terrain.mTerrainGroup->autoUpdateLodAll()
}
});
ecs.system<const ECS::Camera, const Terrain>("UpdateTerrainStatus")
@@ -738,11 +745,13 @@ TerrainModule::TerrainModule(flecs::world &ecs)
player.modified<CharacterLocation>();
ECS::get().remove<CanSetPlayerPosition>();
});
ecs.observer<const Terrain>("LoadTerrainItems")
.event(flecs::OnSet)
ecs.system<const Terrain>("UpdateTerrainGroup")
.kind(flecs::OnUpdate)
.interval(2.0f)
.each([](const Terrain &terrain) {
if (terrain.mTerrainGroup)
loadItems();
if (!terrain.mTerrainGroup
->isDerivedDataUpdateInProgress())
terrain.mTerrainGroup->update(false);
});
}
float TerrainModule::get_height(Ogre::TerrainGroup *group,
@@ -783,167 +792,9 @@ void TerrainModule::save_heightmap()
{
HeightData::get_singleton()->save_heightmap();
}
flecs::entity TerrainModule::createItem(const Ogre::Vector3 &position,
const Ogre::Quaternion &orientation,
const Ogre::String &type)
void TerrainModule::defineTerrain(long x, long y)
{
long x, y;
ECS::get<Terrain>().mTerrainGroup->convertWorldPositionToTerrainSlot(
position, &x, &y);
std::pair<long, long> pos{ x, y };
flecs::entity slot =
ECS::get().query_builder<const TerrainSlotParent>().build().find(
[&](const TerrainSlotParent &slot) -> bool {
return slot.slot == pos;
});
if (!slot.is_valid())
slot = ECS::get().entity().add<TerrainSlotParent>();
flecs::entity item = ECS::get().entity().child_of(slot);
nlohmann::json jproperties;
jproperties["type"] = type;
item.set<TerrainItem>({ position, orientation, jproperties.dump() });
return item;
}
void TerrainModule::setItemProperties(flecs::entity id, Ogre::String properties)
{
OgreAssert(id.is_valid(), "bad id");
id.get_mut<TerrainItem>().properties = properties;
id.modified<TerrainItem>();
}
const Ogre::String &TerrainModule::getItemProperties(flecs::entity id)
{
OgreAssert(id.is_valid(), "bad id");
return id.get<TerrainItem>().properties;
}
static void to_json(nlohmann::json &j, const Ogre::Vector3 &position)
{
j["x"] = position.x;
j["y"] = position.y;
j["z"] = position.z;
}
static void to_json(nlohmann::json &j, const Ogre::Quaternion &orientation)
{
j["w"] = orientation.w;
j["x"] = orientation.x;
j["y"] = orientation.y;
j["z"] = orientation.z;
}
static void from_json(const nlohmann::json &j, Ogre::Vector3 &position)
{
position.x = j["x"].get<float>();
position.y = j["y"].get<float>();
position.z = j["z"].get<float>();
}
static void from_json(const nlohmann::json &j, Ogre::Quaternion &orientation)
{
orientation.w = j["w"].get<float>();
orientation.x = j["x"].get<float>();
orientation.y = j["y"].get<float>();
orientation.z = j["z"].get<float>();
}
void TerrainModule::saveItems()
{
Ogre::String path = "resources/buildings/items.list";
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"items.list")) {
Ogre::String group =
Ogre::ResourceGroupManager::getSingleton()
.findGroupContainingResource("items.list");
Ogre::FileInfoListPtr fileInfoList(
Ogre::ResourceGroupManager::getSingleton()
.findResourceFileInfo(group, "items.list"));
OgreAssert(fileInfoList->size() == 1,
"worpd_map.png should be there and only once");
path = fileInfoList->at(0).archive->getName() + "/" +
"items.list";
Ogre::FileSystemLayer::removeFile(path);
}
std::fstream fout(path.c_str(), std::ios::out);
nlohmann::json jitemlist;
ECS::get().query_builder<const TerrainItem>().build().each(
[&](flecs::entity e, const TerrainItem &item) {
nlohmann::json jitem;
to_json(jitem["position"], item.position);
to_json(jitem["orientation"], item.orientation);
to_json(jitem["properties"], item.properties);
jitemlist.push_back(jitem);
});
fout << jitemlist.dump();
fout.close();
}
void TerrainModule::loadItems()
{
if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"items.list"))
return;
Ogre::String group = Ogre::ResourceGroupManager::getSingleton()
.findGroupContainingResource("items.list");
Ogre::DataStreamPtr stream =
Ogre::ResourceGroupManager::getSingleton().openResource(
"items.list", group);
Ogre::String json = stream->getAsString();
nlohmann::json jlist = nlohmann::json::parse(json);
ECS::get().delete_with<TerrainItem>();
ECS::get().delete_with<TerrainSlotParent>();
for (const auto &v : jlist) {
Ogre::Vector3 position;
Ogre::Quaternion orientation;
Ogre::String properties;
from_json(v["position"], position);
from_json(v["orientation"], orientation);
properties = v["properties"].get<Ogre::String>();
long x, y;
ECS::get<Terrain>()
.mTerrainGroup->convertWorldPositionToTerrainSlot(
position, &x, &y);
std::pair<long, long> pos{ x, y };
flecs::entity slot =
ECS::get()
.query_builder<const TerrainSlotParent>()
.build()
.find([&](const TerrainSlotParent &slot)
-> bool {
return slot.slot == pos;
});
if (!slot.is_valid())
slot = ECS::get().entity().add<TerrainSlotParent>();
flecs::entity item = ECS::get().entity().child_of(slot);
item.set<TerrainItem>({ position, orientation, properties });
std::cout << "position: " << item.id() << " " << position
<< std::endl;
}
}
void TerrainModule::getItemPositionPerSlot(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;
});
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);
std::cout << e.id() << " " << item.position
<< std::endl;
});
}
void TerrainModule::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);
std::cout << e.id() << " " << item.position
<< std::endl;
});
ECS::get<Terrain>().definer->define(ECS::get<Terrain>().mTerrainGroup,
x, y);
}
}