Converting vehicle and building workflow to blender2ogre

This commit is contained in:
2025-09-20 05:52:24 +03:00
parent 62e14cf075
commit e967844558
143 changed files with 12687 additions and 51 deletions

View File

@@ -12,24 +12,80 @@ BoatModule::BoatModule(flecs::world &ecs)
ecs.module<BoatModule>();
ecs.component<BoatBase>();
ecs.component<BoatBody>();
ecs.component<BoatType>().on_set([](flecs::entity e, BoatType &type) {
int i;
if (e.has<BoatBody>() || e.has<BoatBase>())
return;
BoatBase &boat = e.ensure<BoatBase>();
boat.mEnt = ECS::get<EngineData>().mScnMgr->createEntity(
type.resourceName);
boat.mNode = ECS::get<EngineData>()
.mScnMgr->getRootSceneNode()
->createChildSceneNode(type.position,
type.orientation);
boat.mNode->attachObject(boat.mEnt);
ecs.system<const EngineData, BoatType>("CreateBoat")
.kind(flecs::OnUpdate)
.without<BoatBase>()
.without<BoatBody>()
.each([](flecs::entity e, const EngineData &eng,
BoatType &type) {
BoatBase &boat = e.ensure<BoatBase>();
if (type.resourceName.find(".glb") !=
std::string::npos) {
boat.mEnt = ECS::get<EngineData>()
.mScnMgr->createEntity(
type.resourceName);
boat.mNode = eng.mScnMgr->getRootSceneNode()
->createChildSceneNode(
type.position,
type.orientation);
boat.mNode->attachObject(boat.mEnt);
BoatBody &body = e.ensure<BoatBody>();
body.body = ECS::get<EngineData>().mWorld->addRigidBody(
0, boat.mEnt, Ogre::Bullet::CT_HULL, nullptr, 2,
0x7fffffff);
e.modified<BoatBody>();
});
BoatBody &body = e.ensure<BoatBody>();
body.body =
ECS::get<EngineData>()
.mWorld->addRigidBody(
0, boat.mEnt,
Ogre::Bullet::CT_HULL,
nullptr, 2, 0x7fffffff);
} else if (type.resourceName.find(".scene") !=
std::string::npos) {
boat.mNode =
ECS::get<EngineData>()
.mScnMgr->getRootSceneNode()
->createChildSceneNode(
type.position,
type.orientation);
Ogre::SceneNode *attachment =
eng.mScnMgr->getRootSceneNode()
->createChildSceneNode();
attachment->loadChildren(type.resourceName);
std::vector<Ogre::Node *> v =
attachment->getChildren();
int i;
OgreAssert(v.size() == 1, "Bad nodes count");
Ogre::Any any =
static_cast<Ogre::SceneNode *>(v[0])
->getUserObjectBindings()
.getUserAny("type");
OgreAssert(any.has_value(),
"bas node type costom prop");
Ogre::String obj_type =
Ogre::any_cast<Ogre::String>(any);
std::cout << "type: " << obj_type << std::endl;
OgreAssert(obj_type == "boat", "not a boat");
boat.mNode =
static_cast<Ogre::SceneNode *>(v[0]);
boat.mNode->_setDerivedPosition(type.position);
boat.mNode->_setDerivedOrientation(
type.orientation);
boat.mEnt = static_cast<Ogre::Entity *>(
boat.mNode->getAttachedObject("boat"));
BoatBody &body = e.ensure<BoatBody>();
body.body =
ECS::get<EngineData>()
.mWorld->addRigidBody(
0, boat.mEnt,
Ogre::Bullet::CT_HULL,
nullptr, 2, 0x7fffffff);
#if 0
boat.mEnt = eng.mScnMgr->getEntity("boat");
boat.mNode = boat.mEnt->get
/* no need to attach anything */
BoatBody &body =
e.ensure<BoatBody>();
#endif
}
e.modified<BoatBody>();
});
}
}

View File

