Commit 2dc5c7d7 authored by cutealien's avatar cutealien

- Reversed change in vector3d::normalize. The check for 0 vector isn't there...

- Reversed change in vector3d::normalize. The check for 0 vector isn't there for optimization, but to prevent NAN values.
  Works now again as documented and a corresponding test has been added.
  Does fix bug 2770709 (https://sourceforge.net/tracker/?func=detail&aid=2770709&group_id=74339&atid=540676)
- Animations can now be paused by setting the fps to 0.
- Avoid fp-precision problem in getPickedNodeBB (see also 
http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=33838&highlight=). 
  This change might also fix the problem with picking nodes found by aanderse 
(http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=32890&highlight=)



git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2419 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 2391338b
......@@ -13,7 +13,7 @@ namespace core
{
//! 3d vector template class with lots of operators and methods.
/** The vector3d class is used in Irrlicht for three main purposes:
/** The vector3d class is used in Irrlicht for three main purposes:
1) As a direction vector (most of the methods assume this).
2) As a position in 3d space (which is synonymous with a direction vector from the origin to this position).
3) To hold three Euler rotations, where X is pitch, Y is yaw and Z is roll.
......@@ -140,8 +140,11 @@ namespace core
\return Reference to this vector after normalization. */
vector3d<T>& normalize()
{
const f64 length = core::reciprocal_squareroot ( (f64) (X*X + Y*Y + Z*Z) );
f64 length = (f32)(X*X + Y*Y + Z*Z);
if (core::equals(length, 0.0)) // this check isn't an optimization but prevents getting NAN in the sqrt.
return *this;
length = core::reciprocal_squareroot ( (f64) (X*X + Y*Y + Z*Z) );
X = (T)(X * length);
Y = (T)(Y * length);
Z = (T)(Z * length);
......@@ -263,10 +266,10 @@ namespace core
// Where target and seeker are of type ISceneNode*
const vector3df toTarget(target->getAbsolutePosition() - seeker->getAbsolutePosition());
const vector3df requiredRotation = toTarget.getHorizontalAngle();
seeker->setRotation(requiredRotation);
seeker->setRotation(requiredRotation);
\return A rotation vector containing the X (pitch) and Y (raw) rotations (in degrees) that when applied to a
+Z (e.g. 0, 0, 1) direction vector would make it point in the same direction as this vector. The Z (roll) rotation
\return A rotation vector containing the X (pitch) and Y (raw) rotations (in degrees) that when applied to a
+Z (e.g. 0, 0, 1) direction vector would make it point in the same direction as this vector. The Z (roll) rotation
is always 0, since two Euler rotations are sufficient to point in any given direction. */
vector3d<T> getHorizontalAngle() const
{
......@@ -295,9 +298,9 @@ namespace core
/** This vector is assumed to be a rotation vector composed of 3 Euler angle rotations, in degrees.
The implementation performs the same calculations as using a matrix to do the rotation.
\param[in] forwards The direction representing "forwards" which will be rotated by this vector.
\param[in] forwards The direction representing "forwards" which will be rotated by this vector.
If you do not provide a direction, then the +Z axis (0, 0, 1) will be assumed to be forwards.
\return A direction vector calculated by rotating the forwards direction by the 3 Euler angles
\return A direction vector calculated by rotating the forwards direction by the 3 Euler angles
(in degrees) represented by this vector. */
vector3d<T> rotationToDirection(const vector3d<T> & forwards = vector3d<T>(0, 0, 1)) const
{
......
......@@ -107,7 +107,7 @@ void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs)
}
}
if ((StartFrame==EndFrame) || (FramesPerSecond==0.f))
if ((StartFrame==EndFrame))
{
CurrentFrameNr = (f32)StartFrame; //Support for non animated meshes
}
......@@ -210,7 +210,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(bool forceRecalcOfControl
if (JointMode == EJUOR_CONTROL)//write to mesh
skinnedMesh->transferJointsToMesh(JointChildSceneNodes);
else
else
skinnedMesh->animateMesh(getFrameNr(), 1.0f);
// Update the skinned mesh for the current joint transforms.
......@@ -242,12 +242,12 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(bool forceRecalcOfControl
//! OnAnimate() is called just before rendering the whole scene.
void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
{
buildFrameNr(timeMs-LastTimeMs);
buildFrameNr(timeMs-LastTimeMs);
if ( Mesh )
{
scene::IMesh * mesh = getMeshForCurrentFrame( true );
if ( mesh )
Box = mesh->getBoundingBox();
}
......@@ -886,7 +886,7 @@ void CAnimatedMeshSceneNode::updateAbsolutePosition()
SMD3QuaternionTag parent ( MD3Special->Tagname );
if ( Parent && Parent->getType () == ESNT_ANIMATED_MESH)
{
const SMD3QuaternionTag * p = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation
const SMD3QuaternionTag * p = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation
( MD3Special->Tagname );
if ( p )
......
......@@ -149,9 +149,10 @@ void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, core::line3df& ra
core::vector3df intersection;
core::plane3df facePlane;
f32 bestDistToBoxBorder = FLT_MAX;
f32 bestToIntersectionSq = FLT_MAX;
bool gotHit = false;
for(s32 face = 0; face < 6 && !gotHit; ++face)
for(s32 face = 0; face < 6; ++face)
{
facePlane.setPlane(edges[faceEdges[face][0]],
edges[faceEdges[face][1]],
......@@ -170,21 +171,18 @@ void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, core::line3df& ra
if(toIntersectionSq < outbestdistance)
{
// We have to check that the intersection with this plane is actually
// on the box, so need to go back to object space again. We also
// need to move the intersection very slightly closer to the centre of
// the box to take into account fp precision losses, since the intersection
// will axiomatically be on the very edge of the box.
// on the box, so need to go back to object space again.
worldToObject.transformVect(intersection);
intersection *= 0.99f;
if(objectBox.isPointInside(intersection))
{
outbestdistance = toIntersectionSq;
outbestnode = current;
// We can only hit one face, so stop checking now.
gotHit = true;
}
// find the closes point on the box borders. Have to do this as exact checks will fail due to floating point problems.
f32 distToBorder = core::max_ ( core::min_ (core::abs_(objectBox.MinEdge.X-intersection.X), core::abs_(objectBox.MaxEdge.X-intersection.X)),
core::min_ (core::abs_(objectBox.MinEdge.Y-intersection.Y), core::abs_(objectBox.MaxEdge.Y-intersection.Y)),
core::min_ (core::abs_(objectBox.MinEdge.Z-intersection.Z), core::abs_(objectBox.MaxEdge.Z-intersection.Z)) );
if ( distToBorder < bestDistToBoxBorder )
{
bestDistToBoxBorder = distToBorder;
bestToIntersectionSq = toIntersectionSq;
}
}
}
......@@ -194,9 +192,14 @@ void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, core::line3df& ra
++face;
}
// If we got a hit, we can now truncate the ray to stop us hitting further nodes.
if (gotHit)
ray.end = ray.start + (rayVector * sqrtf(outbestdistance));
if ( bestDistToBoxBorder < FLT_MAX )
{
outbestdistance = bestToIntersectionSq;
outbestnode = current;
// If we got a hit, we can now truncate the ray to stop us hitting further nodes.
ray.end = ray.start + (rayVector * sqrtf(outbestdistance));
}
}
}
......
......@@ -8,13 +8,22 @@
using namespace irr;
using namespace core;
// check if the vector contains a NAN (a==b is guaranteed to return false in this case)
template<class T>
static bool is_nan(const core::vector3d<T> &vec )
{
return ( !(vec.X == vec.X)
|| !(vec.Y == vec.Y)
|| !(vec.Z == vec.Z) );
}
template<class T>
static bool compareVectors(const core::vector3d<T> & compare,
const core::vector3d<T> & with)
{
if(compare != with)
{
logTestString("\nERROR: vector3d %.16f, %.16f, %.16f != vector3d %.16f, %.16f, %.16f\n",
logTestString("\nERROR: vector3dOr %.16f, %.16f, %.16f != vector3d %.16f, %.16f, %.16f\n",
(f64)compare.X, (f64)compare.Y, (f64)compare.Z,
(f64)with.X, (f64)with.Y, (f64)with.Z);
assert(compare == with);
......@@ -113,6 +122,11 @@ static bool doTests()
interpolated = vec.getInterpolated_quadratic(otherVec, thirdVec, 1.f);
COMPARE_VECTORS(interpolated, thirdVec); // 1.f means all the 3rd vector
vec.set(0,0,0);
vec.setLength(99);
if ( is_nan(vec) )
return false;
return true;
}
......
Test suite pass at GMT Wed Jun 10 20:04:22 2009
Test suite pass at GMT Thu Jun 11 22:44:22 2009
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment