Action nodes support and lots of other updates

This commit is contained in:
2026-01-19 00:07:03 +03:00
parent f86e7fd96c
commit 4b24d85123
34 changed files with 7810 additions and 3488 deletions

File diff suppressed because it is too large Load Diff

22
src/FastNoiseLite/LICENSE Normal file
View File

@@ -0,0 +1,22 @@
MIT License
Copyright(c) 2020 Jordan Peck (jordan.me2@gmail.com)
Copyright(c) 2020 Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,23 @@
## Getting Started
Here's an example for creating a 128x128 array of OpenSimplex2 noise
```cpp
// Create and configure FastNoise object
FastNoiseLite noise;
noise.SetNoiseType(FastNoiseLite::NoiseType_OpenSimplex2);
// Gather noise data
std::vector<float> noiseData(128 * 128);
int index = 0;
for (int y = 0; y < 128; y++)
{
for (int x = 0; x < 128; x++)
{
noiseData[index++] = noise.GetNoise((float)x, (float)y);
}
}
// Do something with this data...
```

View File

@@ -16,7 +16,7 @@
#include "Components.h"
#include "CharacterModule.h"
#include "TerrainModule.h"
#include "GUIModule.h"
#include "GUIModuleCommon.h"
#include "AppModule.h"
#include "EditorGizmoModule.h"
#include "EditorInputModule.h"

View File

@@ -6,9 +6,10 @@ find_package(nlohmann_json REQUIRED)
find_package(OgreProcedural REQUIRED CONFIG)
add_subdirectory(items)
add_library(GameData STATIC GameData.cpp CharacterModule.cpp WaterModule.cpp SunModule.cpp TerrainModule.cpp
GUIModule.cpp LuaData.cpp WorldMapModule.cpp BoatModule.cpp EventTriggerModule.cpp
GUIModule.cpp EditorGUIModule.cpp LuaData.cpp WorldMapModule.cpp BoatModule.cpp EventTriggerModule.cpp
CharacterAnimationModule.cpp PhysicsModule.cpp EventModule.cpp CharacterManagerModule.cpp
VehicleManagerModule.cpp AppModule.cpp StaticGeometryModule.cpp SmartObject.cpp SlotsModule.cpp goap.cpp)
VehicleManagerModule.cpp AppModule.cpp StaticGeometryModule.cpp SmartObject.cpp SlotsModule.cpp
PlayerActionModule.cpp goap.cpp)
target_link_libraries(GameData PUBLIC
lua
flecs::flecs_static

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
#ifndef __EDITORGUIMODULE_H__
#define __EDITORGUIMODULE_H__
namespace ECS {
struct EditorGUIModule {
EditorGUIModule(flecs::world &ecs);
};
}
#endif // EDITORGUIMODULE_H

View File

@@ -26,4 +26,4 @@ struct EventModule {
flecs::entity to);
};
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -6,40 +6,9 @@ namespace OgreBites
}
namespace ECS
{
struct GUI {
bool enabled;
bool grab;
bool grabChanged;
bool narrationBox;
bool mainMenu;
Ogre::String narrationText;
std::vector<Ogre::String> choices;
int narration_answer;
static void setWindowGrab(bool g = true)
{
ECS::GUI &gui = ECS::get().get_mut<GUI>();
if (gui.grab != g) {
gui.grab = g;
gui.grabChanged = true;
ECS::get().modified<GUI>();
}
}
static void finish()
{
ECS::GUI &gui = ECS::get().get_mut<ECS::GUI>();
gui.enabled = false;
gui.mainMenu = false;
gui.narrationBox = false;
ECS::get().modified<ECS::GUI>();
setWindowGrab(true);
}
};
struct GUIModule {
flecs::entity ui_wait;
GUIModule(flecs::world &ecs);
};
struct EditorGUIModule {
EditorGUIModule(flecs::world &ecs);
};
}
#endif
#endif

View File

