Working on new animations
This commit is contained in:
1 parent
fe01a5d1b2
commit
52c4ad8ee0
33 files changed
+417542
-134
No files matched your search
+174
-90
@@ -7,6 +7,8 @@
|
||||
namespace ZL {
|
||||
|
||||
const float ATTACK_COOLDOWN_TIME = 3.0f;
|
||||
extern float x;
|
||||
extern float y;
|
||||
|
||||
void Character::loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile) {
|
||||
auto& data = animations[state];
|
||||
@@ -79,113 +81,111 @@ AnimationState Character::resolveActiveState() const {
|
||||
}
|
||||
|
||||
void Character::update(int64_t deltaMs) {
|
||||
//std::cout << "update called with deltaMs: " << deltaMs << std::endl;
|
||||
// Move toward walk target on the XZ plane
|
||||
Eigen::Vector3f activeTarget = walkTarget;
|
||||
if (!pathWaypoints.empty() && currentWaypointIndex < pathWaypoints.size()) {
|
||||
activeTarget = pathWaypoints[currentWaypointIndex];
|
||||
}
|
||||
|
||||
Eigen::Vector3f toTarget = activeTarget - position;
|
||||
toTarget.y() = 0.f;
|
||||
float dist = toTarget.norm();
|
||||
|
||||
if (dist > WALK_THRESHOLD) {
|
||||
Eigen::Vector3f dir = toTarget / dist;
|
||||
float moveAmount = walkSpeed * static_cast<float>(deltaMs) / 1000.f;
|
||||
if (moveAmount >= dist) {
|
||||
position = activeTarget;
|
||||
position.y() = 0.f;
|
||||
} else {
|
||||
position += dir * moveAmount;
|
||||
}
|
||||
targetFacingAngle = atan2(dir.x(), -dir.z());
|
||||
if (battle_state == 0 && currentState == AnimationState::STAND)
|
||||
{
|
||||
currentState = AnimationState::WALK;
|
||||
}
|
||||
} else {
|
||||
if (battle_state == 0 &&
|
||||
currentState == AnimationState::WALK
|
||||
)
|
||||
{
|
||||
currentState = AnimationState::STAND;
|
||||
}
|
||||
|
||||
const bool hasNextWaypoint = !pathWaypoints.empty() && currentWaypointIndex + 1 < pathWaypoints.size();
|
||||
if (hasNextWaypoint) {
|
||||
++currentWaypointIndex;
|
||||
}
|
||||
else {
|
||||
pathWaypoints.clear();
|
||||
currentWaypointIndex = 0;
|
||||
}
|
||||
|
||||
if (!hasNextWaypoint && onArrivedCallback) {
|
||||
auto cb = std::move(onArrivedCallback);
|
||||
onArrivedCallback = nullptr;
|
||||
cb();
|
||||
}
|
||||
}
|
||||
|
||||
if (battle_state == 1 && attack == 1 && attackTarget != nullptr)
|
||||
//weaponInitialRotation = Eigen::AngleAxisf(x/180.0, Eigen::Vector3f::UnitZ()).toRotationMatrix();
|
||||
//weaponInitialRotation = Eigen::AngleAxisf(-M_PI*0.5, Eigen::Vector3f::UnitZ()).toRotationMatrix();
|
||||
//weaponInitialPosition = Eigen::Vector3f(0, 0.09, 0.016);
|
||||
/*if (deltaMs > 200)
|
||||
{
|
||||
targetFacingAngle = atan2(attackTarget->position.x() - position.x(), -(attackTarget->position.z() - position.z()));
|
||||
deltaMs = 200;
|
||||
}*/
|
||||
Eigen::Vector3f activeTarget;
|
||||
Eigen::Vector3f lookTarget;
|
||||
|
||||
if (attackTarget == nullptr)
|
||||
{
|
||||
battle_state = 0;
|
||||
attack = 0;
|
||||
}
|
||||
|
||||
// Rotate toward target facing angle at constant angular speed
|
||||
float angleDiff = targetFacingAngle - facingAngle;
|
||||
while (angleDiff > static_cast<float>(M_PI)) angleDiff -= 2.f * static_cast<float>(M_PI);
|
||||
while (angleDiff < -static_cast<float>(M_PI)) angleDiff += 2.f * static_cast<float>(M_PI);
|
||||
float rotStep = rotationSpeed * static_cast<float>(deltaMs) / 1000.f;
|
||||
if (std::fabs(angleDiff) <= rotStep) {
|
||||
facingAngle = targetFacingAngle;
|
||||
} else {
|
||||
facingAngle += (angleDiff > 0.f ? rotStep : -rotStep);
|
||||
}
|
||||
|
||||
if (canAttack && attackTarget != nullptr)
|
||||
if (attackTarget != nullptr)
|
||||
{
|
||||
float distToGhost = (attackTarget->position - position).norm();
|
||||
if (distToGhost >= 10.f)
|
||||
{
|
||||
if (isPlayer)
|
||||
{
|
||||
setTarget(attackTarget->position);
|
||||
}
|
||||
if (battle_state != 0)
|
||||
{
|
||||
battle_state = 0;
|
||||
setTarget(attackTarget->position);
|
||||
}
|
||||
battle_state = 0;
|
||||
|
||||
}
|
||||
else if (distToGhost < 10.0f && distToGhost >= 1.f) {
|
||||
setTarget(attackTarget->position);
|
||||
if (battle_state != 0)
|
||||
{
|
||||
battle_state = 0;
|
||||
}
|
||||
battle_state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
setTarget(position);
|
||||
if (battle_state != 1)
|
||||
{
|
||||
battle_state = 1;
|
||||
}
|
||||
battle_state = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (attackTarget == nullptr)
|
||||
|
||||
|
||||
if (!pathWaypoints.empty() && currentWaypointIndex < pathWaypoints.size()) {
|
||||
activeTarget = pathWaypoints[currentWaypointIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (battle_state != 0)
|
||||
{
|
||||
battle_state = 0;
|
||||
attack = 0;
|
||||
}
|
||||
|
||||
activeTarget = walkTarget;
|
||||
}
|
||||
|
||||
if (battle_state == 0)
|
||||
{
|
||||
lookTarget = activeTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
lookTarget = attackTarget->position;
|
||||
}
|
||||
|
||||
targetFacingAngle = facingAngle;
|
||||
|
||||
if (currentState == AnimationState::WALK || currentState == AnimationState::STAND)
|
||||
{
|
||||
Eigen::Vector3f toTarget = activeTarget - position;
|
||||
toTarget.y() = 0.f;
|
||||
float dist = toTarget.norm();
|
||||
|
||||
if (dist > WALK_THRESHOLD) {
|
||||
Eigen::Vector3f dir = toTarget / dist;
|
||||
float moveAmount = walkSpeed * static_cast<float>(deltaMs) / 1000.f;
|
||||
if (moveAmount >= dist) {
|
||||
position = activeTarget;
|
||||
position.y() = 0.f;
|
||||
}
|
||||
else {
|
||||
position += dir * moveAmount;
|
||||
}
|
||||
targetFacingAngle = atan2(dir.x(), -dir.z());
|
||||
currentState = AnimationState::WALK;
|
||||
}
|
||||
else {
|
||||
currentState = AnimationState::STAND;
|
||||
|
||||
const bool hasNextWaypoint = !pathWaypoints.empty() && currentWaypointIndex + 1 < pathWaypoints.size();
|
||||
if (hasNextWaypoint) {
|
||||
++currentWaypointIndex;
|
||||
}
|
||||
else {
|
||||
pathWaypoints.clear();
|
||||
currentWaypointIndex = 0;
|
||||
}
|
||||
|
||||
if (!hasNextWaypoint && onArrivedCallback) {
|
||||
auto cb = std::move(onArrivedCallback);
|
||||
onArrivedCallback = nullptr;
|
||||
cb();
|
||||
}
|
||||
|
||||
targetFacingAngle = facingAngle;
|
||||
}
|
||||
}
|
||||
|
||||
if (battle_state == 1)
|
||||
{
|
||||
targetFacingAngle = atan2(lookTarget.x() - position.x(), -(lookTarget.z() - position.z()));
|
||||
|
||||
if (currentState == AnimationState::STAND || currentState == AnimationState::WALK) {
|
||||
currentState = AnimationState::STAND_TO_ACTION;
|
||||
resetAnim = true;
|
||||
@@ -209,7 +209,7 @@ void Character::update(int64_t deltaMs) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentState == AnimationState::STAND_TO_ACTION
|
||||
if (currentState == AnimationState::STAND_TO_ACTION
|
||||
|| currentState == AnimationState::ACTION_IDLE
|
||||
|| currentState == AnimationState::ACTION_ATTACK
|
||||
) {
|
||||
@@ -218,6 +218,19 @@ void Character::update(int64_t deltaMs) {
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate toward target facing angle at constant angular speed
|
||||
float angleDiff = targetFacingAngle - facingAngle;
|
||||
while (angleDiff > static_cast<float>(M_PI)) angleDiff -= 2.f * static_cast<float>(M_PI);
|
||||
while (angleDiff < -static_cast<float>(M_PI)) angleDiff += 2.f * static_cast<float>(M_PI);
|
||||
float rotStep = rotationSpeed * static_cast<float>(deltaMs) / 1000.f;
|
||||
if (std::fabs(angleDiff) <= rotStep) {
|
||||
facingAngle = targetFacingAngle;
|
||||
} else {
|
||||
facingAngle += (angleDiff > 0.f ? rotStep : -rotStep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
auto it = animations.find(currentState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
@@ -229,7 +242,22 @@ void Character::update(int64_t deltaMs) {
|
||||
anim.currentFrame = 0;
|
||||
}
|
||||
anim.currentFrame += static_cast<float>(deltaMs) / 24.f;
|
||||
|
||||
//std::cout << "Current animation frame: " << anim.currentFrame << " / " << anim.totalFrames << " -- " << anim.lastFrame << std::endl;
|
||||
|
||||
if (static_cast<int>(anim.currentFrame) >= 20 && currentState == AnimationState::STAND_TO_ACTION)
|
||||
{
|
||||
showWeapon = true;
|
||||
}
|
||||
else if (static_cast<int>(anim.currentFrame) <= 32 && currentState == AnimationState::ACTION_TO_STAND)
|
||||
{
|
||||
showWeapon = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
showWeapon = false;
|
||||
}
|
||||
|
||||
int frms = anim.model.animations[0].keyFrames[anim.model.animations[0].keyFrames.size() - 1].frame;
|
||||
if (static_cast<int>(anim.currentFrame) >= frms) {
|
||||
anim.currentFrame = anim.model.startingFrame;
|
||||
@@ -255,9 +283,8 @@ void Character::update(int64_t deltaMs) {
|
||||
|
||||
|
||||
if (static_cast<int>(anim.currentFrame) != anim.lastFrame) {
|
||||
if (useGpuSkinning) {
|
||||
anim.gpuSkinningShaderData.ComputeSkinningMatrices(anim.model.startBones, anim.model.animations[0].keyFrames, static_cast<int>(anim.currentFrame));
|
||||
} else {
|
||||
anim.gpuSkinningShaderData.ComputeSkinningMatrices(anim.model.startBones, anim.model.animations[0].keyFrames, static_cast<int>(anim.currentFrame));
|
||||
if (!useGpuSkinning) {
|
||||
anim.model.Interpolate(static_cast<int>(anim.currentFrame));
|
||||
}
|
||||
anim.lastFrame = static_cast<int>(anim.currentFrame);
|
||||
@@ -294,6 +321,9 @@ void Character::draw(Renderer& renderer) {
|
||||
renderer.DrawVertexRenderStruct(modelMutable);
|
||||
|
||||
renderer.PopMatrix();
|
||||
|
||||
drawAttachedWeapon(renderer);
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
}
|
||||
@@ -351,8 +381,14 @@ void Character::drawGpuSkinning(Renderer& renderer) {
|
||||
#endif
|
||||
|
||||
anim.gpuSkinningShaderData.RenderVBO(renderer);
|
||||
|
||||
|
||||
renderer.PopMatrix();
|
||||
|
||||
renderer.shaderManager.PushShader(defaultShaderName);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
drawAttachedWeapon(renderer);
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
}
|
||||
@@ -385,6 +421,38 @@ bool Character::prepareGpuSkinning()
|
||||
return true;
|
||||
}
|
||||
|
||||
void Character::drawAttachedWeapon(Renderer& renderer)
|
||||
{
|
||||
if (!showWeapon) return;
|
||||
if (weaponMesh.data.PositionData.size() == 0 || !weaponTexture) return;
|
||||
|
||||
auto it = animations.find(resolveActiveState());
|
||||
if (it == animations.end()) return;
|
||||
|
||||
auto& anim = it->second;
|
||||
if (anim.gpuSkinningShaderData.skinningMatrices.empty()) return;
|
||||
|
||||
int boneIdx = anim.model.findBoneIndex(weaponAttachBoneName);
|
||||
if (boneIdx < 0) return;
|
||||
|
||||
const Eigen::Matrix4f& bindBone = anim.model.animations[0].keyFrames[0].bones[boneIdx].boneMatrixWorld;
|
||||
Eigen::Matrix4f currentBone = anim.gpuSkinningShaderData.skinningMatrices[boneIdx] * bindBone;
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ position.x(), position.y(), position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(modelScale);
|
||||
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix(Eigen::Vector3f(currentBone.block<3, 1>(0, 3)));
|
||||
renderer.RotateMatrix(Eigen::Matrix3f(currentBone.block<3, 3>(0, 0)));
|
||||
renderer.TranslateMatrix(weaponInitialPosition);
|
||||
renderer.RotateMatrix(weaponInitialRotation);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, weaponTexture->getTexID());
|
||||
renderer.DrawVertexRenderStruct(weaponMesh);
|
||||
renderer.PopMatrix();
|
||||
}
|
||||
|
||||
// ==================== Shadow depth pass ====================
|
||||
|
||||
void Character::drawShadowDepth(Renderer& renderer) {
|
||||
@@ -412,8 +480,9 @@ void Character::drawShadowDepthCpu(Renderer& renderer) {
|
||||
modelMutable.AssignFrom(anim.model.mesh);
|
||||
modelMutable.RefreshVBO();
|
||||
renderer.DrawVertexRenderStruct(modelMutable);
|
||||
|
||||
renderer.PopMatrix();
|
||||
|
||||
drawAttachedWeapon(renderer);
|
||||
}
|
||||
|
||||
void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
|
||||
@@ -453,6 +522,8 @@ void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
|
||||
renderer.PopMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
drawAttachedWeapon(renderer);
|
||||
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
@@ -500,6 +571,12 @@ void Character::drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lig
|
||||
renderer.DrawVertexRenderStruct(modelMutable);
|
||||
|
||||
renderer.PopMatrix();
|
||||
|
||||
renderer.shaderManager.PushShader(defaultShaderName);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
drawAttachedWeapon(renderer);
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
}
|
||||
@@ -553,9 +630,16 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
it->second.gpuSkinningShaderData.RenderVBO(renderer);
|
||||
|
||||
renderer.PopMatrix();
|
||||
|
||||
renderer.shaderManager.PushShader(defaultShaderName);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
drawAttachedWeapon(renderer);
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
|
||||
renderer.PopMatrix();
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
|
||||
Reference in new issue
Block a user