@@ -10,12 +10,15 @@ namespace ECS
{
CharacterModule::CharacterModule(flecs::world &ecs)
{
struct TriggerPhysicsChange {};
ecs.module<CharacterModule>();
ecs.component<Character>();
ecs.component<Player>();
ecs.component<CharacterBase>();
ecs.component<CharacterVelocity>();
ecs.component<CharacterBody>();
ecs.component<CharacterDisablePhysics>();
ecs.component<CharacterUpdatePhysicsState>();
ecs.system<EngineData, CharacterBase>("UpdateTimer")
.kind(flecs::OnUpdate)
.each([this](EngineData &eng, CharacterBase &ch) {
@@ -207,6 +210,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
.with<TerrainReady>()
.with<WaterReady>()
.with<InWater>()
.without<CharacterDisablePhysics>()
.each([this](flecs::entity e, const EngineData &eng,
const CharacterBase &ch, CharacterVelocity &gr) {
Ogre::Vector3 gravity(0, -9.8f, 0);
@@ -245,6 +249,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
.with<WaterReady>()
.without<InWater>()
.with<CharacterGravity>()
.without<CharacterDisablePhysics>()
.each([this](flecs::entity e, const EngineData &eng,
const CharacterBase &ch, CharacterVelocity &gr) {
Ogre::Vector3 gravity(0, -9.8f, 0);
@@ -728,6 +733,21 @@ CharacterModule::CharacterModule(flecs::world &ecs)
<< "\n";
});
#endif
ecs.system<const EngineData, const CharacterBody>("UpdatePhysics")
.kind(flecs::OnUpdate)
.with<CharacterUpdatePhysicsState>()
.write<CharacterUpdatePhysicsState>()
.each([](flecs::entity e, const EngineData &eng,
const CharacterBody &body) {
if (e.has<CharacterDisablePhysics>()) {
eng.mWorld->getBtWorld()->removeAction(
body.mController);
} else {
eng.mWorld->getBtWorld()->addAction(
body.mController);
}
e.remove<CharacterUpdatePhysicsState>();
});
}
void CharacterModule::setAnimation(AnimationControl &anim)

View File

@@ -9,6 +9,8 @@ struct Character {}; /* tag */
struct Player {}; /* tag */
struct CharacterGravity {};
struct CharacterBuoyancy {};
struct CharacterDisablePhysics {};
struct CharacterUpdatePhysicsState {};
struct CharacterBase {
Ogre::String type;
float mTimer;

View File

@@ -24,6 +24,7 @@ struct EngineData {
float startupDelay;
int width;
int height;
bool enableDbgDraw;
};
struct Vector3 {
float x;
@@ -68,6 +69,9 @@ struct App {
OgreBites::InputListenerChain *mInput;
std::vector<OgreBites::InputListener *> listeners;
};
struct CollisionShape {
btCollisionShape *shape;
};
struct InWater {};
struct TerrainReady {};
struct WaterReady {};

View File

@@ -81,12 +81,14 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs)
e.get<EventTrigger>().position,
Ogre::Quaternion(0, 0, 0, 1));
}
/*
Ogre::MeshPtr mesh =
Ogre::MeshManager::getSingleton().createManual(
"trigger", "General");
Ogre::Entity *ent =
ECS::get<EngineData>().mScnMgr->createEntity(mesh);
body.mSceneNode->attachObject(ent);
*/
body.mBody = new btPairCachingGhostObject();
body.mBody->getWorldTransform().setOrigin(Ogre::Bullet::convert(
body.mSceneNode->_getDerivedPosition()));
@@ -100,8 +102,42 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs)
if (kinematic)
flags |= btCollisionObject::CF_STATIC_OBJECT;
body.mBody->setCollisionFlags(flags);
/*
ECS::get<EngineData>().mWorld->attachCollisionObject(
body.mBody, ent, 16, 0x1);
*/
ECS::get<EngineData>().mWorld->getBtWorld()->addCollisionObject(
body.mBody, 16, 0x1);
struct EntityCollisionListener {
const Ogre::MovableObject *entity;
Ogre::Bullet::CollisionListener *listener;
};
body.mBody->setUserPointer(
new EntityCollisionListener{ nullptr, nullptr });
class CollisionObject {
protected:
btCollisionObject *mBtBody;
btCollisionWorld *mBtWorld;
public:
CollisionObject(btCollisionObject *btBody,
btCollisionWorld *btWorld)
: mBtBody(btBody)
, mBtWorld(btWorld)
{
}
virtual ~CollisionObject()
{
mBtWorld->removeCollisionObject(mBtBody);
delete mBtBody->getCollisionShape();
delete mBtBody;
}
};
auto objWrapper = std::make_shared<CollisionObject>(
body.mBody,
ECS::get<EngineData>().mWorld->getBtWorld());
body.mSceneNode->getUserObjectBindings().setUserAny(
"BtCollisionObject", objWrapper);
});
ecs.component<EventTrigger>().on_set(
[](flecs::entity e, EventTrigger &ev) {

View File

@@ -79,8 +79,8 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world,
#endif
});
ecs.set<EngineData>({ scnMgr, world, 0.0f, 5.0f,
(int)window->getWidth(),
(int)window->getHeight() });
(int)window->getWidth(), (int)window->getHeight(),
false });
ecs.set<Camera>({ cameraNode, camera, false });
ecs.add<GameData>();
ecs.add<Input>();