@@ -0,0 +1,36 @@
#ifndef __GUIMODULECOMMON_H__
#define __GUIMODULECOMMON_H__
namespace ECS
{
struct GUI {
bool enabled;
bool grab;
bool grabChanged;
bool narrationBox;
bool mainMenu;
Ogre::String narrationText;
std::vector<Ogre::String> choices;
int narration_answer;
static void setWindowGrab(bool g = true)
{
ECS::GUI &gui = ECS::get().get_mut<GUI>();
if (gui.grab != g) {
gui.grab = g;
gui.grabChanged = true;
ECS::get().modified<GUI>();
}
}
static void finish()
{
ECS::GUI &gui = ECS::get().get_mut<ECS::GUI>();
gui.enabled = false;
gui.mainMenu = false;
gui.narrationBox = false;
ECS::get().modified<ECS::GUI>();
setWindowGrab(true);
}
};
}
#endif // GUIMODULECOMMON_H

View File

@@ -10,7 +10,9 @@
#include "WaterModule.h"
#include "TerrainModule.h"
#include "SunModule.h"
#include "GUIModuleCommon.h"
#include "GUIModule.h"
#include "EditorGUIModule.h"
#include "LuaData.h"
#include "WorldMapModule.h"
#include "BoatModule.h"
@@ -20,6 +22,7 @@
#include "EventModule.h"
#include "CharacterManagerModule.h"
#include "VehicleManagerModule.h"
#include "PlayerActionModule.h"
#include "AppModule.h"
#include "world-build.h"
@@ -42,7 +45,7 @@ void setup_minimal()
ecs.component<Body2Entity>().add(flecs::Singleton);
}
void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
Ogre::Camera *camera, Ogre::RenderWindow *window)
Ogre::Camera *camera, Ogre::RenderWindow *window)
{
std::cout << "Setup GameData\n";
setup_minimal();
@@ -53,11 +56,13 @@ void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
ecs.import <WaterModule>();
ecs.import <SunModule>();
ecs.import <TerrainModule>();
ecs.import <GUIModule>();
ecs.import <GUIModule>();
ecs.import <EventTriggerModule>();
ecs.import <LuaModule>();
ecs.import <WorldMapModule>();
ecs.import <CharacterAnimationModule>();
ecs.import <PlayerActionModule>();
ecs.add<ActionNodeList>();
ecs.system<EngineData>("UpdateDelta")
.kind(flecs::OnUpdate)
@@ -90,7 +95,7 @@ void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
#endif
});
ecs.set<EngineData>({ scnMgr, 0.0f, 5.0f, (int)window->getWidth(),
(int)window->getHeight(), false });
(int)window->getHeight(), false });
ecs.set<Camera>({ cameraNode, camera, false });
ecs.add<GameData>();
ecs.add<Input>();
@@ -168,7 +173,7 @@ void setupInventoryScene(Ogre::SceneManager *scnMgr,
}
void setupEditor(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
Ogre::Camera *camera, Ogre::RenderWindow *window)
Ogre::Camera *camera, Ogre::RenderWindow *window)
{
std::cout << "Setup Editor\n";
setup_minimal();
@@ -217,7 +222,7 @@ void setupEditor(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
#endif
});
ecs.set<EngineData>({ scnMgr, 0.0f, 5.0f, (int)window->getWidth(),
(int)window->getHeight(), false });
(int)window->getHeight(), false });
ecs.set<Camera>({ cameraNode, camera, false });
#if 0
ecs.set<EditorSceneSwitch>({ 0 });

View File

@@ -6,13 +6,13 @@ namespace ECS
extern flecs::entity player;
void setup_minimal();
void setupExteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
Ogre::Camera *camera, Ogre::RenderWindow *window);
Ogre::Camera *camera, Ogre::RenderWindow *window);
void setupInteriorScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
Ogre::Camera *camera, Ogre::RenderWindow *window);
void setupInventoryScene(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
Ogre::Camera *camera, Ogre::RenderWindow *window);
void setupEditor(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
Ogre::Camera *camera, Ogre::RenderWindow *window);
Ogre::Camera *camera, Ogre::RenderWindow *window);
void setupEditorAlt(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
Ogre::Camera *camera, Ogre::RenderWindow *window);
void update(float delta);

View File

@@ -1,7 +1,7 @@
#include <OgreFileSystemLayer.h>
#include "GameData.h"
#include "Components.h"
#include "GUIModule.h"
#include "GUIModuleCommon.h"
#include "PhysicsModule.h"
#include "CharacterModule.h"
#include "CharacterAnimationModule.h"
@@ -911,4 +911,4 @@ LuaModule::LuaModule(flecs::world &ecs)
}
});
}
}
}

