Merging r5975 through r6036 from trunk to ogl-es branch.
GLES drivers adapted, but only did make compile-tests. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6038 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
310
source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp
Normal file
310
source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp
Normal file
@@ -0,0 +1,310 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CSceneNodeAnimatorCollisionResponse.h"
|
||||
#include "ISceneCollisionManager.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CSceneNodeAnimatorCollisionResponse::CSceneNodeAnimatorCollisionResponse(
|
||||
ISceneManager* scenemanager,
|
||||
ITriangleSelector* world, ISceneNode* object,
|
||||
const core::vector3df& ellipsoidRadius,
|
||||
const core::vector3df& gravityPerSecond,
|
||||
const core::vector3df& ellipsoidTranslation,
|
||||
f32 slidingSpeed)
|
||||
: Radius(ellipsoidRadius), Gravity(gravityPerSecond), Translation(ellipsoidTranslation),
|
||||
World(world), Object(object), SceneManager(scenemanager), LastTime(0),
|
||||
SlidingSpeed(slidingSpeed), CollisionNode(0), CollisionCallback(0),
|
||||
Falling(false), IsCamera(false), AnimateCameraTarget(true), CollisionOccurred(false),
|
||||
FirstUpdate(true)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CSceneNodeAnimatorCollisionResponse");
|
||||
#endif
|
||||
|
||||
if (World)
|
||||
World->grab();
|
||||
|
||||
setNode(Object);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CSceneNodeAnimatorCollisionResponse::~CSceneNodeAnimatorCollisionResponse()
|
||||
{
|
||||
if (World)
|
||||
World->drop();
|
||||
|
||||
if (CollisionCallback)
|
||||
CollisionCallback->drop();
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the attached scene node is falling, which means that
|
||||
//! there is no blocking wall from the scene node in the direction of
|
||||
//! the gravity.
|
||||
bool CSceneNodeAnimatorCollisionResponse::isFalling() const
|
||||
{
|
||||
return Falling;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the radius of the ellipsoid with which collision detection and
|
||||
//! response is done.
|
||||
void CSceneNodeAnimatorCollisionResponse::setEllipsoidRadius(
|
||||
const core::vector3df& radius)
|
||||
{
|
||||
Radius = radius;
|
||||
FirstUpdate = true;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the radius of the ellipsoid with which the collision detection and
|
||||
//! response is done.
|
||||
core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidRadius() const
|
||||
{
|
||||
return Radius;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the gravity of the environment.
|
||||
void CSceneNodeAnimatorCollisionResponse::setGravity(const core::vector3df& gravity)
|
||||
{
|
||||
Gravity = gravity;
|
||||
FirstUpdate = true;
|
||||
}
|
||||
|
||||
|
||||
//! Returns current vector of gravity.
|
||||
core::vector3df CSceneNodeAnimatorCollisionResponse::getGravity() const
|
||||
{
|
||||
return Gravity;
|
||||
}
|
||||
|
||||
|
||||
//! 'Jump' the animator, by adding a jump speed opposite to its gravity
|
||||
void CSceneNodeAnimatorCollisionResponse::jump(f32 jumpSpeed)
|
||||
{
|
||||
FallingVelocity -= (core::vector3df(Gravity).normalize()) * jumpSpeed;
|
||||
Falling = true;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the translation of the ellipsoid for collision detection.
|
||||
void CSceneNodeAnimatorCollisionResponse::setEllipsoidTranslation(const core::vector3df &translation)
|
||||
{
|
||||
Translation = translation;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the translation of the ellipsoid for collision detection.
|
||||
core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidTranslation() const
|
||||
{
|
||||
return Translation;
|
||||
}
|
||||
|
||||
|
||||
//! Sets a triangle selector holding all triangles of the world with which
|
||||
//! the scene node may collide.
|
||||
void CSceneNodeAnimatorCollisionResponse::setWorld(ITriangleSelector* newWorld)
|
||||
{
|
||||
if (newWorld)
|
||||
newWorld->grab();
|
||||
|
||||
if (World)
|
||||
World->drop();
|
||||
|
||||
World = newWorld;
|
||||
|
||||
FirstUpdate = true;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the current triangle selector containing all triangles for
|
||||
//! collision detection.
|
||||
ITriangleSelector* CSceneNodeAnimatorCollisionResponse::getWorld() const
|
||||
{
|
||||
return World;
|
||||
}
|
||||
|
||||
|
||||
void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 timeMs)
|
||||
{
|
||||
CollisionOccurred = false;
|
||||
|
||||
if (node != Object)
|
||||
setNode(node);
|
||||
|
||||
if(!Object || !World)
|
||||
return;
|
||||
|
||||
// trigger reset
|
||||
if ( timeMs == 0 )
|
||||
{
|
||||
FirstUpdate = true;
|
||||
timeMs = LastTime;
|
||||
}
|
||||
|
||||
if ( FirstUpdate )
|
||||
{
|
||||
LastPosition = Object->getPosition();
|
||||
Falling = false;
|
||||
LastTime = timeMs;
|
||||
FallingVelocity.set ( 0, 0, 0 );
|
||||
|
||||
FirstUpdate = false;
|
||||
}
|
||||
|
||||
const f32 diffSec = (f32)(timeMs - LastTime)*0.001f;
|
||||
LastTime = timeMs;
|
||||
|
||||
CollisionResultPosition = Object->getPosition();
|
||||
core::vector3df vel = CollisionResultPosition - LastPosition;
|
||||
|
||||
FallingVelocity += Gravity * diffSec;
|
||||
|
||||
CollisionTriangle = RefTriangle;
|
||||
CollisionPoint = core::vector3df();
|
||||
CollisionResultPosition = core::vector3df();
|
||||
CollisionNode = 0;
|
||||
|
||||
// core::vector3df force = vel + FallingVelocity;
|
||||
|
||||
if ( AnimateCameraTarget )
|
||||
{
|
||||
// TODO: divide SlidingSpeed by frame time
|
||||
|
||||
bool f = false;
|
||||
CollisionResultPosition
|
||||
= SceneManager->getSceneCollisionManager()->getCollisionResultPosition(
|
||||
World, LastPosition-Translation,
|
||||
Radius, vel, CollisionTriangle, CollisionPoint, f,
|
||||
CollisionNode, SlidingSpeed, FallingVelocity*diffSec);
|
||||
|
||||
CollisionOccurred = (CollisionTriangle != RefTriangle);
|
||||
|
||||
CollisionResultPosition += Translation;
|
||||
|
||||
if ( diffSec > 0 ) // don't change the state when there was no time
|
||||
{
|
||||
if (f)//CollisionTriangle == RefTriangle)
|
||||
{
|
||||
Falling = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( CollisionOccurred ) // f can also happen to be false when FallingVelocity was already 0 (p.e. at top of a jump)
|
||||
Falling = false;
|
||||
FallingVelocity.set(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool collisionConsumed = false;
|
||||
|
||||
if (CollisionOccurred && CollisionCallback)
|
||||
collisionConsumed = CollisionCallback->onCollision(*this);
|
||||
|
||||
if(!collisionConsumed)
|
||||
Object->setPosition(CollisionResultPosition);
|
||||
}
|
||||
|
||||
// move camera target
|
||||
if (AnimateCameraTarget && IsCamera)
|
||||
{
|
||||
const core::vector3df pdiff = Object->getPosition() - LastPosition - vel;
|
||||
ICameraSceneNode* cam = (ICameraSceneNode*)Object;
|
||||
cam->setTarget(cam->getTarget() + pdiff);
|
||||
}
|
||||
|
||||
LastPosition = Object->getPosition();
|
||||
}
|
||||
|
||||
|
||||
void CSceneNodeAnimatorCollisionResponse::setNode(ISceneNode* node)
|
||||
{
|
||||
Object = node;
|
||||
|
||||
if (Object)
|
||||
{
|
||||
LastPosition = Object->getPosition();
|
||||
IsCamera = (Object->getType() == ESNT_CAMERA);
|
||||
}
|
||||
|
||||
LastTime = os::Timer::getTime();
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the scene node animator.
|
||||
void CSceneNodeAnimatorCollisionResponse::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
ISceneNodeAnimatorCollisionResponse::serializeAttributes(out, options);
|
||||
|
||||
out->addVector3d("Radius", Radius);
|
||||
out->addVector3d("Gravity", Gravity);
|
||||
out->addVector3d("Translation", Translation);
|
||||
out->addBool("AnimateCameraTarget", AnimateCameraTarget);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the scene node animator.
|
||||
void CSceneNodeAnimatorCollisionResponse::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
ISceneNodeAnimatorCollisionResponse::deserializeAttributes(in, options);
|
||||
|
||||
Radius = in->getAttributeAsVector3d("Radius", Radius);
|
||||
Gravity = in->getAttributeAsVector3d("Gravity", Gravity);
|
||||
Translation = in->getAttributeAsVector3d("Translation", Translation);
|
||||
AnimateCameraTarget = in->getAttributeAsBool("AnimateCameraTarget", AnimateCameraTarget);
|
||||
}
|
||||
|
||||
|
||||
ISceneNodeAnimator* CSceneNodeAnimatorCollisionResponse::createClone(ISceneNode* node, ISceneManager* newManager)
|
||||
{
|
||||
if (!newManager) newManager = SceneManager;
|
||||
|
||||
CSceneNodeAnimatorCollisionResponse * newAnimator =
|
||||
new CSceneNodeAnimatorCollisionResponse(newManager, World, Object, Radius,
|
||||
Gravity, Translation, SlidingSpeed);
|
||||
newAnimator->cloneMembers(this);
|
||||
return newAnimator;
|
||||
}
|
||||
|
||||
void CSceneNodeAnimatorCollisionResponse::setCollisionCallback(ICollisionCallback* callback)
|
||||
{
|
||||
if ( CollisionCallback == callback )
|
||||
return;
|
||||
|
||||
if (CollisionCallback)
|
||||
CollisionCallback->drop();
|
||||
|
||||
CollisionCallback = callback;
|
||||
|
||||
if (CollisionCallback)
|
||||
CollisionCallback->grab();
|
||||
}
|
||||
|
||||
//! Should the Target react on collision ( default = true )
|
||||
void CSceneNodeAnimatorCollisionResponse::setAnimateTarget ( bool enable )
|
||||
{
|
||||
AnimateCameraTarget = enable;
|
||||
FirstUpdate = true;
|
||||
}
|
||||
|
||||
//! Should the Target react on collision ( default = true )
|
||||
bool CSceneNodeAnimatorCollisionResponse::getAnimateTarget () const
|
||||
{
|
||||
return AnimateCameraTarget;
|
||||
}
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
Reference in New Issue
Block a user