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

@@ -9,11 +9,16 @@
#include <OgreImGuiInputListener.h>
#include <OgreFontManager.h>
#include <OgreTerrainGroup.h>
#include <OgrePagedWorld.h>
#include <OgreTerrainPaging.h>
#include <OgreTerrainPagedWorldSection.h>
#include <nlohmann/json.hpp>
#include "GameData.h"
#include "Components.h"
#include "LuaData.h"
#include "AppModule.h"
#include "TerrainModule.h"
#include "StaticGeometryModule.h"
#include "EditorGizmoModule.h"
#include "GUIModule.h"
namespace ECS
@@ -701,6 +706,7 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
float strength = 0.0f;
int size = 0;
long slot_x, slot_y;
float cursorAngle = 0;
void updateWorldTexture()
{
// Get the hardware pixel buffer
@@ -733,21 +739,16 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
ECS::get<Terrain>()
.mTerrainGroup->convertWorldPositionToTerrainSlot(
worldPos, &x, &y);
int i, j;
for (j = -1; j < 2; j++)
for (i = -1; i < 2; i++) {
Ogre::Terrain *terrain =
ECS::get<Terrain>()
.mTerrainGroup->getTerrain(
x + j, y + i);
if (terrain && terrain->isLoaded()) {
terrain->dirty();
terrain->update(true);
terrain->waitForDerivedProcesses();
}
}
ECS::get<Terrain>().mTerrainGroup->update(true);
for (auto &slot :
ECS::get<Terrain>().mTerrainGroup->getTerrainSlots()) {
Ogre::uint32 page =
ECS::get<Terrain>().mTerrainGroup->packIndex(
slot.second->x, slot.second->y);
ECS::get<Terrain>()
.mTerrainPagedWorldSection->unloadPage(page,
false);
}
ECS::get<Terrain>().mTerrainGroup->update(false);
}
void setCursorPos(Ogre::Vector3 &cursorPosition,
Ogre::Quaternion &orientation)
@@ -793,6 +794,229 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
.mCameraGoal->_getDerivedOrientation());
updateHeightmap();
}
void setCursorSelectedPos(flecs::entity e, Ogre::Vector3 &position,
Ogre::Quaternion &orientation)
{
StaticGeometryModule::getItemPositionAndRotation(e, position,
orientation);
selected_x = TerrainModule::get_img_x(position.x);
selected_y = TerrainModule::get_img_y(position.z);
ECS::get<EditorGizmo>().sceneNode->_setDerivedPosition(
position);
ECS::get<EditorGizmo>().sceneNode->_setDerivedOrientation(
orientation);
}
void setCameraSelectedPos(flecs::entity e)
{
Ogre::Vector3 cursorPos;
Ogre::Quaternion cursorOrientation;
setCursorSelectedPos(e, cursorPos, cursorOrientation);
Ogre::Vector3 cameraPos =
ECS::get<Camera>().mCameraPivot->_getDerivedPosition();
Ogre::Vector3 cameraOffset =
cursorOrientation * Ogre::Vector3::UNIT_Z * 30.0f;
cameraPos.x = cursorPos.x;
cameraPos.z = cursorPos.z;
cameraPos += cameraOffset;
cameraPos.y =
TerrainModule::get_height(
ECS::get<Terrain>().mTerrainGroup, cameraPos) +
10.0f;
if (cameraPos.y < 0.0f)
cameraPos.y = 10.0f;
ECS::get<Camera>().mCameraPivot->_setDerivedPosition(cameraPos);
ECS::get<Camera>().mCameraPivot->_setDerivedOrientation(
cursorOrientation);
cameraPos =
ECS::get<Camera>().mCameraGoal->_getDerivedPosition();
ECS::get<Camera>().mCameraNode->_setDerivedPosition(cameraPos);
ECS::get<Camera>().mCameraNode->_setDerivedOrientation(
ECS::get<Camera>()
.mCameraGoal->_getDerivedOrientation());
updateHeightmap();
}
void setSurfaceLevel(int actualSize, int center_x, int center_y,
float level)
{
int i, j;
float original = level;
if (actualSize == 1)
level += 0.4f;
else if (actualSize == 2)
level += 0.35f;
original = Ogre::Math::Clamp(original, 0.0f, 1.0f);
for (i = -actualSize; i < actualSize + 1; i++)
for (j = -actualSize; j < actualSize + 1; j++) {
if (i * i + j * j > actualSize * actualSize)
continue;
if (center_x + j < 0 ||
center_x + j >= worldMap->getWidth())
continue;
if (center_y + i < 0 ||
center_y + i >= worldMap->getHeight())
continue;
Ogre::ColourValue cv =
worldMapImage.getColourAt(
center_x + j, center_y + i, 0);
cv.r = original;
worldMapImage.setColourAt(cv, center_x + j,
center_y + i, 0);
}
updateWorldTexture();
updateHeightmap();
}
void setHarbourSurface()
{
int base_size = 3;
float base_height = 0.517f;
float base_step = 0.1f;
float deep = 0.25f;
float shallow = 0.35f;
float maxStep = 600.0f;
Ogre::Vector3 basePos =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion baseRot =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
float baseOffset = 200.0f;
Ogre::Vector3 stepOffset =
baseRot * Ogre::Vector3::NEGATIVE_UNIT_Z * baseOffset;
std::vector<float> heights = { deep, shallow, base_height,
base_height + base_step,
base_height + base_step * 2.0f };
int step_count = 0;
for (float height : heights) {
float localStep = 0.0f;
Ogre::Vector3 currentPosition =
basePos + stepOffset * (float)step_count -
stepOffset * 0.5f;
float goTill = maxStep;
if (step_count < 2)
goTill += 420.0f;
while (localStep <
goTill - 150.0f * (float)step_count) {
localStep += baseOffset;
currentPosition += stepOffset;
int center_x = TerrainModule::get_img_x(
currentPosition.x);
int center_y = TerrainModule::get_img_y(
currentPosition.z);
int size = base_size + 10 - step_count * 2;
if (step_count < 2)
size = base_size + 14 - step_count * 2;
if (step_count == 0)
size += 1;
setSurfaceLevel(size, center_x, center_y,
height);
}
step_count++;
}
}
/* This is editor function */
static bool findPierOffset(float &offset)
{
Ogre::Vector3 basePos =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion baseRot =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1);
float length = 0.0f;
while (length < 250.0f) {
Ogre::Vector3 currentPosition =
basePos + direction * length;
float height =
ECS::get<Terrain>()
.mTerrainGroup->getHeightAtWorldPosition(
currentPosition);
if (height < -4.0f) {
offset = length;
break;
}
length += 2.0f;
}
return length < 250.0f;
}
static bool findPierOffsetAndLengthAndDepth(float &offset,
float &length, float &depth)
{
if (!findPierOffset(offset))
return false;
Ogre::Vector3 basePos =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion baseRot =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1);
length = 0.0f;
depth = 4.0f;
while (length < 60.0f) {
Ogre::Vector3 currentPosition =
basePos + direction * (offset + length);
float height =
ECS::get<Terrain>()
.mTerrainGroup->getHeightAtWorldPosition(
currentPosition);
if (depth < -height)
depth = -height;
if (height > -4.0f)
break;
length += 6.0f;
}
return true;
}
static void findPierHeight(float maxLength, float &height)
{
Ogre::Vector3 basePos =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion baseRot =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
Ogre::Vector3 direction = baseRot * Ogre::Vector3(0, 0, 1);
float length = 0.0f;
height = 0.0f;
while (length < 60.0f) {
Ogre::Vector3 currentPosition =
basePos + direction * (length);
float dheight =
ECS::get<Terrain>()
.mTerrainGroup->getHeightAtWorldPosition(
currentPosition);
if (height < dheight)
height = dheight;
length += 1.0f;
}
}
void createHarbourItem()
{
Ogre::Vector3 itemPosition =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion itemOrientation =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
float pierLength, pierDepth;
float pierOffset;
float pierHeight;
if (!findPierOffsetAndLengthAndDepth(pierOffset, pierLength,
pierDepth))
return;
findPierHeight(pierOffset + pierLength, pierHeight);
flecs::entity e = StaticGeometryModule::createItem(
itemPosition, itemOrientation, "harbour");
Ogre::String prop = StaticGeometryModule::getItemProperties(e);
nlohmann::json j = nlohmann::json::parse(prop);
j["pierOffset"] = pierOffset;
j["pierLength"] = pierLength;
j["pierDepth"] = pierDepth;
j["pierHeight"] = pierHeight;
StaticGeometryModule::setItemProperties(e, j.dump());
// setHarbourSurface();
StaticGeometryModule::saveItems();
// updateWorldTexture();
// updateHeightmap();
// TerrainModule::save_heightmap();
}
void worldMapView()
{
OgreAssert(TerrainModule::get_img_x(0) ==
@@ -885,20 +1109,29 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
1.0f, IM_COL32(0, 255, 0, 255));
{
std::list<Ogre::Vector3> positions;
TerrainModule::getItemPositions(&positions);
StaticGeometryModule::getItemPositions(&positions);
for (auto pos : positions) {
int item_x = TerrainModule::get_img_x(pos.x);
int item_y = TerrainModule::get_img_y(pos.z);
draw_list->AddCircleFilled(
ImVec2(top_x + item_x, top_y + item_y),
3.0f, IM_COL32(255, 255, 0, 255));
std::cout << pos << std::endl;
}
}
if (locationSelected)
draw_list->AddCircleFilled(
ImVec2(top_x + selected_x, top_y + selected_y),
4.0f, IM_COL32(64, 255, 64, 255));
{
Ogre::Vector3 cursorPos =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedPosition();
int cursor_x = TerrainModule::get_img_x(cursorPos.x);
int cursor_y = TerrainModule::get_img_y(cursorPos.z);
draw_list->AddCircleFilled(
ImVec2(top_x + cursor_x, top_y + cursor_y),
4.0f, IM_COL32(255, 64, 64, 128));
}
ImGui::PopStyleVar();
ImGui::Spacing();
ImGui::EndChild();
@@ -924,16 +1157,32 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
position.y, position.z);
}
if (ImGui::Button("Update terrain")) {
ECS::get<Terrain>().mTerrainGroup->update(true);
ECS::get<Terrain>().mTerrainGroup->update(false);
}
ImGui::SliderFloat("Strength...", &strength, 0.0f, 0.2f);
ImGui::SliderInt("Size", &size, 0, 8);
if (ImGui::Button("Update cursor position")) {
Ogre::Vector3 position =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedPosition();
position.y =
ECS::get<Terrain>()
.mTerrainGroup
->getHeightAtWorldPosition(position);
ECS::get<EditorGizmo>().sceneNode->_setDerivedPosition(
position);
}
ImGui::SliderFloat("Strength...", &strength, 0.0f, 1.0f);
ImGui::SliderInt("Size", &size, 0, 32);
ImGui::SliderFloat("Cursor Angle...", &cursorAngle, -180.0f,
180.0f);
bool riseLower = false;
bool riseLower2 = false;
bool smooth = false;
bool setLevel = false;
float setLevelValue = 0.0f;
float riseLowerChange = 0.0f;
ECS::get<EditorGizmo>().sceneNode->_setDerivedOrientation(
Ogre::Quaternion(Ogre::Degree(cursorAngle),
Ogre::Vector3::UNIT_Y));
if (ImGui::Button("Elevate")) {
riseLower = true;
riseLowerChange = strength;
@@ -957,9 +1206,19 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
setLevelValue = 0.0f;
}
ImGui::SameLine();
if (ImGui::Button("Highest")) {
if (ImGui::Button("Deep")) {
setLevel = true;
setLevelValue = 1.0f;
setLevelValue = 0.25f;
}
ImGui::SameLine();
if (ImGui::Button("Shallow1")) {
setLevel = true;
setLevelValue = 0.35f;
}
ImGui::SameLine();
if (ImGui::Button("Shallow2")) {
setLevel = true;
setLevelValue = 0.47f;
}
ImGui::SameLine();
if (ImGui::Button("Beach")) {
@@ -994,16 +1253,56 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
setLevel = true;
setLevelValue = 0.646f;
}
if (ImGui::Button("Harbour")) {
Ogre::Vector3 itemPosition =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedPosition();
Ogre::Quaternion itemOrientation =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
TerrainModule::createItem(itemPosition, itemOrientation,
"harbour");
TerrainModule::saveItems();
ImGui::SameLine();
if (ImGui::Button("Highest")) {
setLevel = true;
setLevelValue = 1.0f;
}
if (ImGui::Button("Harbour"))
createHarbourItem();
flecs::entity selected_item;
bool item_is_selected = false;
{
std::list<std::pair<flecs::entity, Ogre::String> > items;
StaticGeometryModule::getItemsProperties(&items);
for (const auto &item : items) {
Ogre::String label =
Ogre::StringConverter::toString(
item.first.id());
label += item.second.substr(0, 32);
if (ImGui::SmallButton(
label.c_str())) { /* select */
selected_item = item.first;
item_is_selected = true;
setCameraSelectedPos(selected_item);
}
ImGui::SameLine();
Ogre::String upd_label =
"Update Height##" +
Ogre::StringConverter::toString(
item.first.id());
if (ImGui::SmallButton(upd_label.c_str())) {
TerrainItem &uitem =
item.first
.get_mut<TerrainItem>();
uitem.position.y =
ECS::get<Terrain>()
.mTerrainGroup
->getHeightAtWorldPosition(
uitem.position);
StaticGeometryModule::saveItems();
}
ImGui::SameLine();
Ogre::String del_label =
"delete##" +
Ogre::StringConverter::toString(
item.first.id());
if (ImGui::SmallButton(del_label.c_str())) {
item.first.destruct();
StaticGeometryModule::saveItems();
}
ImGui::Spacing();
}
}
if (riseLower) {
int actualSize = 1 + size * 2;
@@ -1058,12 +1357,6 @@ struct EditorGUIListener : public Ogre::RenderTargetListener {
float actualStrength =
riseLowerChange /
(1.0f + (float)(i * i + j * j));
if (i * i + j * j ==
actualSize * actualSize) {
std::cout << actualStrength
<< std::endl;
// OgreAssert(false, "strength");
}
Ogre::ColourValue cv =
worldMapImage.getColourAt(
selected_x + j,
@@ -1597,6 +1890,7 @@ EditorGUIModule::EditorGUIModule(flecs::world &ecs)
{
ecs.module<EditorGUIModule>();
ecs.import <AppModule>();
ecs.import <StaticGeometryModule>();
ecs.component<GUI>()
.on_add([](GUI &gui) {
gui.enabled = true;