View File

@@ -0,0 +1,114 @@
#include <nanoflann.hpp>
#include <vector>
#include <iostream>
#include "Components.h"
#include "GameData.h"
#include "PlayerActionModule.h"
namespace ECS
{
struct OgreVector3Adaptor {
const std::vector<ActionNodeList::ActionNode> &nodes;
OgreVector3Adaptor(const std::vector<ActionNodeList::ActionNode> &nodes)
: nodes(nodes)
{
}
// Required by nanoflann: Number of data points
inline size_t kdtree_get_point_count() const
{
return nodes.size();
}
// Required by nanoflann: Returns the distance between the vector and a point
// Using squared distance is standard for performance
inline float kdtree_get_pt(const size_t idx, const size_t dim) const
{
return nodes[idx].position[dim];
}
// Optional: bounding box optimization (return false if not implemented)
template <class BBOX> bool kdtree_get_bbox(BBOX & /*bb*/) const
{
return false;
}
};
typedef nanoflann::KDTreeSingleIndexAdaptor<
nanoflann::L2_Simple_Adaptor<float, OgreVector3Adaptor>,
OgreVector3Adaptor, 3 /* dimensionality */
>
OgreKDTree;
struct ActionNodeList::indexObject {
OgreVector3Adaptor adaptor;
OgreKDTree index;
indexObject(const std::vector<ActionNodeList::ActionNode> &nodes)
: adaptor(nodes)
, index(3, adaptor,
nanoflann::KDTreeSingleIndexAdaptorParams(10))
{
}
};
PlayerActionModule::PlayerActionModule(flecs::world &ecs)
{
ecs.module<PlayerActionModule>();
ecs.component<ActionNodeList>()
.on_add([](flecs::entity e, ActionNodeList &alist) {
alist.dirty = true;
alist.nodes.reserve(1000);
})
.add(flecs::Singleton);
#if 0
ecs.system<ActionNodeList>("testNodeList")
.kind(flecs::OnUpdate)
.each([](ActionNodeList &list) {
if (list.nodes.size() > 0) {
Ogre::Vector3 queryPos =
ECS::get<Camera>()
.mCameraNode
->_getDerivedPosition();
std::vector<size_t> points;
list.query(queryPos, points);
for (auto &p : points)
std::cout << p << std::endl
<< list.nodes[p].props.dump()
<< std::endl;
OgreAssert(points.size() == 0, "got result");
}
});
#endif
}
void ActionNodeList::build()
{
indexObj = std::make_shared<ActionNodeList::indexObject>(nodes);
indexObj->index.buildIndex();
dirty = false;
std::cout << "index built" << std::endl;
}
bool ActionNodeList::query(const Ogre::Vector3 &position,
std::vector<size_t> &points)
{
if (dirty)
build();
std::vector<size_t> tmppoints;
std::vector<float> tmpdistances;
points.clear();
points.reserve(4);
tmppoints.resize(4);
tmpdistances.resize(4);
nanoflann::KNNResultSet<float> resultSet(4);
resultSet.init(tmppoints.data(), tmpdistances.data());
bool ret = indexObj->index.findNeighbors(resultSet, &position.x,
nanoflann::SearchParameters());
int i;
for (i = 0; i < resultSet.size(); i++)
if (tmpdistances[i] < 25.0f)
points.push_back(tmppoints[i]);
return ret;
}
}

View File

@@ -0,0 +1,42 @@
#ifndef PLAYERACTIONMODULE_H
#define PLAYERACTIONMODULE_H
#include <flecs.h>
#include <nlohmann/json.hpp>
#include <Ogre.h>
namespace ECS {
struct ActionNodeList {
struct indexObject;
struct ActionNode {
Ogre::String action;
Ogre::String action_text;
Ogre::Vector3 position;
Ogre::Quaternion rotation;
nlohmann::json props;
};
std::vector<ActionNode> nodes;
std::shared_ptr<indexObject> indexObj;
bool dirty;
void build();
bool query(const Ogre::Vector3 &position, std::vector<size_t> &points);
int addNode(struct ActionNodeList::ActionNode &node)
{
int index = nodes.size();
nodes.push_back(node);
dirty = true;
return index;
}
void removeNode(int index)
{
nodes.erase(nodes.begin() + index);
}
};
struct PlayerActionModule
{
PlayerActionModule(flecs::world &ecs);
};
}
#endif // PLAYERACTIONMODULE_H

