238 lines
5.6 KiB
C++
238 lines
5.6 KiB
C++
// Copyright (C) 2002-2008 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 / 1000.0f), Translation(ellipsoidTranslation),
|
|
World(world), Object(object), SceneManager(scenemanager),
|
|
SlidingSpeed(slidingSpeed), Falling(false), IsCamera(false), AnimateCameraTarget(true)
|
|
{
|
|
|
|
#ifdef _DEBUG
|
|
setDebugName("CSceneNodeAnimatorCollisionResponse");
|
|
#endif
|
|
|
|
if (World)
|
|
World->grab();
|
|
|
|
setNode(Object);
|
|
}
|
|
|
|
|
|
|
|
//! destructor
|
|
CSceneNodeAnimatorCollisionResponse::~CSceneNodeAnimatorCollisionResponse()
|
|
{
|
|
if (World)
|
|
World->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
|
|
{
|
|
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
|
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;
|
|
}
|
|
|
|
//! Returns the radius of the ellipsoid with wich 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;
|
|
}
|
|
|
|
|
|
//! Returns current vector of gravity.
|
|
core::vector3df CSceneNodeAnimatorCollisionResponse::getGravity() const
|
|
{
|
|
return Gravity;
|
|
}
|
|
|
|
|
|
//! 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)
|
|
{
|
|
Falling = false;
|
|
|
|
LastTime = os::Timer::getTime();
|
|
FallStartTime = LastTime;
|
|
|
|
|
|
if (World)
|
|
World->drop();
|
|
|
|
World = newWorld;
|
|
if (World)
|
|
World->grab();
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Returns the current triangle selector containing all triangles for
|
|
//! collision detection.
|
|
ITriangleSelector* CSceneNodeAnimatorCollisionResponse::getWorld() const
|
|
{
|
|
return World;
|
|
}
|
|
|
|
|
|
|
|
void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 timeMs)
|
|
{
|
|
if (node != Object)
|
|
{
|
|
setNode(node);
|
|
return;
|
|
}
|
|
|
|
if (!World)
|
|
return;
|
|
|
|
u32 diff = timeMs - LastTime;
|
|
LastTime = timeMs;
|
|
|
|
core::vector3df pos = Object->getPosition();
|
|
core::vector3df vel = pos - LastPosition;
|
|
|
|
//g = Gravity * (f32)((timeMs - FallStartTime) * diff);
|
|
|
|
f32 dt = 1.f;
|
|
if (Falling)
|
|
{
|
|
dt = f32 ( ( timeMs - FallStartTime ) * diff );
|
|
}
|
|
core::vector3df g = Gravity * dt;
|
|
|
|
core::triangle3df triangle = RefTriangle;
|
|
|
|
core::vector3df force = vel + g;
|
|
|
|
const core::vector3df nullVector ( 0.f, 0.f, 0.f );
|
|
|
|
if ( force != nullVector )
|
|
{
|
|
// TODO: divide SlidingSpeed by frame time
|
|
|
|
bool f = false;
|
|
pos = SceneManager->getSceneCollisionManager()->getCollisionResultPosition(
|
|
World, LastPosition-Translation,
|
|
Radius, vel, triangle, f, SlidingSpeed, g);
|
|
|
|
pos += Translation;
|
|
|
|
if (f)//triangle == RefTriangle)
|
|
{
|
|
if (!Falling)
|
|
FallStartTime = timeMs;
|
|
|
|
Falling = true;
|
|
}
|
|
else
|
|
Falling = false;
|
|
|
|
Object->setPosition(pos);
|
|
}
|
|
|
|
// move camera target
|
|
if (AnimateCameraTarget && IsCamera)
|
|
{
|
|
const core::vector3df diff = Object->getPosition() - LastPosition - vel;
|
|
ICameraSceneNode* cam = (ICameraSceneNode*)Object;
|
|
cam->setTarget(cam->getTarget() + diff);
|
|
}
|
|
|
|
LastPosition = Object->getPosition();
|
|
}
|
|
|
|
void CSceneNodeAnimatorCollisionResponse::setNode(ISceneNode* node)
|
|
{
|
|
Object = node;
|
|
|
|
if (Object)
|
|
{
|
|
LastPosition = Object->getPosition();
|
|
IsCamera = (Object->getType() == ESNT_CAMERA);
|
|
}
|
|
|
|
LastTime = os::Timer::getTime();
|
|
FallStartTime = LastTime;
|
|
}
|
|
|
|
//! Writes attributes of the scene node animator.
|
|
void CSceneNodeAnimatorCollisionResponse::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
|
{
|
|
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)
|
|
{
|
|
Radius = in->getAttributeAsVector3d("Radius");
|
|
Gravity = in->getAttributeAsVector3d("Gravity");
|
|
Translation = in->getAttributeAsVector3d("Translation");
|
|
AnimateCameraTarget = in->getAttributeAsBool("AnimateCameraTarget");
|
|
}
|
|
|
|
|
|
|
|
} // end namespace scene
|
|
} // end namespace irr
|
|
|