Commit 1b628ef6 authored by Rogerborg's avatar Rogerborg

Expose the target scene nodes of collision response animators. Setting the...

Expose the target scene nodes of collision response animators.  Setting the target forces an update of its last position.  This allows a setPosition() to take effect without being blocked by the collision geometry.  Added comments to this effect, a unit test, and some unrelated !node checks in all the animators' animateNode() methods.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1957 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 9bc11201
...@@ -1082,7 +1082,9 @@ namespace scene ...@@ -1082,7 +1082,9 @@ namespace scene
ISceneManager::createTriangleSelector(); ISceneManager::createTriangleSelector();
\param sceneNode: SceneNode which should be manipulated. After you added this animator \param sceneNode: SceneNode which should be manipulated. After you added this animator
to the scene node, the scene node will not be able to move through walls and is to the scene node, the scene node will not be able to move through walls and is
affected by gravity. affected by gravity. If you need to teleport the scene node to a new position without
it being effected by the collision geometry, then call sceneNode->setPosition(); then
animator->setTargetNode(sceneNode);
\param ellipsoidRadius: Radius of the ellipsoid with which collision detection and \param ellipsoidRadius: Radius of the ellipsoid with which collision detection and
response is done. If you have got a scene node, and you are unsure about response is done. If you have got a scene node, and you are unsure about
how big the radius should be, you could use the following code to determine how big the radius should be, you could use the following code to determine
......
...@@ -13,14 +13,19 @@ namespace scene ...@@ -13,14 +13,19 @@ namespace scene
{ {
//! Special scene node animator for doing automatic collision detection and response. //! Special scene node animator for doing automatic collision detection and response.
/** This scene node animator can be attached to any scene node /** This scene node animator can be attached to any single scene node
modifying it in that way, that it cannot move through walls of the and will then prevent it from moving through specified collision geometry
world, is influenced by gravity and acceleration. This animator is (e.g. walls and floors of the) world, as well as having it fall under gravity.
useful for example for first person shooter games. Attach it for This animator provides a simple implementation of first person shooter cameras.
example to a first person shooter camera, and the camera will behave as Attach it to a camera, and the camera will behave as the player control in a
the player control in a first person shooter game: The camera stops and first person shooter game: The camera stops and slides at walls, walks up stairs,
slides at walls, walks up stairs, falls down if there is no floor under falls down if there is no floor under it, and so on.
it, and so on. */
The animator will treat any change in the position of its target scene
node as movement, including a setPosition(), as movement. If you want to
teleport the target scene node manually to a location without it being effected
by collision geometry, then call setTargetNode(node) after calling node->setPosition().
*/
class ISceneNodeAnimatorCollisionResponse : public ISceneNodeAnimator class ISceneNodeAnimatorCollisionResponse : public ISceneNodeAnimator
{ {
public: public:
...@@ -92,6 +97,17 @@ namespace scene ...@@ -92,6 +97,17 @@ namespace scene
//! Get the current triangle selector containing all triangles for collision detection. //! Get the current triangle selector containing all triangles for collision detection.
virtual ITriangleSelector* getWorld() const = 0; virtual ITriangleSelector* getWorld() const = 0;
//! Set the single node that this animator will act on.
/** \param node The new target node. Setting this will force the animator to update
its last target position for the node, allowing setPosition() to teleport
the node through collision geometry. */
virtual void setTargetNode(ISceneNode * node) = 0;
//! Gets the single node that this animator is acting on.
/** \return The node that this animator is acting on. */
virtual ISceneNode* getTargetNode(void) const = 0;
}; };
......
...@@ -96,7 +96,7 @@ bool CSceneNodeAnimatorCameraFPS::OnEvent(const SEvent& evt) ...@@ -96,7 +96,7 @@ bool CSceneNodeAnimatorCameraFPS::OnEvent(const SEvent& evt)
void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
{ {
if (node->getType() != ESNT_CAMERA) if (!node || node->getType() != ESNT_CAMERA)
return; return;
ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node); ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);
......
...@@ -90,7 +90,7 @@ void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs) ...@@ -90,7 +90,7 @@ void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs)
//Alt + LM + MM = Dolly forth/back in view direction (speed % distance camera pivot - max distance to pivot) //Alt + LM + MM = Dolly forth/back in view direction (speed % distance camera pivot - max distance to pivot)
//Alt + MM = Move on camera plane (Screen center is about the mouse pointer, depending on move speed) //Alt + MM = Move on camera plane (Screen center is about the mouse pointer, depending on move speed)
if (node->getType() != ESNT_CAMERA) if (!node || node->getType() != ESNT_CAMERA)
return; return;
ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node); ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);
......
...@@ -137,12 +137,9 @@ ITriangleSelector* CSceneNodeAnimatorCollisionResponse::getWorld() const ...@@ -137,12 +137,9 @@ ITriangleSelector* CSceneNodeAnimatorCollisionResponse::getWorld() const
void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 timeMs) void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 timeMs)
{ {
if (node != Object) if (node != Object)
{
setNode(node); setNode(node);
return;
}
if (!World) if(!Object || !World)
return; return;
u32 diff = timeMs - LastTime; u32 diff = timeMs - LastTime;
......
...@@ -89,6 +89,12 @@ namespace scene ...@@ -89,6 +89,12 @@ namespace scene
this. */ this. */
virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0);
//! Set the single node that this animator will act on.
virtual void setTargetNode(ISceneNode * node) { setNode(node); }
//! Gets the single node that this animator is acting on.
virtual ISceneNode* getTargetNode(void) const { return Object; }
private: private:
void setNode(ISceneNode* node); void setNode(ISceneNode* node);
......
...@@ -30,6 +30,9 @@ inline s32 CSceneNodeAnimatorFollowSpline::clamp(s32 idx, s32 size) ...@@ -30,6 +30,9 @@ inline s32 CSceneNodeAnimatorFollowSpline::clamp(s32 idx, s32 size)
//! animates a scene node //! animates a scene node
void CSceneNodeAnimatorFollowSpline::animateNode(ISceneNode* node, u32 timeMs) void CSceneNodeAnimatorFollowSpline::animateNode(ISceneNode* node, u32 timeMs)
{ {
if(!node)
return;
const u32 pSize = Points.size(); const u32 pSize = Points.size();
if (pSize==0) if (pSize==0)
return; return;
......
...@@ -53,6 +53,9 @@ void CSceneNodeAnimatorTexture::clearTextures() ...@@ -53,6 +53,9 @@ void CSceneNodeAnimatorTexture::clearTextures()
//! animates a scene node //! animates a scene node
void CSceneNodeAnimatorTexture::animateNode(ISceneNode* node, u32 timeMs) void CSceneNodeAnimatorTexture::animateNode(ISceneNode* node, u32 timeMs)
{ {
if(!node)
return;
if (Textures.size()) if (Textures.size())
{ {
const u32 t = (timeMs-StartTime); const u32 t = (timeMs-StartTime);
......
...@@ -54,6 +54,7 @@ int main(int argumentCount, char * arguments[]) ...@@ -54,6 +54,7 @@ int main(int argumentCount, char * arguments[])
extern bool md2Animation(void); extern bool md2Animation(void);
extern bool b3dAnimation(void); extern bool b3dAnimation(void);
extern bool guiDisabledMenu(void); extern bool guiDisabledMenu(void);
extern bool collisionResponseAnimator(void);
typedef struct _STest typedef struct _STest
{ {
...@@ -65,7 +66,11 @@ int main(int argumentCount, char * arguments[]) ...@@ -65,7 +66,11 @@ int main(int argumentCount, char * arguments[])
static const STest tests[] = static const STest tests[] =
{ {
TEST(disambiguateTextures), // Run this first, since it validates the WD. // Note that to interactively debug a test, you will generally want to move it
// (temporarily) to the beginning of the list, since each test runs in its own
// process.
TEST(collisionResponseAnimator),
TEST(disambiguateTextures), // Normally you should run this first, since it validates the working directory.
TEST(exports), TEST(exports),
TEST(testVector3d), TEST(testVector3d),
TEST(testVector2d), TEST(testVector2d),
......
...@@ -8,9 +8,9 @@ ...@@ -8,9 +8,9 @@
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#if defined(_MSC_VER) && !defined(NDEBUG) #if defined(TESTING_ON_WINDOWS)
#include <windows.h> #include <windows.h> // For OutputDebugString()
#endif // #if defined(_MSC_VER) && !defined(NDEBUG) #endif // #if defined(TESTING_ON_WINDOWS)
using namespace irr; using namespace irr;
...@@ -247,7 +247,7 @@ void logTestString(const char * format, ...) ...@@ -247,7 +247,7 @@ void logTestString(const char * format, ...)
(void)fflush(logFile); (void)fflush(logFile);
} }
#if defined(_MSC_VER) && !defined(NDEBUG) #if defined(TESTING_ON_WINDOWS)
OutputDebugStringA(logString); OutputDebugStringA(logString);
#endif // #if defined(_MSC_VER) && !defined(NDEBUG) #endif // #if defined(TESTING_ON_WINDOWS)
} }
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
#include "irrlicht.h" #include "irrlicht.h"
#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) || defined(_WIN32_WCE)
#define TESTING_ON_WINDOWS
#endif
//! Compare two files //! Compare two files
/** \param fileName1 The first file for comparison. /** \param fileName1 The first file for comparison.
\param fileName1 The second file for comparison. \param fileName1 The second file for comparison.
......
Test suite pass at GMT Fri Dec 12 10:58:58 2008 Test suite pass at GMT Tue Dec 16 14:56:26 2008
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
</Linker> </Linker>
<Unit filename="b3dAnimation.cpp" /> <Unit filename="b3dAnimation.cpp" />
<Unit filename="disambiguateTextures.cpp" /> <Unit filename="disambiguateTextures.cpp" />
<Unit filename="collisionResponseAnimator.cpp" />
<Unit filename="drawPixel.cpp" /> <Unit filename="drawPixel.cpp" />
<Unit filename="exports.cpp" /> <Unit filename="exports.cpp" />
<Unit filename="fast_atof.cpp" /> <Unit filename="fast_atof.cpp" />
......
...@@ -173,6 +173,10 @@ ...@@ -173,6 +173,10 @@
RelativePath=".\b3dAnimation.cpp" RelativePath=".\b3dAnimation.cpp"
> >
</File> </File>
<File
RelativePath=".\collisionResponseAnimator.cpp"
>
</File>
<File <File
RelativePath=".\disambiguateTextures.cpp" RelativePath=".\disambiguateTextures.cpp"
> >
...@@ -206,11 +210,11 @@ ...@@ -206,11 +210,11 @@
> >
</File> </File>
<File <File
RelativePath=".\softwareDevice.cpp" RelativePath=".\planeMatrix.cpp"
> >
</File> </File>
<File <File
RelativePath=".\planeMatrix.cpp" RelativePath=".\softwareDevice.cpp"
> >
</File> </File>
<File <File
......
...@@ -169,6 +169,10 @@ ...@@ -169,6 +169,10 @@
RelativePath=".\b3dAnimation.cpp" RelativePath=".\b3dAnimation.cpp"
> >
</File> </File>
<File
RelativePath=".\collisionResponseAnimator.cpp"
>
</File>
<File <File
RelativePath=".\disambiguateTextures.cpp" RelativePath=".\disambiguateTextures.cpp"
> >
......
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