View File

@@ -6,6 +6,7 @@
#include <OgreRTShaderSystem.h>
#include <OgreStaticGeometry.h>
#include <OgreMeshLodGenerator.h>
#include <OgreWorkQueue.h>
#include <Procedural.h>
#include "Components.h"
#include "GameData.h"
@@ -20,6 +21,7 @@ namespace ECS
static bool itemsLoaded = false;
static bool furnitureLoaded = false;
static bool templatesLoaded = false;
static std::list<std::pair<long, long> > addQueue;
StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
{
@@ -27,6 +29,32 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
ecs.component<TerrainSlotParent>();
ecs.component<TerrainItem>();
ecs.component<FurnitureItem>();
ecs.component<FurnitureInstance>()
.on_remove([](flecs::entity e, FurnitureInstance &instance) {
if (instance.furniture) {
instance.furniture
->destroyAllChildrenAndObjects();
instance.furniture->getCreator()
->destroySceneNode(instance.furniture);
instance.furniture = nullptr;
}
})
.on_set([](flecs::entity e, FurnitureInstance &instance) {
if (instance.furniture !=
e.get<FurnitureInstance>().furniture) {
FurnitureInstance &f =
e.get_mut<FurnitureInstance>();
if (f.furniture) {
f.furniture
->destroyAllChildrenAndObjects();
f.furniture->getCreator()
->destroySceneNode(f.furniture);
}
}
})
.on_add([](flecs::entity e, FurnitureInstance &instance) {
instance.furniture = nullptr;
});
ecs.component<TerrainItemNode>().on_remove([](flecs::entity e,
TerrainItemNode &item) {
if (item.itemNode) {
@@ -42,6 +70,7 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
}
});
ecs.component<TerrainItemMeshNode>();
ecs.component<GeometryUpdateItem>();
ecs.import <TerrainModule>();
ecs.observer<const Terrain>("LoadTerrainItems")
.event(flecs::OnSet)
@@ -65,6 +94,10 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
if (!furnitureLoaded) {
loadFurniture();
furnitureLoaded = true;
}
if (!templatesLoaded) {
loadTemplates();
templatesLoaded = true;
}
std::list<std::pair<long, long> > output;
while (!addQueue.empty()) {
@@ -163,8 +196,48 @@ void StaticGeometryModule::setItemProperties(flecs::entity id,
const Ogre::String &StaticGeometryModule::getItemProperties(flecs::entity id)
{
OgreAssert(id.is_valid(), "bad id");
return id.get<TerrainItem>().properties;
return id.get<TerrainItem>().properties;
}
nlohmann::json templates;
void StaticGeometryModule::loadTemplates()
{
if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"templates.list"))
return;
Ogre::String group =
Ogre::ResourceGroupManager::getSingleton()
.findGroupContainingResource("templates.list");
Ogre::DataStreamPtr stream =
Ogre::ResourceGroupManager::getSingleton().openResource(
"templates.list", group);
Ogre::String json = stream->getAsString();
nlohmann::json jtemplates = nlohmann::json::parse(json);
templates = jtemplates;
}
void StaticGeometryModule::saveTemplates()
{
Ogre::String path = "resources/buildings/templates.list";
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
"templates.list")) {
Ogre::String group =
Ogre::ResourceGroupManager::getSingleton()
.findGroupContainingResource("templates.list");
Ogre::FileInfoListPtr fileInfoList(
Ogre::ResourceGroupManager::getSingleton()
.findResourceFileInfo(group, "templates.list"));
OgreAssert(fileInfoList->size() == 1,
"templates.list should be there and only once");
path = fileInfoList->at(0).archive->getName() + "/" +
"templates.list";
Ogre::FileSystemLayer::removeFile(path);
}
std::fstream fout(path.c_str(), std::ios::out);
fout << templates.dump();
fout.close();
}
void StaticGeometryModule::saveItems()
{
Ogre::String path = "resources/buildings/items.list";
@@ -378,6 +451,58 @@ void StaticGeometryModule::destroyItemGeometry(flecs::entity e)
{
Geometry::destroyItemGeometry(e);
}
nlohmann::json &StaticGeometryModule::getTemplates()
{
return templates;
}
void StaticGeometryModule::updateItemGeometry(flecs::entity e)
{
if (e.has<GeometryUpdateItem>())
return;
e.add<GeometryUpdateItem>();
Ogre::Root::getSingleton().getWorkQueue()->addTask([e]() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
Ogre::Root::getSingleton().getWorkQueue()->addMainThreadTask(
[e]() {
Geometry::updateItemGeometry(e);
e.remove<GeometryUpdateItem>();
});
});
}
void StaticGeometryModule::addTriangleBufferWork(
const Ogre::String &meshName, Ogre::StaticGeometry *geo,
const Ogre::Vector3 &position, const Ogre::Quaternion &rotation,
const Procedural::TriangleBuffer &tb)
{
struct WorkData {
Ogre::String meshName;
Ogre::StaticGeometry *geo;
Ogre::Vector3 position;
Ogre::Quaternion rotation;
Procedural::TriangleBuffer tb;
};
WorkData data = { meshName, geo, position, rotation, tb };
Ogre::Root::getSingleton().getWorkQueue()->addTask([captData = std::move(
data)]() {
Ogre::Root::getSingleton().getWorkQueue()->addMainThreadTask(
[captData]() {
Ogre::MeshPtr mesh =
captData.tb.transformToMesh(
captData.meshName);
Ogre::Entity *ent =
ECS::get<EngineData>()
.mScnMgr->createEntity(mesh);
captData.geo->addEntity(ent, captData.position,
captData.rotation);
ECS::get<EngineData>().mScnMgr->destroyEntity(
ent);
});
});
}
struct TiledMeshes {
struct Tile {
Ogre::String materialName;
@@ -412,13 +537,6 @@ struct TiledMeshes {
if (tiles.find(name) == tiles.end())
return;
tiles[name].positions.erase(packKey(position));
#if 0
auto pos = std::find(tiles[name].positions.begin(),
tiles[name].positions.end(),
packKey(position));
if (pos != tiles[name].positions.end())
tiles[name].positions.erase(pos);
#endif
}
void addTile(const Ogre::String &name, Ogre::MeshPtr mesh)
{
@@ -435,102 +553,6 @@ struct TiledMeshes {
std::shared_ptr<Ogre::IndexData>(
submesh->indexData->clone()),
{} };
#if 0
std::vector<Ogre::Vector3> vertices;
std::vector<uint32_t> indices;
int count = mesh->getNumSubMeshes();
int i, j;
int indexCount = 0;
int vertexCount = 0;
int sharedVertexOffset = 0;
for (i = 0; i < count; i++) {
Ogre::SubMesh *submesh = mesh->getSubMesh(i);
indexCount += submesh->indexData->indexCount;
if (submesh->useSharedVertices)
vertexCount +=
mesh->sharedVertexData->vertexCount;
else
vertexCount += submesh->vertexData->vertexCount;
}
indices.reserve(indexCount);
vertices.reserve(vertexCount);
size_t currentVertexOffset = 0;
bool added_shared = false;
for (i = 0; i < count; i++) {
Ogre::SubMesh *submesh = mesh->getSubMesh(i);
Ogre::VertexData *vertex_data =
submesh->useSharedVertices ?
mesh->sharedVertexData :
submesh->vertexData;
bool add_vertices =
(submesh->useSharedVertices && !added_shared) ||
!submesh->useSharedVertices;
if (add_vertices) {
if (submesh->useSharedVertices)
sharedVertexOffset = vertices.size();
const Ogre::VertexDeclaration *decl =
vertex_data->vertexDeclaration;
const Ogre::VertexBufferBinding *bind =
vertex_data->vertexBufferBinding;
const Ogre::VertexElement *position_element =
decl->findElementBySemantic(
Ogre::VES_POSITION);
if (!position_element)
continue;
Ogre::HardwareVertexBufferSharedPtr vbuf =
bind->getBuffer(
position_element->getSource());
unsigned char *vertex_buffer = static_cast<
unsigned char *>(vbuf->lock(
Ogre::HardwareBuffer::HBL_READ_ONLY));
int vertexSize = vbuf->getVertexSize();
for (j = 0; j < vertex_data->vertexCount; j++) {
float *position_data;
position_element
->baseVertexPointerToElement(
vertex_buffer,
&position_data);
vertices.push_back(
{ position_data[0],
position_data[1],
position_data[2] });
vertex_buffer += vertexSize;
}
if (submesh->useSharedVertices)
added_shared = true;
vbuf->unlock();
}
Ogre::HardwareIndexBufferSharedPtr ibuf =
submesh->indexData->indexBuffer;
size_t numIndices = submesh->indexData->indexCount;
size_t vertexOffset = submesh->useSharedVertices ?
sharedVertexOffset :
currentVertexOffset;
if (ibuf->getType() ==
Ogre::HardwareIndexBuffer::IT_32BIT) {
unsigned int *pIndices = static_cast<
unsigned int *>(ibuf->lock(
Ogre::HardwareBuffer::HBL_READ_ONLY));
for (j = 0; j < numIndices; j++) {
indices.push_back(
(uint32_t)pIndices[j] +
vertexOffset);
}
ibuf->unlock();
} else {
unsigned short *pIndices = static_cast<
unsigned short *>(ibuf->lock(
Ogre::HardwareBuffer::HBL_READ_ONLY));
for (j = 0; j < numIndices; j++) {
indices.push_back(
(uint32_t)pIndices[j] +
vertexOffset);
}
ibuf->unlock();
}
currentVertexOffset = vertices.size();
}
#endif
}
struct buildSettings {
Ogre::String meshName;
@@ -766,10 +788,8 @@ out:;
config.advanced.preventBreakingLines = true;
config.createGeneratedLodLevel(2, 0.15f);
config.createGeneratedLodLevel(20, 0.49f);
#if 0
config.createGeneratedLodLevel(15, 0.49f);
config.createGeneratedLodLevel(150, 0.75f);
#endif
config.advanced.useBackgroundQueue = false;
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(
config);

View File

@@ -3,6 +3,10 @@
#include <flecs.h>
#include <nlohmann/json.hpp>
#include <Ogre.h>
namespace Procedural
{
class TriangleBuffer;
}
namespace Ogre
{
struct LodConfig;
@@ -29,6 +33,10 @@ struct FurnitureItem {
Ogre::String properties;
std::vector<Ogre::String> tags;
};
struct FurnitureInstance {
Ogre::SceneNode *furniture;
};
struct GeometryUpdateItem {};
struct TownCollider {};
@@ -42,7 +50,9 @@ struct StaticGeometryModule {
static void setItemProperties(flecs::entity id,
Ogre::String properties);
static const Ogre::String &getItemProperties(flecs::entity id);
static void saveItems();
static void loadTemplates();
static void saveTemplates();
static void saveItems();
static void loadItems();
static void saveFurniture();
static void loadFurniture();
@@ -56,6 +66,13 @@ struct StaticGeometryModule {
std::list<std::pair<flecs::entity, Ogre::String> > *items);
static void createItemGeometry(flecs::entity e);
static void destroyItemGeometry(flecs::entity e);
static nlohmann::json &getTemplates();
static void updateItemGeometry(flecs::entity e);
static void addTriangleBufferWork(const Ogre::String &meshName,
Ogre::StaticGeometry *geo,
const Ogre::Vector3 &position,
const Ogre::Quaternion &rotation,
const Procedural::TriangleBuffer &tb);
};
}
#endif

View File

@@ -4,7 +4,7 @@ find_package(Bullet REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(OgreProcedural REQUIRED CONFIG)
add_library(items STATIC items.cpp harbour.cpp temple.cpp town.cpp)
target_include_directories(items PUBLIC .)
target_include_directories(items PUBLIC . ${CMAKE_SOURCE_DIR}/src/FastNoiseLite)
target_link_libraries(items PRIVATE
flecs::flecs_static
nlohmann_json::nlohmann_json
@@ -13,4 +13,4 @@ target_link_libraries(items PRIVATE
OgreBites
editor
physics
)
)

View File

@@ -22,6 +22,22 @@ namespace ECS
{
namespace Items
{
void runScriptsForAllTowns()
{
std::pair<flecs::entity, Ogre::String> selected_item;
std::list<std::pair<flecs::entity, Ogre::String> > items;
StaticGeometryModule::getItemsProperties(&items);
for (const auto &item : items) {
nlohmann::json j = nlohmann::json::parse(item.second);
Ogre::String itemType = j["type"].get<Ogre::String>();
if (itemType == "town") {
Items::runAllScriptsForTown(item.first);
if (item.first.has<TerrainItemNode>())
Geometry::updateItemGeometry(item.first);
}
}
StaticGeometryModule::saveItems();
}
void showItemPopup(const std::pair<flecs::entity, Ogre::String> &item)
{
Ogre::String popupLabel =
@@ -131,8 +147,7 @@ void showItemPopup(const std::pair<flecs::entity, Ogre::String> &item)
orientation;
item.first.modified<TerrainItem>();
StaticGeometryModule::saveItems();
StaticGeometryModule::destroyItemGeometry(item.first);
StaticGeometryModule::createItemGeometry(item.first);
StaticGeometryModule::updateItemGeometry(item.first);
}
if (itemType == "harbour")
createHarbourPopup(item);
@@ -194,6 +209,7 @@ namespace Geometry
{
void setupLods(Ogre::LodConfig &config)
{
int count = 0;
// config.advanced.useCompression = false;
config.advanced.useVertexNormals = true;
config.advanced.preventPunchingHoles = true;
@@ -204,7 +220,28 @@ void setupLods(Ogre::LodConfig &config)
// config.createGeneratedLodLevel(200, 0.50f);
config.createGeneratedLodLevel(500, 0.85f);
config.advanced.useBackgroundQueue = false;
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(config);
std::cout << "mesh name: " << config.mesh->getName() << std::endl;
bool crash = false;
for (count = 0; count < config.mesh->getSubMeshes().size(); count++) {
Ogre::SubMesh *submesh = config.mesh->getSubMeshes()[count];
std::cout << "unprocessed submesh: " << count << " " << submesh
<< std::endl;
if (submesh)
submesh->parent = config.mesh.get();
else
crash = true;
}
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(config);
for (count = 0; count < config.mesh->getSubMeshes().size(); count++) {
Ogre::SubMesh *submesh = config.mesh->getSubMeshes()[count];
std::cout << "submesh: " << count << " " << submesh
<< std::endl;
if (submesh)
submesh->parent = config.mesh.get();
else
crash = true;
}
OgreAssert(!crash, "no submesh");
}
Ogre::StaticGeometry *createStaticGeometry(flecs::entity e)
@@ -294,6 +331,14 @@ void destroyItemGeometry(flecs::entity e)
#endif
e.remove<TerrainItemNode>();
}
void updateItemGeometry(flecs::entity e)
{
OgreAssert(e.has<TerrainItem>(), "not terrain item");
if (e.has<TerrainItemNode>())
destroyItemGeometry(e);
createItemGeometry(e);
}
flecs::entity createMeshGeometry(const Ogre::String &meshName,
flecs::entity parente,
Ogre::SceneNode *sceneNode,
@@ -322,7 +367,7 @@ flecs::entity createMeshGeometry(const Ogre::String &meshName,
.set<TerrainItemMeshNode>({ sceneNode, geo });
JoltPhysicsWrapper::getSingleton().addBody(id,
JPH::EActivation::Activate);
return e;
return e;
}
}

View File

@@ -9,6 +9,7 @@ namespace Items
void showItemPopup(const std::pair<flecs::entity, Ogre::String> &item);
void showItemButtons(const std::pair<flecs::entity, Ogre::String> &item);
void createItemsMenu();
void runScriptsForAllTowns();
}
namespace Geometry
{
@@ -53,6 +54,7 @@ struct harbourMaker {
};
void createItemGeometry(flecs::entity e);
void destroyItemGeometry(flecs::entity e);
void updateItemGeometry(flecs::entity e);
flecs::entity createMeshGeometry(const Ogre::String &meshName,
flecs::entity parente,
Ogre::SceneNode *sceneNode,

File diff suppressed because it is too large Load Diff

View File

@@ -12,25 +12,15 @@ namespace Items
void createTownItem();
void createTownMenu();
void createTownPopup(const std::pair<flecs::entity, Ogre::String> item);
void runAllScriptsForTown(flecs::entity e);
}
namespace Geometry
{
void clampUV(flecs::entity e, Procedural::TriangleBuffer &tb,
const Ogre::String &rectKey);
Ogre::MaterialPtr createTownMaterial(flecs::entity e, bool force = false);
void createCells(flecs::entity e, const nlohmann::json &jdistrict, int index,
Ogre::SceneNode *sceneNode, Ogre::StaticGeometry *geo);
void createTown(flecs::entity e, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo);
void createTownPlazza(flecs::entity e, const nlohmann::json &jdistrict,
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo);
void createTownLots(flecs::entity e, const nlohmann::json &jdistrict,
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo);
void createTownRoofs(flecs::entity e, const nlohmann::json &jdistrict,
int index, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo);
}
}
#endif

View File

@@ -90,7 +90,10 @@ public:
Layers::MOVING; // Non moving only collides with moving
case Layers::MOVING:
return true; // Moving collides with everything
default:
case Layers::SENSORS:
return inObject2 ==
Layers::MOVING; // Non moving only collides with moving
default:
JPH_ASSERT(false);
return false;
}
@@ -107,7 +110,8 @@ public:
mObjectToBroadPhase[Layers::NON_MOVING] =
BroadPhaseLayers::NON_MOVING;
mObjectToBroadPhase[Layers::MOVING] = BroadPhaseLayers::MOVING;
}
mObjectToBroadPhase[Layers::SENSORS] = BroadPhaseLayers::MOVING;
}
virtual uint GetNumBroadPhaseLayers() const override
{
@@ -1330,7 +1334,18 @@ public:
OgreAssert(result.Get(), "Can not create com offset shape");
return result.Get();
}
void applyBuoyancyImpulse(JPH::BodyID id,
JPH::ShapeRefC
createRotatedTranslatedShape(const Ogre::Vector3 &offset,
const Ogre::Quaternion rotation,
JPH::ShapeRefC shape)
{
return JPH::RotatedTranslatedShapeSettings(
JoltPhysics::convert(offset),
JoltPhysics::convert(rotation), shape)
.Create()
.Get();
}
void applyBuoyancyImpulse(JPH::BodyID id,
const Ogre::Vector3 &surfacePosition,
const Ogre::Vector3 &surfaceNormal,
float buoyancy, float linearDrag,
@@ -1597,7 +1612,14 @@ JPH::ShapeRefC
JoltPhysicsWrapper::createOffsetCenterOfMassShape(const Ogre::Vector3 &offset,
JPH::ShapeRefC shape)
{
return phys->createOffsetCenterOfMassShape(offset, shape);
return phys->createOffsetCenterOfMassShape(offset, shape);
}
JPH::ShapeRefC JoltPhysicsWrapper::createRotatedTranslatedShape(
const Ogre::Vector3 &offset, const Ogre::Quaternion rotation,
JPH::ShapeRefC shape)
{
return phys->createRotatedTranslatedShape(offset, rotation, shape);
}
JPH::BodyID

View File

@@ -26,7 +26,8 @@ namespace Layers
{
static constexpr JPH::ObjectLayer NON_MOVING = 0;
static constexpr JPH::ObjectLayer MOVING = 1;
static constexpr JPH::ObjectLayer NUM_LAYERS = 2;
static constexpr JPH::ObjectLayer SENSORS = 2;
static constexpr JPH::ObjectLayer NUM_LAYERS = 3;
};
// Each broadphase layer results in a separate bounding volume tree in the broad phase. You at least want to have
@@ -134,7 +135,10 @@ public:
JPH::ShapeRefC
createOffsetCenterOfMassShape(const Ogre::Vector3 &offset,
JPH::ShapeRefC shape);
JPH::BodyID createBody(const JPH::BodyCreationSettings &settings);
JPH::ShapeRefC
createRotatedTranslatedShape(const Ogre::Vector3 &offset, const Ogre::Quaternion rotation,
JPH::ShapeRefC shape);
JPH::BodyID createBody(const JPH::BodyCreationSettings &settings);
JPH::BodyID createBody(const JPH::Shape *shape, float mass,
const Ogre::Vector3 &position,
const Ogre::Quaternion &rotation,