|
49 | 49 | #include "../mwmechanics/combat.hpp" |
50 | 50 | #include "../mwmechanics/creaturestats.hpp" |
51 | 51 | #include "../mwmechanics/spellcasting.hpp" |
52 | | -#include "../mwmechanics/weapontype.hpp" |
53 | 52 |
|
54 | 53 | #include "../mwrender/animation.hpp" |
55 | 54 | #include "../mwrender/renderingmanager.hpp" |
@@ -152,6 +151,29 @@ namespace |
152 | 151 |
|
153 | 152 | return lightDiffuseColor; |
154 | 153 | } |
| 154 | + |
| 155 | + osg::Quat lookAt(const osg::Vec3f& pos) |
| 156 | + { |
| 157 | + // Rotate the forward vector towards the position (used for gravity-affected projectiles) |
| 158 | + // Can't use Quat::makeRotate as the shortest angle contains undesirable local roll |
| 159 | + const float dist = pos.length(); |
| 160 | + if (dist < 1e-4f) |
| 161 | + return {}; |
| 162 | + |
| 163 | + const osg::Vec3f dir = pos / dist; |
| 164 | + osg::Vec3f right = dir ^ osg::Z_AXIS; |
| 165 | + if (right.normalize() < 1e-4f) |
| 166 | + right = osg::X_AXIS; |
| 167 | + |
| 168 | + const osg::Vec3f up = right ^ dir; |
| 169 | + |
| 170 | + osg::Matrixf mat(right.x(), right.y(), right.z(), 0.f, dir.x(), dir.y(), dir.z(), 0.f, up.x(), up.y(), up.z(), |
| 171 | + 0.f, 0.f, 0.f, 0.f, 1.f); |
| 172 | + |
| 173 | + osg::Quat orient; |
| 174 | + orient.set(mat); |
| 175 | + return orient; |
| 176 | + } |
155 | 177 | } |
156 | 178 |
|
157 | 179 | namespace MWWorld |
@@ -349,8 +371,6 @@ namespace MWWorld |
349 | 371 | state.mIdArrow = projectile.getCellRef().getRefId(); |
350 | 372 | state.mCasterHandle = actor; |
351 | 373 | state.mAttackStrength = attackStrength; |
352 | | - int type = projectile.get<ESM::Weapon>()->mBase->mData.mType; |
353 | | - state.mThrown = MWMechanics::getWeaponType(type)->mWeaponClass == ESM::WeaponType::Thrown; |
354 | 374 |
|
355 | 375 | MWWorld::ManualRef ref(*MWBase::Environment::get().getESMStore(), projectile.getCellRef().getRefId()); |
356 | 376 | MWWorld::Ptr ptr = ref.getPtr(); |
@@ -493,14 +513,7 @@ namespace MWWorld |
493 | 513 |
|
494 | 514 | projectile->setVelocity(projectileState.mVelocity); |
495 | 515 |
|
496 | | - // rotation does not work well for throwing projectiles - their roll angle will depend on shooting |
497 | | - // direction. |
498 | | - if (!projectileState.mThrown) |
499 | | - { |
500 | | - osg::Quat orient; |
501 | | - orient.makeRotate(osg::Vec3f(0, 1, 0), projectileState.mVelocity); |
502 | | - projectileState.mNode->setAttitude(orient); |
503 | | - } |
| 516 | + projectileState.mNode->setAttitude(lookAt(projectileState.mVelocity)); |
504 | 517 |
|
505 | 518 | update(projectileState, duration); |
506 | 519 |
|
@@ -710,8 +723,6 @@ namespace MWWorld |
710 | 723 | MWWorld::ManualRef ref(*MWBase::Environment::get().getESMStore(), esm.mId); |
711 | 724 | MWWorld::Ptr ptr = ref.getPtr(); |
712 | 725 | model = ptr.getClass().getCorrectedModel(ptr); |
713 | | - int weaponType = ptr.get<ESM::Weapon>()->mBase->mData.mType; |
714 | | - state.mThrown = MWMechanics::getWeaponType(weaponType)->mWeaponClass == ESM::WeaponType::Thrown; |
715 | 726 |
|
716 | 727 | state.mProjectileId |
717 | 728 | = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition), model, false); |
|
0 commit comments