Significant internal change to the way that FPS camera jump speed and collision response animator gravity interact. The behaviour is now much more realistic, but it will require you to adjust your jump speed and gravity. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1811 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
f7dfda9f1f
commit
a83051f62e
|
@ -1,5 +1,7 @@
|
|||
Changes in version 1.5 (... 2008)
|
||||
|
||||
- Significant internal change to the way that FPS camera jump speed and collision response animator gravity interact. The behaviour is now much more realistic, but it will require you to adjust your jump speed and gravity.
|
||||
|
||||
- Renamed IGUIElement::setRelativePosition(const core::rect<f32>& r) to IGUIElement::setRelativePositionProportional(), as it has radically different functionality from setRelativePosition(const core::rect<s32>& r)
|
||||
|
||||
- Added IGUIElement::setRelativePosition(const core::position2di & position) to set a new position while retaining the existing height and width.
|
||||
|
|
|
@ -95,14 +95,14 @@ int main()
|
|||
We add a first person shooter camera to the scene for being able to
|
||||
move in the quake 3 level like in tutorial 2. But this, time, we add a
|
||||
special animator to the camera: A Collision Response animator. This
|
||||
thing modifies the scene node to which it is attached to in that way,
|
||||
that it may no more move through walls and is affected by gravity. The
|
||||
animator modifies the scene node to which it is attached to in order to
|
||||
prevent it moving through walls, and to add gravity to it. The
|
||||
only thing we have to tell the animator is how the world looks like,
|
||||
how big the scene node is, how gravity and so on. After the collision
|
||||
response animator is attached to the camera, we do not have to do
|
||||
anything more for collision detection, anything is done automaticly,
|
||||
how big the scene node is, how much gravity to apply and so on. After the
|
||||
collision response animator is attached to the camera, we do not have to do
|
||||
anything more for collision detection, anything is done automatically,
|
||||
all other collision detection code below is for picking. And please
|
||||
note another cool feature: The collsion response animator can be
|
||||
note another cool feature: The collision response animator can be
|
||||
attached also to all other scene nodes, not only to cameras. And it can
|
||||
be mixed with other scene node animators. In this way, collision
|
||||
detection and response in the Irrlicht engine is really, really easy.
|
||||
|
@ -115,26 +115,29 @@ int main()
|
|||
case it is the camera. The third defines how big the object is, it is
|
||||
the radius of an ellipsoid. Try it out and change the radius to smaller
|
||||
values, the camera will be able to move closer to walls after this. The
|
||||
next parameter is the direction and speed of gravity. You could set it
|
||||
to (0,0,0) to disable gravity. And the last value is just a
|
||||
translation: Without this, the ellipsoid with which collision detection
|
||||
is done would be around the camera, and the camera would be in the
|
||||
middle of the ellipsoid. But as human beings, we are used to have our
|
||||
next parameter is the direction and speed of gravity. We'll set it to
|
||||
(0, -10, 0), which approximates to realistic gravity, assuming that our
|
||||
units are metres. You could set it to (0,0,0) to disable gravity. And the
|
||||
last value is just a translation: Without this, the ellipsoid with which
|
||||
collision detection is done would be around the camera, and the camera would
|
||||
be in the middle of the ellipsoid. But as human beings, we are used to have our
|
||||
eyes on top of the body, with which we collide with our world, not in
|
||||
the middle of it. So we place the scene node 50 units over the center
|
||||
of the ellipsoid with this parameter. And that's it, collision
|
||||
detection works now.
|
||||
*/
|
||||
|
||||
// Set a jump speed of 3 units per second, which gives a fairly realistic jump
|
||||
// when used with the gravity of (0, -10, 0) in the collision response animator.
|
||||
scene::ICameraSceneNode* camera =
|
||||
smgr->addCameraSceneNodeFPS(0, 100.0f, 300.0f, -1, 0, 0, true);
|
||||
smgr->addCameraSceneNodeFPS(0, 100.0f, 300.0f, -1, 0, 0, true, 3.f);
|
||||
camera->setPosition(core::vector3df(-100,50,-150));
|
||||
|
||||
if (selector)
|
||||
{
|
||||
scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
|
||||
selector, camera, core::vector3df(30,50,30),
|
||||
core::vector3df(0,-3,0),
|
||||
core::vector3df(0,-10,0),
|
||||
core::vector3df(0,50,0));
|
||||
camera->addAnimator(anim);
|
||||
anim->drop();
|
||||
|
|
|
@ -324,13 +324,13 @@ void CDemo::switchToNextScene()
|
|||
keyMap[8].Action = EKA_JUMP_UP;
|
||||
keyMap[8].KeyCode = KEY_KEY_J;
|
||||
|
||||
camera = sm->addCameraSceneNodeFPS(0, 100.0f, 400.0f, -1, keyMap, 9, false, 0.f);
|
||||
camera = sm->addCameraSceneNodeFPS(0, 100.0f, 400.0f, -1, keyMap, 9, false, 3.f);
|
||||
camera->setPosition(core::vector3df(108,140,-140));
|
||||
|
||||
scene::ISceneNodeAnimatorCollisionResponse* collider =
|
||||
sm->createCollisionResponseAnimator(
|
||||
metaSelector, camera, core::vector3df(25,50,25),
|
||||
core::vector3df(0, quakeLevelMesh ? -2.5f : 0.0f,0),
|
||||
core::vector3df(0, quakeLevelMesh ? -10.f : 0.0f,0),
|
||||
core::vector3df(0,45,0), 0.005f);
|
||||
|
||||
camera->addAnimator(collider);
|
||||
|
|
|
@ -1086,9 +1086,9 @@ namespace scene
|
|||
const core::aabbox3d<f32>& box = yourSceneNode->getBoundingBox();
|
||||
core::vector3df radius = box.MaxEdge - box.getCenter();
|
||||
\endcode
|
||||
\param gravityPerSecond: Sets the gravity of the environment. A good example value would be
|
||||
core::vector3df(0,-100.0f,0) for letting gravity affect all object to
|
||||
fall down. For bigger gravity, make increase the length of the vector.
|
||||
\param gravityPerSecond: Sets the gravity of the environment, as an acceleration in
|
||||
units per second per second. If your units are equivalent to metres, then
|
||||
core::vector3df(0,-10.0f,0) would give an approximately realistic gravity.
|
||||
You can disable gravity by setting it to core::vector3df(0,0,0).
|
||||
\param ellipsoidTranslation: By default, the ellipsoid for collision detection is created around
|
||||
the center of the scene node, which means that the ellipsoid surrounds
|
||||
|
@ -1102,7 +1102,7 @@ namespace scene
|
|||
virtual ISceneNodeAnimatorCollisionResponse* createCollisionResponseAnimator(
|
||||
ITriangleSelector* world, ISceneNode* sceneNode,
|
||||
const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30),
|
||||
const core::vector3df& gravityPerSecond = core::vector3df(0,-100.0f,0),
|
||||
const core::vector3df& gravityPerSecond = core::vector3df(0,-10.0f,0),
|
||||
const core::vector3df& ellipsoidTranslation = core::vector3df(0,0,0),
|
||||
f32 slidingValue = 0.0005f) = 0;
|
||||
|
||||
|
|
|
@ -63,6 +63,11 @@ namespace scene
|
|||
//! \return Gravity vector. */
|
||||
virtual core::vector3df getGravity() const = 0;
|
||||
|
||||
//! 'Jump' the animator, by adding a jump speed opposite to its gravity
|
||||
/** \param jumpSpeed The initial speed of the jump; the velocity will be opposite
|
||||
to this animator's gravity vector. */
|
||||
virtual void jump(f32 jumpSpeed) = 0;
|
||||
|
||||
//! Set translation of the collision ellipsoid.
|
||||
/** By default, the ellipsoid for collision detection is
|
||||
created around the center of the scene node, which means that
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "Keycodes.h"
|
||||
#include "ICursorControl.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "ISceneNodeAnimatorCollisionResponse.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
@ -199,9 +200,26 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
|
|||
if (CursorKeys[EKA_STRAFE_RIGHT])
|
||||
pos -= strafevect * timeDiff * MoveSpeed;
|
||||
|
||||
// jumping ( needs a gravity , else it's a fly to the World-UpVector )
|
||||
// For jumping, we find the collision response animator attached to our camera
|
||||
// and if it's not falling, we tell it to jump.
|
||||
if (CursorKeys[EKA_JUMP_UP])
|
||||
pos += camera->getUpVector() * timeDiff * JumpSpeed;
|
||||
{
|
||||
const core::list<ISceneNodeAnimator*> & animators = camera->getAnimators();
|
||||
core::list<ISceneNodeAnimator*>::ConstIterator it = animators.begin();
|
||||
while(it != animators.end())
|
||||
{
|
||||
if(ESNAT_COLLISION_RESPONSE == (*it)->getType())
|
||||
{
|
||||
ISceneNodeAnimatorCollisionResponse * collisionResponse =
|
||||
static_cast<ISceneNodeAnimatorCollisionResponse *>(*it);
|
||||
|
||||
if(!collisionResponse->isFalling())
|
||||
collisionResponse->jump(JumpSpeed);
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
// write translation
|
||||
camera->setPosition(pos);
|
||||
|
|
|
@ -21,8 +21,8 @@ CSceneNodeAnimatorCollisionResponse::CSceneNodeAnimatorCollisionResponse(
|
|||
const core::vector3df& gravityPerSecond,
|
||||
const core::vector3df& ellipsoidTranslation,
|
||||
f32 slidingSpeed)
|
||||
: Radius(ellipsoidRadius), Gravity(gravityPerSecond / 1000.0f), Translation(ellipsoidTranslation),
|
||||
World(world), Object(object), SceneManager(scenemanager),
|
||||
: Radius(ellipsoidRadius), Gravity(gravityPerSecond), Translation(ellipsoidTranslation),
|
||||
World(world), Object(object), SceneManager(scenemanager), FallingVelocity(0.f),
|
||||
SlidingSpeed(slidingSpeed), Falling(false), IsCamera(false), AnimateCameraTarget(true)
|
||||
{
|
||||
|
||||
|
@ -85,6 +85,13 @@ 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)
|
||||
|
@ -108,8 +115,6 @@ void CSceneNodeAnimatorCollisionResponse::setWorld(ITriangleSelector* newWorld)
|
|||
Falling = false;
|
||||
|
||||
LastTime = os::Timer::getTime();
|
||||
FallStartTime = LastTime;
|
||||
|
||||
|
||||
if (World)
|
||||
World->drop();
|
||||
|
@ -148,18 +153,11 @@ void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 time
|
|||
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;
|
||||
FallingVelocity += Gravity * (f32)diff * 0.001f;
|
||||
|
||||
core::triangle3df triangle = RefTriangle;
|
||||
|
||||
core::vector3df force = vel + g;
|
||||
core::vector3df force = vel + FallingVelocity;
|
||||
|
||||
const core::vector3df nullVector ( 0.f, 0.f, 0.f );
|
||||
|
||||
|
@ -170,19 +168,19 @@ void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 time
|
|||
bool f = false;
|
||||
pos = SceneManager->getSceneCollisionManager()->getCollisionResultPosition(
|
||||
World, LastPosition-Translation,
|
||||
Radius, vel, triangle, f, SlidingSpeed, g);
|
||||
Radius, vel, triangle, f, SlidingSpeed, FallingVelocity);
|
||||
|
||||
pos += Translation;
|
||||
|
||||
if (f)//triangle == RefTriangle)
|
||||
{
|
||||
if (!Falling)
|
||||
FallStartTime = timeMs;
|
||||
|
||||
Falling = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Falling = false;
|
||||
FallingVelocity.set(0, 0, 0);
|
||||
}
|
||||
|
||||
Object->setPosition(pos);
|
||||
}
|
||||
|
@ -209,7 +207,6 @@ void CSceneNodeAnimatorCollisionResponse::setNode(ISceneNode* node)
|
|||
}
|
||||
|
||||
LastTime = os::Timer::getTime();
|
||||
FallStartTime = LastTime;
|
||||
}
|
||||
|
||||
//! Writes attributes of the scene node animator.
|
||||
|
|
|
@ -51,6 +51,9 @@ namespace scene
|
|||
//! Sets the gravity of the environment.
|
||||
virtual void setGravity(const core::vector3df& gravity);
|
||||
|
||||
//! 'Jump' the animator, by adding a jump speed opposite to its gravity
|
||||
virtual void jump(f32 jumpSpeed);
|
||||
|
||||
//! Returns current vector of gravity.
|
||||
virtual core::vector3df getGravity() const;
|
||||
|
||||
|
@ -93,13 +96,13 @@ namespace scene
|
|||
core::vector3df LastPosition;
|
||||
core::vector3df Radius;
|
||||
core::vector3df Gravity;
|
||||
core::vector3df FallingVelocity; // In the direction of Gravity.
|
||||
core::vector3df Translation;
|
||||
|
||||
ITriangleSelector* World;
|
||||
ISceneNode* Object;
|
||||
ISceneManager* SceneManager;
|
||||
u32 LastTime;
|
||||
u32 FallStartTime;
|
||||
f32 SlidingSpeed;
|
||||
bool Falling;
|
||||
bool IsCamera;
|
||||
|
|
Loading…
Reference in New Issue