From e29467e434984b423c132fab8f12f84202be3bcd Mon Sep 17 00:00:00 2001 From: mrzzzrm Date: Tue, 29 Apr 2014 01:16:40 +0200 Subject: [PATCH 1/2] initial --- src/utils/glmext/safenormalize.h | 0 src/utils/glmext/safenormalize.inl | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/utils/glmext/safenormalize.h create mode 100644 src/utils/glmext/safenormalize.inl diff --git a/src/utils/glmext/safenormalize.h b/src/utils/glmext/safenormalize.h new file mode 100644 index 00000000..e69de29b diff --git a/src/utils/glmext/safenormalize.inl b/src/utils/glmext/safenormalize.inl new file mode 100644 index 00000000..dee8bd5f --- /dev/null +++ b/src/utils/glmext/safenormalize.inl @@ -0,0 +1,20 @@ +#pragma once + + +template +class SafeNormalize { +public: + SafeNormalize(const T& vec); + + bool valid() const; + + const T& get(); + + +protected: + bool m_valid; + T m_vec; +}; + + +#include "safenormalize.inl" From 8aa03d1c34a595a9ff96ae85fa134561157c2db7 Mon Sep 17 00:00:00 2001 From: mrzzzrm Date: Tue, 29 Apr 2014 22:55:49 +0200 Subject: [PATCH 2/2] add and integrate safenormalize --- src/ai/basictasks/fighterfighttask.cpp | 4 +- src/ai/boardcomputer.cpp | 14 +++--- src/ai/squad.cpp | 3 +- src/equipment/hardpoint.cpp | 5 +- src/equipment/weapons/gun.cpp | 7 +-- src/equipment/weapons/splitrocket.cpp | 5 +- .../gameplay/input/gameplayfreecaminput.cpp | 10 ++-- .../gameplay/input/gameplaynormalinput.cpp | 17 ++++--- src/physics/impulse.cpp | 4 +- src/player.cpp | 5 +- src/ui/hud/hudelements.cpp | 12 +++-- src/ui/hud/hudget.cpp | 5 +- src/ui/hud/objecthudget.cpp | 7 +-- src/utils/geometryhelper.cpp | 11 +++-- src/utils/geometryhelper.h | 5 -- src/utils/geometryhelper.inl | 16 ------- src/utils/glmext/poweroftwo.cpp | 20 ++++++++ src/utils/glmext/poweroftwo.h | 6 +++ src/utils/glmext/safenormalize.h | 31 ++++++++++++ src/utils/glmext/safenormalize.inl | 48 +++++++++++++++---- src/utils/rand.cpp | 4 +- src/utils/simplewayfind.cpp | 5 +- src/voxeleffect/enginetrailgenerator.cpp | 3 +- src/voxeleffect/voxelexplosiongenerator.cpp | 6 ++- src/world/handler/damageforwarder.cpp | 9 ++-- src/world/handler/elasticimpulsegenerator.cpp | 3 +- src/worldobject/helper/hardpointaimhelper.cpp | 11 +++-- 27 files changed, 189 insertions(+), 87 deletions(-) delete mode 100644 src/utils/geometryhelper.inl create mode 100644 src/utils/glmext/poweroftwo.cpp create mode 100644 src/utils/glmext/poweroftwo.h diff --git a/src/ai/basictasks/fighterfighttask.cpp b/src/ai/basictasks/fighterfighttask.cpp index 323bfde9..0a76ffe9 100644 --- a/src/ai/basictasks/fighterfighttask.cpp +++ b/src/ai/basictasks/fighterfighttask.cpp @@ -2,6 +2,7 @@ #include "ai/boardcomputer.h" #include "utils/geometryhelper.h" +#include "utils/glmext/safenormalize.h" #include "utils/randfloat.h" #include "voxel/voxelclusterbounds.h" #include "worldobject/ship.h" @@ -134,7 +135,8 @@ void FighterFightTask::setState(State newState) { float FighterFightTask::angleToTarget() { WorldObject* worldObject = boardComputer()->worldObject(); glm::vec3 shipDirection = glm::vec3(0, 0, -1); - glm::vec3 targetDirection = glm::inverse(worldObject->transform().orientation()) * glm::normalize(m_primaryTarget->transform().position() - worldObject->transform().position()); + glm::vec3 targetDirection = glm::inverse(worldObject->transform().orientation()) * safeNormalize(m_primaryTarget->transform().position() - worldObject->transform().position()); float angle = GeometryHelper::angleBetween(shipDirection, targetDirection); return glm::degrees(angle); } + diff --git a/src/ai/boardcomputer.cpp b/src/ai/boardcomputer.cpp index b4cfe924..11c25da4 100644 --- a/src/ai/boardcomputer.cpp +++ b/src/ai/boardcomputer.cpp @@ -6,8 +6,10 @@ #include "collision/collisionfilter.h" +#include "utils/glmext/safenormalize.h" #include "utils/randvec3.h" #include "utils/geometryhelper.h" + #include "physics/physics.h" #include "worldobject/ship.h" @@ -47,13 +49,13 @@ void BoardComputer::moveTo(const glm::vec3& position, bool decelerate) { // the projection is already past the target, but we don't want to deaccelerate // instead, project the target from our current position to a sphere around our position float projectionDistance = glm::length(projectedPosition - currentPosition); - glm::vec3 fakePosition = currentPosition + glm::normalize(position - currentPosition) * 1.5f * projectionDistance; + glm::vec3 fakePosition = currentPosition + safeNormalize(position - currentPosition) * 1.5f * projectionDistance; delta = fakePosition - projectedPosition; } } - glm::vec3 direction = glm::inverse(m_worldObject->transform().orientation()) * glm::normalize(delta); + glm::vec3 direction = glm::inverse(m_worldObject->transform().orientation()) * safeNormalize(delta); m_engineState.setDirectional(direction); } @@ -71,7 +73,7 @@ void BoardComputer::rotateTo(const glm::vec3& position, const glm::vec3& up) { if (position == m_worldObject->transform().position()) { return; } - glm::vec3 targetDirection = glm::inverse(m_worldObject->transform().orientation()) * glm::normalize(position - m_worldObject->transform().position()); + glm::vec3 targetDirection = glm::inverse(m_worldObject->transform().orientation()) * safeNormalize(position - m_worldObject->transform().position()); // The rotation that needs to be performed, in the local coordinate-sys glm::quat rotation = GeometryHelper::quatFromTo(projectedDirection, targetDirection); @@ -96,12 +98,12 @@ void BoardComputer::rotateTo(const glm::vec3& position, const glm::vec3& up) { glm::vec3 BoardComputer::rotateUpTo(const glm::vec3& up) { glm::vec3 upDirection = glm::vec3(0, 1, 0); - glm::vec3 newUpDirection = glm::inverse(m_worldObject->transform().orientation()) * glm::normalize(up); + glm::vec3 newUpDirection = glm::inverse(m_worldObject->transform().orientation()) * safeNormalize(up, glm::vec3(0, 1, 0)); glm::quat upRotation = GeometryHelper::quatFromTo(upDirection, newUpDirection); if (glm::abs(glm::angle(upRotation)) > s_minActAngle) { glm::vec3 euler = glm::eulerAngles(upRotation); - return (glm::normalize(euler) * 0.5f); + return (safeNormalize(euler) * 0.5f); } return glm::vec3(0.0f); @@ -115,7 +117,7 @@ glm::vec3 BoardComputer::rotateUpAuto(const glm::quat& rotation) { glm::quat upRotation = GeometryHelper::quatFromTo(upDirection, newUpDirection); glm::vec3 euler = glm::eulerAngles(upRotation); - return (glm::normalize(euler) * 0.5f); + return (safeNormalize(euler) * 0.5f); } return glm::vec3(0.0f); diff --git a/src/ai/squad.cpp b/src/ai/squad.cpp index c40d77b0..741c00fc 100644 --- a/src/ai/squad.cpp +++ b/src/ai/squad.cpp @@ -2,6 +2,7 @@ #include "worldobject/ship.h" #include "ai/aigrouptask.h" +#include "utils/glmext/safenormalize.h" #include "physics/physics.h" #include "voxel/voxelclusterbounds.h" @@ -120,5 +121,5 @@ glm::vec3 Squad::calculateFormationPosition(Ship* member, int position) { } distance += member->bounds().sphere().radius() + 10; glm::vec3 direction = (position % 2) ? glm::vec3(1, 0, 1) : glm::vec3(-1, 0, 1); - return m_leader->transform().position() + m_leader->physics().speed().directional() + m_leader->transform().orientation() * (distance * glm::normalize(direction)); + return m_leader->transform().position() + m_leader->physics().speed().directional() + m_leader->transform().orientation() * (distance * safeNormalize(direction)); } diff --git a/src/equipment/hardpoint.cpp b/src/equipment/hardpoint.cpp index 59e96714..428a0be9 100644 --- a/src/equipment/hardpoint.cpp +++ b/src/equipment/hardpoint.cpp @@ -1,5 +1,6 @@ #include "hardpoint.h" +#include "utils/glmext/safenormalize.h" #include "utils/geometryhelper.h" #include "voxel/specialvoxels/hardpointvoxel.h" @@ -37,8 +38,8 @@ const glm::vec3& Hardpoint::direction() const { } void Hardpoint::setDirection(const glm::vec3& direction) { - assert(glm::length(direction) > 0); - m_direction = glm::normalize(direction); + assert(normalizeable(direction)); + m_direction = safeNormalize(direction); } float Hardpoint::fieldOfAim() const { diff --git a/src/equipment/weapons/gun.cpp b/src/equipment/weapons/gun.cpp index 991e74db..f318f05f 100644 --- a/src/equipment/weapons/gun.cpp +++ b/src/equipment/weapons/gun.cpp @@ -1,6 +1,7 @@ #include "gun.h" #include "utils/geometryhelper.h" +#include "utils/glmext/safenormalize.h" #include "bullet.h" @@ -66,15 +67,15 @@ void Gun::setupBullet(Bullet* bullet, const glm::vec3& point) { WorldObject* firingWorldObject = m_hardpoint->components()->worldObject(); glm::quat worldObjectOrientation = firingWorldObject->transform().orientation(); - glm::vec3 bulletDirection = glm::normalize(point - m_hardpoint->voxel()->position()); + glm::vec3 bulletDirection = safeNormalize(point - m_hardpoint->voxel()->position(), glm::vec3(0, 0, -1)); glm::vec3 hardpointDirection = worldObjectOrientation * glm::vec3(0, 0, -1); glm::vec3 bulletUp = glm::cross(bulletDirection, hardpointDirection); //bulletTransform.setOrientation(Math::quatFromDir(bulletDirection)); bulletTransform.setOrientation(m_hardpoint->components()->worldObject()->transform().orientation()); - if (bulletUp != glm::vec3(0)) { - glm::vec3 rotationAxis = glm::normalize(bulletUp); + if (normalizeable(bulletUp)) { + glm::vec3 rotationAxis = safeNormalize(bulletUp); float angle = GeometryHelper::angleBetween(bulletDirection, hardpointDirection); glm::quat bulletOrientation = glm::angleAxis(-angle, rotationAxis); bulletTransform.rotateWorld(bulletOrientation); //then rotate towards target diff --git a/src/equipment/weapons/splitrocket.cpp b/src/equipment/weapons/splitrocket.cpp index feb5a6e6..64a8e05e 100644 --- a/src/equipment/weapons/splitrocket.cpp +++ b/src/equipment/weapons/splitrocket.cpp @@ -11,6 +11,7 @@ #include "resource/worldobjectbuilder.h" #include "utils/geometryhelper.h" +#include "utils/glmext/safenormalize.h" #include "utils/randfloatpool.h" #include "voxeleffect/voxelexplosiongenerator.h" @@ -155,8 +156,8 @@ void SplitRocket::setChildSpeed(WorldObject* child, const glm::quat& launchOrien speed.setDirectional(launchOrientation * glm::vec3(0, 0, -1) * glm::length(speed.directional())); - if (glm::length(speed.directional()) > 0.0f) { - glm::vec3 boostDirection = glm::normalize(speed.directional()); + if (normalizeable(speed.directional())) { + glm::vec3 boostDirection = safeNormalize(speed.directional()); glm::vec3 boost = boostDirection * RandFloatPool::randomize(m_childrenSpeedBoost, m_childrenSpeedBoostRandomization); speed.setDirectional(speed.directional() + boost); } diff --git a/src/gamestate/gameplay/input/gameplayfreecaminput.cpp b/src/gamestate/gameplay/input/gameplayfreecaminput.cpp index 940e061b..8bc29032 100644 --- a/src/gamestate/gameplay/input/gameplayfreecaminput.cpp +++ b/src/gamestate/gameplay/input/gameplayfreecaminput.cpp @@ -13,6 +13,8 @@ #include "input/inputmapping.h" +#include "utils/glmext/safenormalize.h" + GamePlayFreecamInput::GamePlayFreecamInput() : GamePlayInput(), @@ -84,11 +86,11 @@ void GamePlayFreecamInput::applyUpdates() { // some actions can be triggered in different ways or multiple times // especially those done by the mouse // collect them and apply them here - + if (glm::length(m_moveUpdate) > 1.0f) { - m_moveUpdate = glm::normalize(m_moveUpdate); + m_moveUpdate = safeNormalize(m_moveUpdate); } - + m_position += m_orientation * (m_moveUpdate * prop_moveFactor.get()); m_moveUpdate = glm::vec3(0); @@ -246,4 +248,4 @@ void GamePlayFreecamInput::setOrientation(const glm::quat& orientation) { CameraHead& GamePlayFreecamInput::cameraHead() { return m_cameraDolly->cameraHead(); -} \ No newline at end of file +} diff --git a/src/gamestate/gameplay/input/gameplaynormalinput.cpp b/src/gamestate/gameplay/input/gameplaynormalinput.cpp index 7b3778a3..ee25f427 100644 --- a/src/gamestate/gameplay/input/gameplaynormalinput.cpp +++ b/src/gamestate/gameplay/input/gameplaynormalinput.cpp @@ -20,6 +20,13 @@ #include "input/inputmapping.h" #include "input/inputconfigurator.h" +#include "ui/hud/hud.h" +#include "ui/targetselector.h" +#include "ui/hud/crosshair.h" + +#include "utils/glmext/safenormalize.h" + + #include "world/world.h" #include "worldobject/worldobject.h" #include "worldobject/worldobjectcomponents.h" @@ -27,10 +34,6 @@ #include "player.h" -#include "ui/hud/hud.h" -#include "ui/targetselector.h" -#include "ui/hud/crosshair.h" - /* @@ -182,13 +185,13 @@ void GamePlayNormalInput::applyUpdates() { m_rocketUpdate = false; if (glm::length(m_moveUpdate) > 1.0f) { - m_moveUpdate = glm::normalize(m_moveUpdate); + m_moveUpdate = safeNormalize(m_moveUpdate); } World::instance()->player().move(m_moveUpdate); m_moveUpdate = glm::vec3(0); if (glm::length(m_rotateUpdate) > 1.0f) { - m_rotateUpdate = glm::normalize(m_rotateUpdate); + m_rotateUpdate = safeNormalize(m_rotateUpdate); } World::instance()->player().rotate(m_rotateUpdate); m_rotateUpdate = glm::vec3(0); @@ -378,4 +381,4 @@ void GamePlayNormalInput::placeCrossHair(double winX, double winY) { int width, height; glfwGetWindowSize(glfwGetCurrentContext(), &width, &height); World::instance()->player().hud().setCrossHairOffset(glm::vec2((winX - (width/2))/(width/2), -(winY - (height/2))/(height/2))); -} \ No newline at end of file +} diff --git a/src/physics/impulse.cpp b/src/physics/impulse.cpp index cc4c7d07..7e9f564d 100644 --- a/src/physics/impulse.cpp +++ b/src/physics/impulse.cpp @@ -2,13 +2,15 @@ #include +#include "utils/glmext/safenormalize.h" + Impulse::Impulse(WorldObject* worldObject, Voxel* voxel, const glm::vec3& speed, float mass, const glm::vec3& normal): m_worldObject(worldObject), m_voxel(voxel), m_speed(speed), m_mass(mass), - m_normal(glm::normalize(normal)) + m_normal(safeNormalize(normal)) { assert(m_voxel); } diff --git a/src/player.cpp b/src/player.cpp index 9a24fb05..d3c2f2fb 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -15,6 +15,8 @@ #include "ui/hud/aimhelperhudget.h" #include "ui/hud/crosshair.h" +#include "utils/glmext/safenormalize.h" + #include "worldobject/worldobjectinfo.h" #include "utils/aimer.h" @@ -69,6 +71,7 @@ CameraHead& Player::cameraHead() { HUD& Player::hud() { return *m_hud; } +#include "utils/glmext/safenormalize.h" void Player::fire() { if (ship()) { @@ -77,7 +80,7 @@ void Player::fire() { if(m_hud->aimHelper().hovered()) { targetPoint = m_hud->aimHelper().targetPoint(); } else { - glm::vec3 shootDirection(glm::normalize(m_hud->crossHair().worldPosition() - cameraHead().position())); + glm::vec3 shootDirection(safeNormalize(m_hud->crossHair().worldPosition() - cameraHead().position())); Ray ray(m_hud->crossHair().worldPosition(), shootDirection); targetPoint = m_aimer->aim(ray); } diff --git a/src/ui/hud/hudelements.cpp b/src/ui/hud/hudelements.cpp index 9f90cbb1..21017e89 100644 --- a/src/ui/hud/hudelements.cpp +++ b/src/ui/hud/hudelements.cpp @@ -1,5 +1,7 @@ #include "hudelements.h" +#include "utils/glmext/safenormalize.h" + #include "voxel/voxelrenderer.h" #include "hud.h" @@ -11,13 +13,13 @@ HUDElements::HUDElements(HUD& hud): m_hud(hud), - m_targetName(new TextFieldHudget(&m_hud, glm::normalize(glm::vec3(0, -1.1f, -2)), 0.025f, "")), - m_speedLabel(new TextFieldHudget(&m_hud, glm::normalize(glm::vec3(1.5f, -1.1f, -2)), 0.020f, "")), - m_missionTitle(new TextFieldHudget(&m_hud, glm::normalize(glm::vec3(0.0f, 1.0f, -2)), 0.020f, "")), + m_targetName(new TextFieldHudget(&m_hud, safeNormalize(glm::vec3(0, -1.1f, -2)), 0.025f, "")), + m_speedLabel(new TextFieldHudget(&m_hud, safeNormalize(glm::vec3(1.5f, -1.1f, -2)), 0.020f, "")), + m_missionTitle(new TextFieldHudget(&m_hud, safeNormalize(glm::vec3(0.0f, 1.0f, -2)), 0.020f, "")), m_missionTitleHider(new HudgetHideAnimation(*m_missionTitle)), - m_missionCaption(new TextFieldHudget(&m_hud, glm::normalize(glm::vec3(0.0f, 0.8f, -2)), 0.010f, "")), + m_missionCaption(new TextFieldHudget(&m_hud, safeNormalize(glm::vec3(0.0f, 0.8f, -2)), 0.010f, "")), m_missionCaptionHider(new HudgetHideAnimation(*m_missionCaption)), - m_missionMessage(new TextFieldHudget(&m_hud, glm::normalize(glm::vec3(-0.9f, -0.9f, -2)), 0.010f, "")), + m_missionMessage(new TextFieldHudget(&m_hud, safeNormalize(glm::vec3(-0.9f, -0.9f, -2)), 0.010f, "")), m_missionMessageHider(new HudgetHideAnimation(*m_missionMessage)) { addHudget(m_targetName); diff --git a/src/ui/hud/hudget.cpp b/src/ui/hud/hudget.cpp index 42f86bc7..42970659 100644 --- a/src/ui/hud/hudget.cpp +++ b/src/ui/hud/hudget.cpp @@ -1,6 +1,7 @@ #include "hudget.h" #include "utils/geometryhelper.h" +#include "utils/glmext/safenormalize.h" #include "hud.h" @@ -84,11 +85,11 @@ void Hudget::setRelativeDistance(float relativeDistance) { } void Hudget::pointToWorldPoint(const glm::vec3& worldPoint) { - m_direction = glm::normalize(glm::inverse(m_hud->orientation()) * (worldPoint - m_hud->position())); + m_direction = safeNormalize(glm::inverse(m_hud->orientation()) * (worldPoint - m_hud->position())); } void Hudget::pointToLocalPoint(const glm::vec3& localPoint) { - m_direction = glm::normalize(localPoint); + m_direction = safeNormalize(localPoint); } glm::vec3 Hudget::localDirection() const { diff --git a/src/ui/hud/objecthudget.cpp b/src/ui/hud/objecthudget.cpp index 662b183d..c89690dd 100644 --- a/src/ui/hud/objecthudget.cpp +++ b/src/ui/hud/objecthudget.cpp @@ -10,10 +10,11 @@ #include "factions/factionmatrix.h" #include "utils/geometryhelper.h" -#include "worldobject/worldobjectinfo.h" +#include "utils/glmext/safenormalize.h" #include "world/world.h" +#include "worldobject/worldobjectinfo.h" #include "worldobject/worldobject.h" #include "worldobject/ship.h" @@ -133,9 +134,9 @@ glm::vec3 ObjectHudget::closestPointInsideFov() { glm::vec3 pointInsideFov; if (angleX < angleY) { - pointInsideFov = glm::normalize(intersectionX); + pointInsideFov = safeNormalize(intersectionX); } else { - pointInsideFov = glm::normalize(intersectionY); + pointInsideFov = safeNormalize(intersectionY); } pointInsideFov.x = glm::abs(pointInsideFov.x); pointInsideFov.y = glm::abs(pointInsideFov.y); diff --git a/src/utils/geometryhelper.cpp b/src/utils/geometryhelper.cpp index 36e74aa7..c59611a0 100644 --- a/src/utils/geometryhelper.cpp +++ b/src/utils/geometryhelper.cpp @@ -1,8 +1,11 @@ #include "geometryhelper.h" -#include "randvec3.h" #include "geometry/ray.h" +#include "utils/glmext/safenormalize.h" + +#include "randvec3.h" + bool GeometryHelper::intersectRectangle(const Ray* ray, const glm::vec3& p, const glm::vec3& q, const glm::vec3& r, const glm::vec3& s) { glm::vec3 intersectionDummy; @@ -27,7 +30,7 @@ glm::vec3 GeometryHelper::plane(const glm::vec3& p, const glm::vec3& q, const gl } float GeometryHelper::angleBetween(const glm::vec3& u, const glm::vec3& v) { - float angle = glm::acos(glm::clamp(glm::dot(glm::normalize(u), glm::normalize(v)), -1.0f, 1.0f)); + float angle = glm::acos(glm::clamp(glm::dot(safeNormalize(u), safeNormalize(v)), -1.0f, 1.0f)); assert(std::isfinite(angle)); return angle; } @@ -44,7 +47,7 @@ glm::quat GeometryHelper::quatFromTo(const glm::vec3& u, const glm::vec3& v) { if (w == glm::vec3(0)) { w = RandVec3::randUnitVec(); } - return glm::angleAxis(angle, glm::normalize(w)); + return glm::angleAxis(angle, safeNormalize(w)); } glm::quat GeometryHelper::quatFromViewDirection(const glm::vec3& direction) { @@ -57,5 +60,5 @@ glm::quat GeometryHelper::quatFromViewDirection(const glm::vec3& direction) { w = RandVec3::randUnitVec(); } - return glm::angleAxis(angle, glm::normalize(w)); + return glm::angleAxis(angle, safeNormalize(w)); } diff --git a/src/utils/geometryhelper.h b/src/utils/geometryhelper.h index 9bd36cc7..f0a4c5de 100644 --- a/src/utils/geometryhelper.h +++ b/src/utils/geometryhelper.h @@ -25,10 +25,5 @@ class GeometryHelper { // Returns the quaternion from (0,0,-1) to dir static glm::quat quatFromViewDirection(const glm::vec3& dir); - - // Normalize, and return value again if glm::length(value) is 0 - template - static T safeNormalize(const T& value); }; -#include "geometryhelper.inl" diff --git a/src/utils/geometryhelper.inl b/src/utils/geometryhelper.inl deleted file mode 100644 index 7ad9926c..00000000 --- a/src/utils/geometryhelper.inl +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -template -T GeometryHelper::safeNormalize(const T& value) { - // GLM_STATIC_ASSERT(glm::detail::type::is_vector, "'safeNormalize' only accept float vectors"); - // GLM_STATIC_ASSERT(glm::detail::type::is_float, "'safeNormalize' only accepts float vectors"); - - if (glm::length(value) == 0.0f) { - return value; - } else { - return glm::normalize(value); - } -} - diff --git a/src/utils/glmext/poweroftwo.cpp b/src/utils/glmext/poweroftwo.cpp new file mode 100644 index 00000000..b7c1f6b9 --- /dev/null +++ b/src/utils/glmext/poweroftwo.cpp @@ -0,0 +1,20 @@ +#include "poweroftwo.h" + +#include + + +template<> +float powerOfTwo(const glm::vec2& v) { + return v.x * v.x + v.y * v.y; +} + +template<> +float powerOfTwo(const glm::vec3& v) { + return v.x * v.x + v.y * v.y + v.z * v.z; +} + +template<> +float powerOfTwo(const glm::vec4& v) { + return v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w; +} + diff --git a/src/utils/glmext/poweroftwo.h b/src/utils/glmext/poweroftwo.h new file mode 100644 index 00000000..de5b71be --- /dev/null +++ b/src/utils/glmext/poweroftwo.h @@ -0,0 +1,6 @@ +#pragma once + +template +float powerOfTwo(const T& v); + + diff --git a/src/utils/glmext/safenormalize.h b/src/utils/glmext/safenormalize.h index e69de29b..e686e434 100644 --- a/src/utils/glmext/safenormalize.h +++ b/src/utils/glmext/safenormalize.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include + + +template +class SafeNormalize { +public: + SafeNormalize(const T& v, const T& fallback = T(0.0f)); + + const T& get() const; + operator T() const; + + bool valid(); + + +protected: + bool m_valid; + T m_normalized; +}; + +template +T safeNormalize(const T& v, const T& fallback = T(0.0f)); + +template +bool normalizeable(const T& v); + + +#include "safenormalize.inl" diff --git a/src/utils/glmext/safenormalize.inl b/src/utils/glmext/safenormalize.inl index dee8bd5f..9d2e8a20 100644 --- a/src/utils/glmext/safenormalize.inl +++ b/src/utils/glmext/safenormalize.inl @@ -1,20 +1,48 @@ #pragma once +#include + +#include + +#include "poweroftwo.h" + template -class SafeNormalize { -public: - SafeNormalize(const T& vec); +SafeNormalize::SafeNormalize(const T& v, const T& fallback) { + float sqr = powerOfTwo(v); + + m_valid = sqr > 0.0f; + + if (m_valid) { + m_normalized = v * glm::inversesqrt(sqr); + } else { + glow::debug() << "SafeNormalize catched a illegal normalize()"; + m_normalized = fallback; + } +} - bool valid() const; +template +const T& SafeNormalize::get() const { + return m_normalized; +} - const T& get(); +template +SafeNormalize::operator T() const { + return m_normalized; +} +template +bool SafeNormalize::valid() { + return m_valid; +} -protected: - bool m_valid; - T m_vec; -}; +template +T safeNormalize(const T& v, const T& fallback) { + return SafeNormalize(v, fallback); +} +template +bool normalizeable(const T& v) { + return powerOfTwo(v) > 0.0f; +} -#include "safenormalize.inl" diff --git a/src/utils/rand.cpp b/src/utils/rand.cpp index 9f5620b8..58b6bdbe 100644 --- a/src/utils/rand.cpp +++ b/src/utils/rand.cpp @@ -7,6 +7,8 @@ #include #include +#include "utils/glmext/safenormalize.h" + bool RandBool::rand(float trueProbability) { assert(trueProbability >= 0.0f && trueProbability <= 1.0f); @@ -35,6 +37,6 @@ glm::vec3 RandVec3::randUnitVec() { float angX = RandFloat::rand(-glm::pi(), glm::pi()); float angY = glm::acos(RandFloat::rand(-1.0f, 1.0f)); glm::vec3 result = glm::quat(glm::vec3(angX, angY, 0.0f)) * glm::vec3(0.0f, 0.0f, 1.0f); - return glm::normalize(result); + return safeNormalize(result); } diff --git a/src/utils/simplewayfind.cpp b/src/utils/simplewayfind.cpp index 29a5c1ad..6aab8497 100644 --- a/src/utils/simplewayfind.cpp +++ b/src/utils/simplewayfind.cpp @@ -4,6 +4,7 @@ #include "geometry/capsule.h" #include "worldtree/worldtreequery.h" #include "worldobject/worldobject.h" +#include "utils/glmext/safenormalize.h" #include "utils/worldobjectgeometryhelper.h" #include "collision/collisionfilter.h" #include "collision/collisiondetector.h" @@ -38,8 +39,8 @@ glm::vec3 SimpleWayfind::calculateEvasionDirectionFor(WorldObject& self, WorldOb float dotP = glm::dot(toTarget, toObject); float cosAlpha = dotP / (glm::length(toTarget) * glm::length(toObject)); - glm::vec3 crossPoint = self.transform().position() + (glm::normalize(toTarget) * cosAlpha * glm::length(toObject)); - return glm::normalize(crossPoint - obstacle.transform().position()); + glm::vec3 crossPoint = self.transform().position() + (safeNormalize(toTarget) * cosAlpha * glm::length(toObject)); + return safeNormalize(crossPoint - obstacle.transform().position()); } glm::vec3 SimpleWayfind::calculateEvasionPointFor(WorldObject& self, WorldObject& obstacle, const glm::vec3& targetPoint) { diff --git a/src/voxeleffect/enginetrailgenerator.cpp b/src/voxeleffect/enginetrailgenerator.cpp index 197d5910..b35146e7 100644 --- a/src/voxeleffect/enginetrailgenerator.cpp +++ b/src/voxeleffect/enginetrailgenerator.cpp @@ -1,6 +1,7 @@ #include "enginetrailgenerator.h" #include "utils/tostring.h" +#include "utils/glmext/safenormalize.h" #include "utils/geometryhelper.h" #include "voxel/specialvoxels/engineslotvoxel.h" @@ -68,7 +69,7 @@ void EngineTrailGenerator::spawnTrail() { glm::vec3 newPosition = calculateSpawnPosition(); glm::vec3 distance = newPosition - m_lastSpawnPoint; - glm::vec3 step = GeometryHelper::safeNormalize(distance) * prop_stepDistance.get(); + glm::vec3 step = safeNormalize(distance) * prop_stepDistance.get(); glm::vec3 currentPosition = m_lastSpawnPoint; float stepCount = glm::length(distance) / prop_stepDistance; diff --git a/src/voxeleffect/voxelexplosiongenerator.cpp b/src/voxeleffect/voxelexplosiongenerator.cpp index c32910d3..393e9890 100644 --- a/src/voxeleffect/voxelexplosiongenerator.cpp +++ b/src/voxeleffect/voxelexplosiongenerator.cpp @@ -2,7 +2,7 @@ #include -#include "world/world.h" +#include "utils/glmext/safenormalize.h" #include "utils/randfloat.h" #include "utils/randfloatpool.h" #include "utils/randvec3.h" @@ -11,6 +11,8 @@ #include "voxelparticlesetup.h" #include "voxelparticleengine.h" +#include "world/world.h" + VoxelExplosionGenerator::VoxelExplosionGenerator(const VoxelCluster* creator) : VoxelParticleSpawnBase(creator, @@ -41,7 +43,7 @@ void VoxelExplosionGenerator::spawn() { glm::vec3 directionalSpeed = createDirectionalSpeed(); transform.setScale(createScale()); - transform.setPosition(m_position + (m_radius * glm::normalize(directionalSpeed))); + transform.setPosition(m_position + (m_radius * safeNormalize(directionalSpeed))); Visuals visuals(m_color, m_emissiveness); Speed speed(directionalSpeed, createAngularSpeed()); diff --git a/src/world/handler/damageforwarder.cpp b/src/world/handler/damageforwarder.cpp index 74e949b7..e3258950 100644 --- a/src/world/handler/damageforwarder.cpp +++ b/src/world/handler/damageforwarder.cpp @@ -8,6 +8,7 @@ #include "voxel/voxeltreenode.h" #include "voxel/voxelneighbourhelper.h" +#include "utils/glmext/safenormalize.h" #include "utils/tostring.h" #include "worldobject/worldobject.h" @@ -26,7 +27,7 @@ void DamageForwarder::forwardDamageImpacts(std::list &dampedDeadly const std::vector& neighbours = nHelper.neighbours(deadVoxel); for(Voxel *neighbour : neighbours) { - glm::vec3 voxelVec = glm::normalize(static_cast(neighbour->gridCell() - deadVoxel->gridCell())); + glm::vec3 voxelVec = safeNormalize(static_cast(neighbour->gridCell() - deadVoxel->gridCell())); glm::vec3 damageImpactVec = glm::normalize(glm::inverse(m_currentWorldObject->transform().orientation()) * dampedDeadlyDamageImpact.damageVec()); float distanceFactor = 1.0f; @@ -39,9 +40,9 @@ void DamageForwarder::forwardDamageImpacts(std::list &dampedDeadly glm::vec3 forwardedDamage = dampedDeadlyDamageImpact.damageVec() * forwardFactor(dotProduct, dampedDeadlyDamageImpact.fieldOfDamage(), neighbours.size()); glm::vec3 createdDamage = voxelVec * deadVoxel->damageForwardingDestructionDamage(); - DamageImpact forwarded(m_currentWorldObject, - neighbour, - distanceFactor * (forwardedDamage + createdDamage), + DamageImpact forwarded(m_currentWorldObject, + neighbour, + distanceFactor * (forwardedDamage + createdDamage), dampedDeadlyDamageImpact.fieldOfDamage()); m_damageImpactAccumulator.parse(forwarded); } diff --git a/src/world/handler/elasticimpulsegenerator.cpp b/src/world/handler/elasticimpulsegenerator.cpp index eea56bf3..663eb698 100644 --- a/src/world/handler/elasticimpulsegenerator.cpp +++ b/src/world/handler/elasticimpulsegenerator.cpp @@ -4,6 +4,7 @@ #include "worldobject/worldobject.h" +#include "utils/glmext/safenormalize.h" #include "utils/tostring.h" #include "collision/voxelcollision.h" #include "voxel/voxel.h" @@ -40,7 +41,7 @@ void ElasticImpulseGenerator::generateImpulse(VoxelCollisionParticipant &from, V glm::vec3(from.voxel()->gridCell())) - from.worldObject()->transform().applyTo(glm::vec3(from.voxel()->gridCell())); - glm::vec3 normal = glm::normalize( + glm::vec3 normal = safeNormalize( to.worldObject()->transform().applyTo(glm::vec3(to.voxel()->gridCell())) - from.worldObject()->transform().applyTo(glm::vec3(from.voxel()->gridCell()))); diff --git a/src/worldobject/helper/hardpointaimhelper.cpp b/src/worldobject/helper/hardpointaimhelper.cpp index 0176f18b..4dbf05fa 100644 --- a/src/worldobject/helper/hardpointaimhelper.cpp +++ b/src/worldobject/helper/hardpointaimhelper.cpp @@ -1,13 +1,18 @@ #include "hardpointaimhelper.h" -#include "voxel/specialvoxels/hardpointvoxel.h" #include "equipment/weapon.h" #include "equipment/hardpoint.h" #include "equipment/weapons/gun.h" -#include "worldobject/worldobject.h" + #include "physics/physics.h" +#include "utils/glmext/safenormalize.h" + +#include "voxel/specialvoxels/hardpointvoxel.h" + +#include "worldobject/worldobject.h" + HardpointAimHelper::HardpointAimHelper(Hardpoint* hardpoint, WorldObject* targetObject): m_hardpoint(hardpoint), @@ -53,7 +58,7 @@ void HardpointAimHelper::aim() { } while(offset > 0.1f); m_hitable = true; - m_direction = glm::normalize(m_point - m_hardpointPosition); + m_direction = safeNormalize(m_point - m_hardpointPosition); m_aimed = true; }