Action nodes work better now

This commit is contained in:
2026-02-01 00:13:33 +03:00
parent 201aa92fe7
commit e6efd89bb0
14 changed files with 548 additions and 126 deletions

View File

@@ -27,6 +27,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
ecs.component<CharacterInActuator>();
ecs.component<Male>();
ecs.component<Female>();
ecs.component<CharacterControlDisable>();
ecs.import <CharacterAnimationModule>();
ecs.import <TerrainModule>();
ecs.import <WaterModule>();
@@ -131,75 +132,14 @@ CharacterModule::CharacterModule(flecs::world &ecs)
else if (current_subm < 0.8f)
ch.is_submerged = false;
});
#if 0
ecs.system<const EngineData, const CharacterBase, CharacterVelocity>(
"HandleGravityBouyanceWater")
.kind(flecs::OnUpdate)
.with<TerrainReady>()
.with<WaterReady>()
.with<InWater>()
.without<CharacterDisablePhysics>()
.without<CharacterUpdatePhysicsState>()
.each([this](flecs::entity e, const EngineData &eng,
const CharacterBase &ch, CharacterVelocity &gr) {
Ogre::Vector3 gravity(0, -9.8f, 0);
Ogre::Vector3 pos = ch.mBodyNode->getPosition();
Ogre::Vector3 v(0, 0, 0);
if (e.has<CharacterGravity>())
v += gravity;
if (e.has<CharacterBuoyancy>()) {
float volume = 2.0f * 0.5f * 0.5f;
float density = 900.0f;
float full_subm = 2.0f;
float mass = 80.0f;
float multiplier = 0.25f;
float current_subm = -Ogre::Math::Clamp(
pos.y + Ogre::Math::Sin(ch.mTimer *
0.13f +
130.0f) *
0.07f,
-full_subm, 0.0f);
Ogre::Vector3 b = -gravity * density * volume *
multiplier * current_subm /
full_subm / mass;
v += b;
}
gr.gvelocity += v * eng.delta;
gr.gvelocity.y =
Ogre::Math::Clamp(gr.gvelocity.y, -2.5f, 1.5f);
gr.gvelocity *= (1.0 - eng.delta);
gr.velocity.y *= (1.0 - eng.delta);
});
#endif
#if 0
ecs.system<const EngineData, const CharacterBase, CharacterVelocity>(
"HandleGravityNoWater")
.kind(flecs::OnUpdate)
.with<TerrainReady>()
.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);
Ogre::Vector3 pos = ch.mBodyNode->getPosition();
gr.gvelocity += gravity * eng.delta;
if (pos.y < -1.2) {
gr.gvelocity.y = 0.0f;
}
gr.gvelocity *= (1.0 - eng.delta);
gr.velocity.y *= (1.0 - eng.delta);
});
#endif
#define TURN_SPEED 500.0f // character turning in degrees per second
ecs.system<const Input, const Camera, CharacterBase>("UpdateBody")
.kind(flecs::OnUpdate)
.with<Character>()
.with<Player>()
.without<CharacterInActuator>()
.each([](flecs::entity e, const Input &input,
.without<CharacterControlDisable>()
.each([](flecs::entity e, const Input &input,
const Camera &camera, CharacterBase &ch) {
ch.mGoalDirection = Ogre::Vector3::ZERO;
float delta = e.world().delta_time();
@@ -604,6 +544,92 @@ void CharacterModule::updateCameraGoal(Camera &camera, Ogre::Real deltaYaw,
}
}
void applyWeightBasedScale(Ogre::Entity *ent,
const Ogre::String &targetBoneName,
const Ogre::Vector3 &scale)
{
Ogre::MeshPtr mesh = ent->getMesh();
Ogre::SkeletonInstance *skel = ent->getSkeleton();
Ogre::Bone *targetBone = skel->getBone(targetBoneName);
// Create a non-uniform scale matrix relative to the bone's local space
Ogre::Matrix4 scaleMatrix = Ogre::Matrix4::IDENTITY;
scaleMatrix.setScale(scale);
for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) {
Ogre::SubMesh *submesh = mesh->getSubMesh(i);
Ogre::VertexData *vertexData = submesh->useSharedVertices ?
mesh->sharedVertexData :
submesh->vertexData;
// 1. Get Position Element
const Ogre::VertexElement *posElem =
vertexData->vertexDeclaration->findElementBySemantic(
Ogre::VES_POSITION);
Ogre::HardwareVertexBufferSharedPtr vbuf =
vertexData->vertexBufferBinding->getBuffer(
posElem->getSource());
// 2. Access Bone Assignments
// This map tells us which bones influence which vertex and by how much
const Ogre::Mesh::VertexBoneAssignmentList &vbal =
submesh->getBoneAssignments();
// Lock buffer for reading and writing
float *pVertices = static_cast<float *>(
vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
for (size_t vIdx = 0; vIdx < vertexData->vertexCount; ++vIdx) {
float totalWeight = 0.0f;
// Find assignments for this specific vertex
for (auto const &[index, assignment] : vbal) {
if (assignment.vertexIndex == vIdx &&
assignment.boneIndex ==
targetBone->getHandle()) {
totalWeight = assignment.weight;
break;
}
}
if (totalWeight > 0.0f) {
float *pPos;
posElem->baseVertexPointerToElement(
reinterpret_cast<unsigned char *>(
pVertices) +
vIdx * vbuf->getVertexSize(),
&pPos);
Ogre::Vector3 vertexPos(pPos[0], pPos[1],
pPos[2]);
// Transform vertex to bone local space, scale it, then move back
// This ensures scaling happens along the bone's axis, not the world axis
Ogre::Vector3 localPos =
targetBone->_getDerivedOrientation()
.Inverse() *
(vertexPos -
targetBone->_getDerivedPosition());
Ogre::Vector3 scaledLocalPos =
scaleMatrix * localPos;
Ogre::Vector3 worldPos =
(targetBone->_getDerivedOrientation() *
scaledLocalPos) +
targetBone->_getDerivedPosition();
// Interpolate based on weight (Lerp) to handle vertices shared with other bones
Ogre::Vector3 finalPos = Ogre::Math::lerp(
vertexPos, worldPos, totalWeight);
pPos[0] = finalPos.x;
pPos[1] = finalPos.y;
pPos[2] = finalPos.z;
}
}
vbuf->unlock();
}
}
void CharacterModule::createCharacter(flecs::entity e,
const Ogre::Vector3 &position,
const Ogre::Quaternion &rotation,