View File

@@ -109,6 +109,14 @@ int luaLibraryLoader(lua_State *L)
return 1;
}
struct LuaChildEventTrigger {
flecs::entity parent_e;
Ogre::Vector3 position;
float halfheight;
float radius;
Ogre::String event;
};
static void installLibraryLoader(lua_State *L)
{
// Insert the c++ func 'luaLibraryLoader' into package.loaders.
@@ -262,8 +270,11 @@ LuaData::LuaData()
Ogre::Quaternion orientation(Ogre::Radian(yaw),
Ogre::Vector3(0, 1, 0));
Ogre::Vector3 position(x, y, z);
e.set<BoatType>({ "boat.glb", position, orientation });
lua_pushinteger(L, idmap.add_entity(e));
e.set<BoatType>(
{ "boat.scene", position, orientation });
int ret = idmap.add_entity(e);
lua_pushinteger(L, ret);
std::cout << "boat created: " << ret << std::endl;
return 1;
}
lua_pushinteger(L, -1);
@@ -301,23 +312,18 @@ LuaData::LuaData()
luaL_checktype(L, 6, LUA_TNUMBER); // halfh
luaL_checktype(L, 7, LUA_TNUMBER); // radius
int parent = lua_tointeger(L, 1);
std::cout << "parent: " << parent << std::endl;
flecs::entity parent_e = idmap.get_entity(parent);
Ogre::SceneNode *parentNode = nullptr;
if (parent_e.has<CharacterBase>())
parentNode = parent_e.get<CharacterBase>().mBodyNode;
else if (parent_e.has<BoatBase>())
parentNode = parent_e.get<BoatBase>().mNode;
flecs::entity e = ECS::get().entity().child_of(parent_e);
Ogre::String event = lua_tostring(L, 2);
float x = lua_tonumber(L, 3);
float y = lua_tonumber(L, 4);
float z = lua_tonumber(L, 5);
float h = lua_tonumber(L, 6);
float r = lua_tonumber(L, 7);
OgreAssert(parentNode, "bad parent");
Ogre::Vector3 position(x, y, z);
e.set<EventTrigger>({ parentNode, position, h, r, event });
flecs::entity e = ECS::get().entity().child_of(parent_e);
e.set<LuaChildEventTrigger>(
{ parent_e, position, h, r, event });
lua_pushinteger(L, idmap.add_entity(e));
return 1;
});
@@ -345,6 +351,54 @@ LuaData::LuaData()
return 1;
});
lua_setglobal(L, "ecs_npc_set");
lua_pushcfunction(L, [](lua_State *L) -> int {
OgreAssert(lua_gettop(L) == 1, "Bad parameters");
luaL_checktype(L, 1, LUA_TSTRING); // type
const char *fileName = lua_tostring(L, 1);
ECS::get<EngineData>().mScnMgr->getRootSceneNode()->saveChildren(
fileName);
return 0;
});
lua_setglobal(L, "ecs_save_scene_debug");
lua_pushcfunction(L, [](lua_State *L) -> int {
OgreAssert(lua_gettop(L) == 2, "Bad parameters");
luaL_checktype(L, 1, LUA_TNUMBER); // object
luaL_checktype(L, 2, LUA_TSTRING); // name
int object = lua_tointeger(L, 1);
flecs::entity object_e = idmap.get_entity(object);
const char *fileName = lua_tostring(L, 2);
Ogre::SceneNode *node = nullptr;
if (object_e.has<CharacterBase>())
node = object_e.get<CharacterBase>().mBodyNode;
else if (object_e.has<BoatBase>())
node = object_e.get<BoatBase>().mNode;
if (node)
node->saveChildren(fileName);
return 0;
});
lua_setglobal(L, "ecs_save_object_debug");
lua_pushcfunction(L, [](lua_State *L) -> int {
luaL_checktype(L, 1, LUA_TBOOLEAN); // object
ECS::get_mut<EngineData>().enableDbgDraw = lua_toboolean(L, 1);
ECS::modified<EngineData>();
return 0;
});
lua_setglobal(L, "ecs_set_debug_drawing");
lua_pushcfunction(L, [](lua_State *L) -> int {
OgreAssert(lua_gettop(L) == 2, "Bad parameters");
luaL_checktype(L, 1, LUA_TNUMBER); // object
luaL_checktype(L, 2, LUA_TBOOLEAN);
int object = lua_tointeger(L, 1);
flecs::entity object_e = idmap.get_entity(object);
bool enable = lua_toboolean(L, 2);
if (enable)
object_e.remove<CharacterDisablePhysics>();
else
object_e.add<CharacterDisablePhysics>();
object_e.add<CharacterUpdatePhysicsState>();
return 0;
});
lua_setglobal(L, "ecs_character_physics_control");
}
LuaData::~LuaData()
@@ -391,6 +445,7 @@ void LuaData::lateSetup()
LuaModule::LuaModule(flecs::world &ecs)
{
ecs.component<LuaChildEventTrigger>();
ecs.component<LuaBase>()
.on_add([](LuaBase &lua) {
lua.mLua = new LuaData;
@@ -399,6 +454,7 @@ LuaModule::LuaModule(flecs::world &ecs)
})
.add(flecs::Singleton);
ecs.add<LuaBase>();
ecs.system<const EngineData, LuaBase>("LuaUpdate")
.kind(flecs::OnUpdate)
.each([](const EngineData &eng, LuaBase &lua) {
@@ -414,5 +470,36 @@ LuaModule::LuaModule(flecs::world &ecs)
}
}
});
ecs.system<const EngineData, const LuaChildEventTrigger>(
"CreateChildTrigger")
.kind(flecs::OnUpdate)
.without<EventTrigger>()
.write<EventTrigger>()
.each([](flecs::entity e, const EngineData &env,
const LuaChildEventTrigger &lct) {
Ogre::SceneNode *parentNode = nullptr;
flecs::entity parent_e = lct.parent_e;
if (parent_e.has<CharacterBase>()) {
parentNode =
parent_e.get<CharacterBase>().mBodyNode;
OgreAssert(
parent_e.get<CharacterBase>().mBodyNode,
"bad node");
} else if (parent_e.has<BoatBase>()) {
parentNode = parent_e.get<BoatBase>().mNode;
OgreAssert(parent_e.get<BoatBase>().mNode,
"bad node");
} else
return;
EventTrigger &trigger = e.ensure<EventTrigger>();
OgreAssert(parentNode, "bad parent");
trigger.position = lct.position;
trigger.halfheight = lct.halfheight;
trigger.radius = lct.radius;
trigger.event = lct.event;
trigger.parent = parentNode;
e.modified<EventTrigger>();
});
}
}