Motion Trails

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
varmint
Posts: 46
Joined: Fri Oct 06, 2006 4:33 pm

Motion Trails

Post by varmint »

Sorry I thought my post got deleted so I took it as no one was interested :P

I used 04.Movement as the example for this. Motion trail is easy to use, it just needs a start node and end node. You can use anything though, mount points on a skeleton or what ever you want. :)

in irrlicht.h add

Code: Select all

#include "IMotionTrailSceneNode.h"
I added it just after
#include "IVolumeLightSceneNode.h"

Then download the following:
http://shadow.krabbit.com/varmint/motio ... amside.png
put it in your media folder

http://shadow.krabbit.com/varmint/motio ... ceneNode.h
place in your include folder

And Finnally
http://shadow.krabbit.com/varmint/motio ... ceneNode.h
http://shadow.krabbit.com/varmint/motio ... neNode.cpp
place in your source/Irrlicht folder

This is the 04.Movement example with the code modified to use the motion trails.
http://shadow.krabbit.com/varmint/motiontrail/main.cpp

To do it yourself

Code: Select all

//include motion trail header
//------------------------------------------------------------
#include "CMotionTrailSceneNode.h" in your project
to create the motion trail

Code: Select all

	//create motion trail
	//------------------------------------------------------------
	scene::IMotionTrailSceneNode *motionTrail = NULL;
	scene::ISceneNode *trailStart = NULL, 
						*trailEnd = NULL;

	motionTrail = new scene::CMotionTrailSceneNode(smgr->getRootSceneNode(),													smgr, 0, device);

	trailStart = device->getSceneManager()->addEmptySceneNode(anms);
	trailStart->setPosition(core::vector3df(0,30,0));

	trailEnd = device->getSceneManager()->addEmptySceneNode(anms);
	trailEnd->setPosition(core::vector3df(0,-20,0));

	video::SMaterial &mat = motionTrail->getMaterial(0);
	mat.DiffuseColor = video::SColor( 51, 51, 204, 204 ); //motion trail colour
	mat.setTexture(0, device->getVideoDriver()->getTexture("../../media/beamside.png"));
	//motionTrail->setLifeTime(0.59f);
	//------------------------------------------------------------

The just after drawAll is called update the motion trail

Code: Select all

//update motion trail
//------------------------------------------------------------
		motionTrail->updateTrail(trailStart->getAbsolutePosition(), trailEnd->getAbsolutePosition(), true);
And there you go.

Image

This currently only works in OpenGL as it uses Quads. Maybe someone can convert it to Tri's as I don't have time too. I also used a link list method instead of core::array to avoid the shuffle, as they are created and deleted fast. Everything has been tested with ValGrind and on OSX, Windows and Linux.

Motion trail video using mount points on an animated skeleton.
http://shadow.krabbit.com/varmint/ksw_test_audio.wmv
a still pic
http://shadow.krabbit.com/varmint/ksw_t ... 800/15.jpg

Enjoy
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Another great addition by our great varmint :)
Thanks!
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
doqkhanh
Posts: 158
Joined: Sat Mar 01, 2008 3:14 am
Location: Tokyo, Japan
Contact:

Post by doqkhanh »

wow !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

:shock: very cool effect!
doqkhanh
Posts: 158
Joined: Sat Mar 01, 2008 3:14 am
Location: Tokyo, Japan
Contact:

Post by doqkhanh »

Oh no! OpenGL only, like your volumetricLightSceneNode :((

Code: Select all

// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
//
// created by Dean Wadsworth aka Varmint Dec 31 2007

#ifndef __I_MOTION_TRAIL_SCENE_NODE_H_INCLUDED__
#define __I_MOTION_TRAIL_SCENE_NODE_H_INCLUDED__

#include "irrlicht.h"
#include "ISceneNode.h"

namespace irr
{
namespace scene
{
	class IMotionTrailSceneNode : public ISceneNode
	{
	public:

		//! constructor
		IMotionTrailSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
			IrrlichtDevice* inDevice, 
			const core::vector3df& position,
			const core::vector3df& rotation,
			const core::vector3df& scale)
			: ISceneNode(parent, mgr, id, position, rotation, scale) {};

		//! Returns type of the scene node
		virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; }

        virtual void addTrail(core::vector3df inStart, core::vector3df inEnd) = 0;
		
		virtual void updateTrail(core::vector3df inStart, core::vector3df inEnd,  bool addMoreTrails = true) = 0;
		
		virtual void setLifeTime(f32 inLifeTime) = 0;
		virtual f32  getLifeTime() = 0;
		
		virtual void setMaxMotionTrails(u32 inMax) = 0;
		virtual u32  getMaxMotionTrails() = 0;
		
		virtual void setCurveTessel(f32 inTessel) = 0;
		virtual f32 getCurveTessel() = 0;

	};

} // end namespace scene
} // end namespace irr

#endif

Code: Select all

// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
//
// created by Dean Wadsworth aka Varmint Jan 12th 2008

#ifndef __C_MOTION_TRAILSCENE_NODE_H_INCLUDED__
#define __C_MOTION_TRAILSCENE_NODE_H_INCLUDED__

#include "IMotionTrailSceneNode.h"
#include "SMeshBuffer.h"

namespace irr
{
namespace scene
{
	class CMotionTrailSceneNode : public IMotionTrailSceneNode
	{
	public:

		//! constructor
		CMotionTrailSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
			IrrlichtDevice* inDevice, 
			const core::vector3df& position = core::vector3df(0,0,0),
			const core::vector3df& rotation = core::vector3df(0,0,0),
			const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
		
		~CMotionTrailSceneNode();

		virtual void OnRegisterSceneNode();

		//! renders the node.
		virtual void render();

		//! returns the axis aligned bounding box of this node
		virtual const core::aabbox3d<f32>& getBoundingBox() const;

		//! returns the material based on the zero based index i. To get the amount
		//! of materials used by this scene node, use getMaterialCount().
		//! This function is needed for inserting the node into the scene hirachy on a
		//! optimal position for minimizing renderstate changes, but can also be used
		//! to directly modify the material of a scene node.
		virtual video::SMaterial& getMaterial(u32 i);

		//! returns amount of materials used by this scene node.
		virtual u32 getMaterialCount() const;

		//! Returns type of the scene node
		virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; }

		//! Writes attributes of the scene node.
		virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;

		//! Reads attributes of the scene node.
		virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);

		//! Creates a clone of this scene node and its children.
		virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
		
		virtual void addTrail(core::vector3df inStart, core::vector3df inEnd);
		
		virtual void updateTrail(core::vector3df inStart, core::vector3df inEnd, bool addMoreTrails = true);
		
		virtual void setLifeTime(f32 inLifeTime) { lifetime = inLifeTime; }
		virtual f32  getLifeTime() { return lifetime; }
		
		virtual void setMaxMotionTrails(u32 inMax) { maxMotionTrails = inMax; };
		virtual u32  getMaxMotionTrails() { return maxMotionTrails; };
		
		virtual void setCurveTessel(f32 inTessel) { curveTessel = inTessel; };
		virtual f32  getCurveTessel() { return curveTessel; };

	private:
	
		void renderTrail(u32 currentTrail);
		void updateBoundingBox();
		
		IrrlichtDevice* irrDevice;
		
		struct vertpoints_s {
			f32 x,y,z;
		};
		struct texcoords_s {
			f32 x,y;
		};

		struct motionTrailSection
		{
		   core::vector3df	start;
		   core::vector3df	end;
		   f32				ElapsedTime;
		   f32				startAlpha;

		   u8           * colour;
		   texcoords_s  * texCoords;
		   vertpoints_s * verts;
		   u16          * indicies;
		   s32 indices_count;

		   motionTrailSection * Next;
		   motionTrailSection * Prev;
		};
		
		struct motionTrailLinkList {
			motionTrailSection * Head;
			motionTrailSection * Curr;
		};
		
		u32 trailCount;
		motionTrailLinkList trailList;
		video::SMaterial trailMaterial;
		u32 maxMotionTrails;				// Number of trails
		
		f32 curveTessel;					// Small values produce a high curve tesselation
											// High values produce a low curve tesselation
		
		f32 lifetime;						//now long each trail section should last
		u32 lastTime;
		core::aabbox3d<f32> boundingBox;
		core::vector3df lastAddedPos;

	};

} // end namespace scene
} // end namespace irr

#endif

Code: Select all


// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
//
// created by Dean Wadsworth aka Varmint Jan 12th 2008
#include "COpenGLDriver.h"
#include "COpenGLTexture.h"


#include "CMotionTrailSceneNode.h"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "S3DVertex.h"
#include "os.h"

namespace irr
{

inline void CatmullRomCalc(core::vector3df &out, f32 t, const core::vector3df p0, const core::vector3df p1, const core::vector3df p2, const core::vector3df p3)
{
	f32 t2 = t * t;
	f32 t3 = t2 * t;
	
	out.X = 0.5f * ( ( 2.0f * p1.X ) +
		( -p0.X + p2.X ) * t +
		( 2.0f * p0.X - 5.0f * p1.X + 4 * p2.X - p3.X ) * t2 +
		( -p0.X + 3.0f * p1.X - 3.0f * p2.X + p3.X ) * t3 );
	out.Y = 0.5f * ( ( 2.0f * p1.Y ) +
		( -p0.Y + p2.Y ) * t +
		( 2.0f * p0.Y - 5.0f * p1.Y + 4 * p2.Y - p3.Y ) * t2 +
		( -p0.Y + 3.0f * p1.Y - 3.0f * p2.Y + p3.Y ) * t3 );
	out.Z = 0.5f * ( ( 2.0f * p1.Z ) +
		( -p0.Z + p2.Z ) * t +
		( 2.0f * p0.Z - 5.0f * p1.Z + 4 * p2.Z - p3.Z ) * t2 +
		( -p0.Z + 3.0f * p1.Z - 3.0f * p2.Z + p3.Z ) * t3 );
}

inline f32 interpolate(const f32 from, const f32 to, const f32 factor)
{
   return from + factor*(to-from);
}   

namespace scene
{

//! constructor
CMotionTrailSceneNode::CMotionTrailSceneNode(ISceneNode* parent, ISceneManager* mgr,
		s32 id, IrrlichtDevice* inDevice, 
		const core::vector3df& position,
		const core::vector3df& rotation, const core::vector3df& scale)
	: IMotionTrailSceneNode(parent, mgr, id, irrDevice, position, rotation, scale),
		maxMotionTrails(60), lastAddedPos(core::vector3df(0.0f, 0.0f, 0.0f)), lifetime(0.4f), curveTessel(0.05f), lastTime(0)
{
	#ifdef _DEBUG
	setDebugName("CMotionTrailSceneNode");
	#endif
	
	trailCount =  0;
	trailList.Head = NULL;
	trailList.Curr = NULL;
	
	//trailMaterial.MaterialType = video::EMT_ONETEXTURE_BLEND;
	//trailMaterial.MaterialTypeParam = pack_texureBlendFunc( video::EBF_SRC_ALPHA, video::EBF_ONE_MINUS_SRC_ALPHA, video::EMFN_MODULATE_1X );
	//trailMaterial.MaterialTypeParam = pack_texureBlendFunc( video::EBF_SRC_COLOR, video::EBF_SRC_ALPHA, video::EMFN_MODULATE_1X );

	//trailMaterial.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
	//trailMaterial.MaterialTypeParam = 0.01f;
	//trailMaterial.MaterialType = video::EMT_DETAIL_MAP;

	trailMaterial.Lighting = false;
	trailMaterial.DiffuseColor = video::SColor( 51, 127, 0, 204 ); //default motiontrail colour
	//trailMaterial.ZWriteEnable = false;
	//trailMaterial.BackfaceCulling = false;
	//trailMaterial.ZBuffer = false;
	
	//trailMaterial.Thickness = 3.0f;
	
	setAutomaticCulling(scene::EAC_OFF);

	irrDevice = inDevice;

	trailCount = 0;
}

CMotionTrailSceneNode::~CMotionTrailSceneNode()
{
	motionTrailSection * dead = trailList.Head;
	while(dead) {
		motionTrailSection * next = dead->Next;
		if (dead->colour) {
			free(dead->colour);
			free(dead->texCoords);
			free(dead->verts);
			free(dead->indicies);
		}
		free(dead);
		dead = next;
	}
}

void CMotionTrailSceneNode::renderTrail(u32 currentTrail)
{
	if (trailList.Curr->verts) {
		//it's already created just render it
		glColorPointer(4, GL_UNSIGNED_BYTE, 0, trailList.Curr->colour);
		glTexCoordPointer(2, GL_FLOAT, sizeof(texcoords_s), trailList.Curr->texCoords);
		glVertexPointer(3, GL_FLOAT, sizeof(vertpoints_s), trailList.Curr->verts);
		glDrawElements(GL_QUADS, trailList.Curr->indices_count+1, GL_UNSIGNED_SHORT, trailList.Curr->indicies);
		return;
	}
	
	//create the trail
	if (trailCount < 2)
		return;

	core::vector3df startPoints[4], endPoints[4];
	
	if(currentTrail < 1)
		startPoints[0] = trailList.Head->start;
	else
		startPoints[0] = trailList.Curr->Prev->start;
	startPoints[1] = trailList.Curr->start;
	startPoints[2] = trailList.Curr->Next->start;
	if (trailCount-1 == 1)
		startPoints[3] = trailList.Head->start;
	else if(currentTrail+2 > trailCount-1)
		startPoints[3] = trailList.Curr->Prev->start;
	else
		startPoints[3] = trailList.Curr->Next->Next->start;

	if(currentTrail < 1)
		endPoints[0] = trailList.Head->end;
	else
		endPoints[0] = trailList.Curr->Prev->end;
	endPoints[1] = trailList.Curr->end;
	endPoints[2] = trailList.Curr->Next->end;
	if (trailCount-1 == 1)
		endPoints[3] = trailList.Head->end;
	else if(currentTrail+2 > trailCount-1)
		endPoints[3] = trailList.Curr->Prev->end;
	else
		endPoints[3] = trailList.Curr->Next->Next->end;

	motionTrailSection quad1 = *trailList.Curr;
	motionTrailSection quad2 = *trailList.Curr->Next;
	float	fPercentage1 = (float)currentTrail/(float)(trailCount-1);
	float	fPercentage2 = (float)(currentTrail+1)/(float)(trailCount-1);
	video::SColor clr = trailMaterial.DiffuseColor;

	core::vector3df start, end;
	float texCoordX;

	f32 fDist = core::vector3df(quad1.start - quad2.start).getLength();
	f32 fInc = curveTessel/fDist;
// -----------------------------------------------------------------------
	s32 size = (s32)((1.0f / fInc)+2.0f)*4;  //*4 for quads

	trailList.Curr->colour		= (u8 *)malloc(sizeof(u8)*size*4); //*4 four colours r,g,b,a
	memset(trailList.Curr->colour, '\0', (sizeof(u8)*size*4));
	trailList.Curr->texCoords	= (texcoords_s *)malloc(sizeof(texcoords_s)*size);
	memset(trailList.Curr->texCoords, '\0', (sizeof(texcoords_s)*size));
	trailList.Curr->verts		= (vertpoints_s *)malloc(sizeof(vertpoints_s)*size);
	memset(trailList.Curr->verts, '\0', (sizeof(vertpoints_s)*size));
	trailList.Curr->indicies	= (u16 *)malloc(sizeof(u16)*size);
	memset(trailList.Curr->indicies, '\0', (sizeof(u16)*size));
	
	trailList.Curr->indices_count = -1;
	
	s32 count = 0;
	s32 clrCount = 0;
// -----------------------------------------------------------------------

    for(f32 f=0.0; f<1.0; f+=fInc)
    {
		// Clamp to 1.0f due to floating point errors
		f32	nextf = core::min_(f+fInc, 1.0f);

		// Compute alpha for first side of quad
		clr.setAlpha(u32(interpolate(quad1.startAlpha, quad2.startAlpha, f)*255.0f));

		// Compute texture coordinate for first side of quad
		texCoordX = interpolate(fPercentage1, fPercentage2, f);

		// Compute interpolated coordinate of first side (top)
		CatmullRomCalc(start, f, startPoints[0], startPoints[1], startPoints[2], startPoints[3]);

		// First quad point
		trailList.Curr->indices_count++;
		clr.toOpenGLColor(&trailList.Curr->colour[clrCount]);
		trailList.Curr->indicies[count] = trailList.Curr->indices_count;
		trailList.Curr->verts[count].x = start.X;
		trailList.Curr->verts[count].y = start.Y;
		trailList.Curr->verts[count].z = start.Z;
		trailList.Curr->texCoords[count].x = texCoordX;
		trailList.Curr->texCoords[count].y = 0.0f;
		count++;
		clrCount+=4;

		// Compute interpolated coordinate of first side (bottom)
		CatmullRomCalc(end, f, endPoints[0], endPoints[1], endPoints[2], endPoints[3]);

		// Second quad point
		trailList.Curr->indices_count++;
		clr.toOpenGLColor(&trailList.Curr->colour[clrCount]);
		trailList.Curr->indicies[count] = trailList.Curr->indices_count;
		trailList.Curr->verts[count].x = end.X;
		trailList.Curr->verts[count].y = end.Y;
		trailList.Curr->verts[count].z = end.Z;
		trailList.Curr->texCoords[count].x = texCoordX;
		trailList.Curr->texCoords[count].y = 1.0f;
		count++;
		clrCount+=4;

		// Compute alpha for second side of quad
		clr.setAlpha(u32(interpolate(quad1.startAlpha, quad2.startAlpha, nextf)*255.0f));

		// Compute texture coordinate for second side of quad
		texCoordX = interpolate(fPercentage1, fPercentage2, nextf);

		// Compute interpolated coordinate of second side (bottom)
		CatmullRomCalc(end, nextf, endPoints[0], endPoints[1], endPoints[2], endPoints[3]);

		// Third quad point
		trailList.Curr->indices_count++;
		clr.toOpenGLColor(&trailList.Curr->colour[clrCount]);
		trailList.Curr->indicies[count] = trailList.Curr->indices_count;
		trailList.Curr->verts[count].x = end.X;
		trailList.Curr->verts[count].y = end.Y;
		trailList.Curr->verts[count].z = end.Z;
		trailList.Curr->texCoords[count].x = texCoordX;
		trailList.Curr->texCoords[count].y = 1.0f;
		count++;
		clrCount+=4;

		// Compute interpolated coordinate of first side (top)
		CatmullRomCalc(start, nextf, startPoints[0], startPoints[1], startPoints[2], startPoints[3]);

		// Forth quad point
		trailList.Curr->indices_count++;
		clr.toOpenGLColor(&trailList.Curr->colour[clrCount]);
		trailList.Curr->indicies[count] = trailList.Curr->indices_count;
		trailList.Curr->verts[count].x = start.X;
		trailList.Curr->verts[count].y = start.Y;
		trailList.Curr->verts[count].z = start.Z;
		trailList.Curr->texCoords[count].x = texCoordX;
		trailList.Curr->texCoords[count].y = 0.0f;
		count++;
		clrCount+=4;

		if ((count+4) >= size)
			break;
	}
	
	//if (size != count)
	//	printf("count: %i size: %i\n", count, size);
	if (trailList.Curr->verts) {
		glColorPointer(4, GL_UNSIGNED_BYTE, 0, trailList.Curr->colour);
		glTexCoordPointer(2, GL_FLOAT, sizeof(texcoords_s), trailList.Curr->texCoords);
		glVertexPointer(3, GL_FLOAT, sizeof(vertpoints_s), trailList.Curr->verts);
		glDrawElements(GL_QUADS, trailList.Curr->indices_count+1, GL_UNSIGNED_SHORT, trailList.Curr->indicies);
	}
}

//! renders the node.
void CMotionTrailSceneNode::render()
{
	if (trailCount < 2)
		return;

	video::IVideoDriver* driver = SceneManager->getVideoDriver();
	core::matrix4 mat;
	driver->setTransform(video::ETS_WORLD, mat);
	//driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
	//driver->setMaterial(trailMaterial);

	//store settings to restore after rendering done
	GLboolean isBlendOn		= glIsEnabled(GL_BLEND);
	GLboolean isCullFace	= glIsEnabled(GL_CULL_FACE);
	GLboolean isDepthTest	= glIsEnabled(GL_DEPTH_TEST);
	GLboolean isTexture2D	= glIsEnabled(GL_TEXTURE_2D);
	GLboolean isAlphaOn		= glIsEnabled(GL_ALPHA_TEST);
	GLboolean isLightingOn	= glIsEnabled(GL_LIGHTING);
	GLboolean isDepthWritable = false;
	GLint blendSrcAlpha = 0, blendDstAlpha = 0;
	glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha);
	glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDstAlpha);
	glGetBooleanv(GL_DEPTH_WRITEMASK, &isDepthWritable);
	GLint textureModeEnv = 0;
	glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &textureModeEnv);
	GLint alphaTestFunc = 0;
	GLfloat alphaRef = 0.0f;
	glGetIntegerv(GL_ALPHA_TEST_FUNC, &alphaTestFunc);
	glGetFloatv(GL_ALPHA_TEST_REF, &alphaRef);
	//store settings to restore after rendering done

	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GEQUAL, 0.01f);
	glEnable(GL_TEXTURE_2D);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	if (!isBlendOn)
		glEnable(GL_BLEND);
	if (isLightingOn)
		glDisable(GL_LIGHTING);
	glDepthMask(GL_FALSE);
	
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_CULL_FACE);

	const video::ITexture* texture = trailMaterial.getTexture(0);
	if (texture) {
		glBindTexture(GL_TEXTURE_2D, static_cast<const video::COpenGLTexture*>(texture)->getOpenGLTextureName());
	}

	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	motionTrailSection * curTrail = trailList.Curr;
	motionTrailSection * mptr = trailList.Head;
	for (u32 i = 0; i < (trailCount-1); i++) {
		if (mptr->ElapsedTime < lifetime) {
			trailList.Curr = mptr;
			renderTrail(i);
		}
		mptr = mptr->Next;
		if (!mptr)
			break;
	}
	
	trailList.Curr = curTrail;
	
	//restore env
	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, textureModeEnv);
	glBlendFunc(blendSrcAlpha, blendDstAlpha);
	glAlphaFunc(alphaTestFunc, alphaRef);
	if (isDepthWritable)
		glDepthMask(GL_TRUE);
	if (!isDepthTest)
		glDisable(GL_DEPTH_TEST);
	if (isCullFace)
		glEnable(GL_CULL_FACE);
	if (!isBlendOn)
		glDisable(GL_BLEND);
	if (!isTexture2D)
		glDisable(GL_TEXTURE_2D);
	if (!isAlphaOn)
		glDisable(GL_ALPHA_TEST);
	if (isLightingOn)
		glEnable(GL_LIGHTING);
}

void CMotionTrailSceneNode::updateTrail(core::vector3df inStart, core::vector3df inEnd, bool addMoreTrails)
{
	if (addMoreTrails && trailCount < maxMotionTrails)
		addTrail(inStart, inEnd);

	u32 curTime = irrDevice->getTimer()->getTime();
	if (trailCount > 0) {
		motionTrailSection * dead = trailList.Head;
		while(dead) {
			motionTrailSection * next = dead->Next;
			dead->ElapsedTime += (f32)(curTime - lastTime) / 1000.0f;
			if (dead->ElapsedTime >= lifetime) {
				if (dead->Prev)
					dead->Prev->Next = next;
				if (next)
					next->Prev = dead->Prev;
				if (trailList.Head == dead) {
					trailList.Head = next;
					if (next)
						setPosition((next->start + next->end) * 0.5f);
				}
				if (trailList.Curr == dead) {
					if (next)
						trailList.Curr = next;
					else if (dead->Prev)
						trailList.Curr = dead->Prev;
					if (!trailList.Curr)
						trailList.Curr = trailList.Head;
				}
				if (dead->colour) {
					free(dead->colour);
					free(dead->texCoords);
					free(dead->verts);
					free(dead->indicies);
				}
				free(dead);
				trailCount--;
			}
			dead = next;
		}
		if (trailCount < 0)
			trailCount = 0;
		if (trailCount == 0) {
			trailList.Head = NULL;
			trailList.Curr = NULL;
		}
	}

	lastTime = curTime;
}


void CMotionTrailSceneNode::updateBoundingBox()
{
   if(1 == trailCount)
   {
      // Reset object box
      boundingBox.reset(0,0,0);
	  boundingBox.addInternalPoint(trailList.Head->start);
	  boundingBox.addInternalPoint(trailList.Head->end);
      // Update the world space position
   } else {
      // Calculate new object box
      core::vector3df vecDist1 = trailList.Curr->start - getAbsolutePosition();
      core::vector3df vecDist2 = trailList.Curr->end - getAbsolutePosition();

      // Has vecDist1 new MinEdge values?
      if(boundingBox.MinEdge.X > vecDist1.X)
         boundingBox.MinEdge.X = vecDist1.X;
      if(boundingBox.MinEdge.Y > vecDist1.Y)
         boundingBox.MinEdge.Y = vecDist1.Y;
      if(boundingBox.MinEdge.Z > vecDist1.Z)
         boundingBox.MinEdge.Z = vecDist1.Z;
      // Has start new MaxEdge values?
      if(boundingBox.MaxEdge.X < vecDist1.X)
         boundingBox.MaxEdge.X = vecDist1.X;
      if(boundingBox.MaxEdge.Y < vecDist1.Y)
         boundingBox.MaxEdge.Y = vecDist1.Y;
      if(boundingBox.MaxEdge.Z < vecDist1.Z)
         boundingBox.MaxEdge.Z = vecDist1.Z;
      // Has end new MinEdge values?
      if(boundingBox.MinEdge.X > vecDist2.X)
         boundingBox.MinEdge.X = vecDist2.X;
      if(boundingBox.MinEdge.Y > vecDist2.Y)
         boundingBox.MinEdge.Y = vecDist2.Y;
      if(boundingBox.MinEdge.Z > vecDist2.Z)
         boundingBox.MinEdge.Z = vecDist2.Z;
      // Has end new MaxEdge values?
      if(boundingBox.MaxEdge.X < vecDist2.X)
         boundingBox.MaxEdge.X = vecDist2.X;
      if(boundingBox.MaxEdge.Y < vecDist2.Y)
         boundingBox.MaxEdge.Y = vecDist2.Y;
      if(boundingBox.MaxEdge.Z < vecDist2.Z)
         boundingBox.MaxEdge.Z = vecDist2.Z;
   }
}

void CMotionTrailSceneNode::addTrail(core::vector3df inStart, core::vector3df inEnd)
{
	// Check, if the new pos is somewhat different from the last one.
	if(core::vector3df(lastAddedPos - inStart).getLength() < 0.1f)
		return;
	
	lastAddedPos = inStart;
	
	motionTrailSection * newTrail;
	
	newTrail = (motionTrailSection *)malloc(sizeof(motionTrailSection));
	memset(newTrail, '\0', sizeof(motionTrailSection));
	
	newTrail->start = inStart;
	newTrail->end   = inEnd;
	newTrail->ElapsedTime = 0.0f;
	newTrail->startAlpha = 1.0f;

	if (trailCount == 0) {
		trailList.Head = newTrail;
	}
	
	if (trailList.Curr) {
		newTrail->Prev = trailList.Curr;
		trailList.Curr->Next = newTrail;
		//need to free current & prev trail for smooth blending with next trail
		if (trailList.Curr->colour) {
			free(trailList.Curr->colour);
			trailList.Curr->colour = NULL;
			free(trailList.Curr->texCoords);
			trailList.Curr->texCoords = NULL;
			free(trailList.Curr->verts);
			trailList.Curr->verts = NULL;
			free(trailList.Curr->indicies);
			trailList.Curr->indicies = NULL;
		}
		if (trailList.Curr->Prev && trailList.Curr->Prev->colour) {
			free(trailList.Curr->Prev->colour);
			trailList.Curr->Prev->colour = NULL;
			free(trailList.Curr->Prev->texCoords);
			trailList.Curr->Prev->texCoords = NULL;
			free(trailList.Curr->Prev->verts);
			trailList.Curr->Prev->verts = NULL;
			free(trailList.Curr->Prev->indicies);
			trailList.Curr->Prev->indicies = NULL;
		}
	}
	trailList.Curr = newTrail;
	
	trailCount++;

	//boundingBox.reset(0,0,0);
	
	//boundingBox.addInternalPoint(trailList.Head->start);
	//boundingBox.addInternalPoint(trail[trailCount-1].end);
	
	if (trailCount == 1) {
		setPosition((inStart + inEnd) * 0.5f);
		//updateAbsolutePosition();
		//updateBoundingBox();
	}
}

//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CMotionTrailSceneNode::getBoundingBox() const
{
	return boundingBox;
}


void CMotionTrailSceneNode::OnRegisterSceneNode()
{
	if (IsVisible)
	{
		SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT);
	}
	ISceneNode::OnRegisterSceneNode();
}


//! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hirachy on a
//! optimal position for minimizing renderstate changes, but can also be used
//! to directly modify the material of a scene node.
video::SMaterial& CMotionTrailSceneNode::getMaterial(u32 i)
{
	return trailMaterial;
}


//! returns amount of materials used by this scene node.
u32 CMotionTrailSceneNode::getMaterialCount() const
{
	return 1;
}


//! Writes attributes of the scene node.
void CMotionTrailSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
	ISceneNode::serializeAttributes(out, options);

}


//! Reads attributes of the scene node.
void CMotionTrailSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{

	ISceneNode::deserializeAttributes(in, options);
}


//! Creates a clone of this scene node and its children.
ISceneNode* CMotionTrailSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
{
	if (!newParent)
		newParent = Parent;
	if (!newManager)
		newManager = SceneManager;

	CMotionTrailSceneNode* nb = new CMotionTrailSceneNode(newParent,
		newManager, ID, irrDevice);
	nb->cloneMembers(this, newManager);

	nb->drop();
	return nb;
}


} // end namespace scene
} // end namespace irr

Code: Select all


/*
This Tutorial shows how to move and animate SceneNodes. The
basic concept of SceneNodeAnimators is shown as well as manual
movement of nodes using the keyboard.

As always, I include the header files, use the irr namespace,
and tell the linker to link with the .lib file.
*/
#include <irrlicht.h>
#include <iostream>

//include motion trail header
//------------------------------------------------------------
#include "CMotionTrailSceneNode.h"

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")

/*
To receive events like mouse and keyboard input, or GUI events like 
"the OK button has been clicked", we need an object which is derived from the 
IEventReceiver object. There is only one method to override: OnEvent. 
This method will be called by the engine once when an event happens. 
What we really want to know is whether a key is being held down,
and so we will remember the current state of each key.
*/
class MyEventReceiver : public IEventReceiver
{
public:
	// This is the one method that we have to implement
	virtual bool OnEvent(const SEvent& event)
	{
		// Remember whether each key is down or up
		if (event.EventType == irr::EET_KEY_INPUT_EVENT)
			KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;

		return false;
	}

	// This is used to check whether a key is being held down
	virtual bool IsKeyDown(EKEY_CODE keyCode) const
	{
		return KeyIsDown[keyCode];
	}

	MyEventReceiver()
	{
		for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
			KeyIsDown[i] = false;
	}

private:
	// We use this array to store the current state of each key
	bool KeyIsDown[KEY_KEY_CODES_COUNT];
};


/*
The event receiver for moving a scene node is ready. So lets just create
an Irrlicht Device and the scene node we want to move. We also create some
other additional scene nodes, to show that there are also some different 
possibilities to move and animate scene nodes.
*/
int main()
{
	// let user select driver type

	video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;

	printf("Please select the driver you want for this example:\n"\
		" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
		" (d) Software Renderer\n (e) Burning's Software Renderer\n"\
		" (f) NullDevice\n (otherKey) exit\n\n");

	char i;
	//std::cin >> i;
	i = 'c';

	switch(i)
	{
		case 'a': driverType = video::EDT_DIRECT3D9;break;
		case 'b': driverType = video::EDT_DIRECT3D8;break;
		case 'c': driverType = video::EDT_OPENGL;   break;
		case 'd': driverType = video::EDT_SOFTWARE; break;
		case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
		case 'f': driverType = video::EDT_NULL;     break;
		default: return 0;
	}	

	// create device
	MyEventReceiver receiver;

	IrrlichtDevice* device = createDevice( driverType, core::dimension2d<s32>(640, 480),
		16, false, false, false, &receiver);

	if (device == 0)
		return 1; // could not create selected driver.


	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();


	/*
	Create the node for moving it with the 'W' and 'S' key. We create a
	sphere node, which is a built in geometry primitive. We place the node
	at (0,0,30) and assign a texture to it to let it look a little bit more
	interesting. Because we have no dynamic lights in this scene we disable
	lighting for each model (otherwise the models would be black).
	*/
	scene::ISceneNode * node = smgr->addSphereSceneNode();
	if (node)
	{
		node->setPosition(core::vector3df(0,0,30));
		node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
		node->setMaterialFlag(video::EMF_LIGHTING, false);
	}


	/* 
	Now we create another node, moving using a scene node animator. Scene
	node animators modify scene nodes and can be attached to any scene node
	like mesh scene nodes, billboards, lights and even camera scene nodes.
	Scene node animators are not only able to modify the position of a
	scene node, they can also animate the textures of an object for
	example.  We create a cube scene node and attach a 'fly circle' scene
	node to it, letting this node fly around our sphere scene node.
	*/
	scene::ISceneNode* n = smgr->addCubeSceneNode();

	if (n)
	{
		n->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg"));
		n->setMaterialFlag(video::EMF_LIGHTING, false);
		scene::ISceneNodeAnimator* anim =
			smgr->createFlyCircleAnimator(core::vector3df(0,0,30), 20.0f);
		if (anim)
		{
			n->addAnimator(anim);
			anim->drop();
		}
	}

	/*
	The last scene node we add to show possibilities of scene node animators is 
	a md2 model, which uses a 'fly straight' animator to run between to points.
	*/
	scene::IAnimatedMeshSceneNode* anms = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/sydney.md2"));

	if (anms)
	{
		scene::ISceneNodeAnimator* anim =
			smgr->createFlyStraightAnimator(core::vector3df(100,0,60), 
			core::vector3df(-100,0,60), 2500, true);
		if (anim)
		{
			anms->addAnimator(anim);
			anim->drop();
		}

		/*
		To make to model look right we set the frames between which the animation
		should loop, rotate the model around 180 degrees, and adjust the animation speed
		and the texture.
		To set the right animation (frames and speed), we would also be able to just
		call "anms->setMD2Animation(scene::EMAT_RUN)" for the 'run' animation 
		instead of "setFrameLoop" and "setAnimationSpeed",
		but this only works with MD2 animations, and so you know how to start other animations.
		but it a good advice to use not hardcoded frame-numbers...
		*/
		anms->setMaterialFlag(video::EMF_LIGHTING, false);

		anms->setFrameLoop(160, 183);
		anms->setAnimationSpeed(40);
		anms->setMD2Animation(scene::EMAT_RUN);

		anms->setRotation(core::vector3df(0,180.0f,0));
		anms->setMaterialTexture(0, driver->getTexture("../../media/sydney.bmp"));

	}
	
	//create motion trail
	//------------------------------------------------------------
	scene::IMotionTrailSceneNode *motionTrail = NULL;
	scene::ISceneNode *trailStart = NULL, 
						*trailEnd = NULL;
	motionTrail = new scene::CMotionTrailSceneNode(smgr->getRootSceneNode(),
													smgr, 0, device);
	trailStart = device->getSceneManager()->addEmptySceneNode(anms);
	trailStart->setPosition(core::vector3df(0,30,0));
	trailEnd = device->getSceneManager()->addEmptySceneNode(anms);
	trailEnd->setPosition(core::vector3df(0,-20,0));
	
	video::SMaterial &mat = motionTrail->getMaterial(0);
	mat.DiffuseColor = video::SColor( 51, 51, 204, 204 );
	mat.setTexture(0, device->getVideoDriver()->getTexture("../../media/beamside.png"));
	//motionTrail->setLifeTime(0.59f);
	//------------------------------------------------------------


	/*
	To be able to look at and move around in this scene, we create a first
	person shooter style camera and make the mouse cursor invisible.
	*/
	scene::ICameraSceneNode * cam = smgr->addCameraSceneNodeFPS(0, 100.0f, 100.0f);
	device->getCursorControl()->setVisible(false);

	/*
	Add a colorful irrlicht logo
	*/
	device->getGUIEnvironment()->addImage(
		driver->getTexture("../../media/irrlichtlogoalpha2.tga"),
		core::position2d<s32>(10,10));

	/*
	We have done everything, so lets draw it. We also write the current
	frames per second and the name of the driver to the caption of the
	window.
	*/
	int lastFPS = -1;

	while(device->run())
	{
		/* Check if key W or key S is being held down, and move the
		sphere node up or down respectively.
		*/
		if(receiver.IsKeyDown(irr::KEY_KEY_W))
		{
			core::vector3df v = node->getPosition();
			v.Y += 0.02f;
			node->setPosition(v);
		}
		else if(receiver.IsKeyDown(irr::KEY_KEY_S))
		{
			core::vector3df v = node->getPosition();
			v.Y -= 0.02f;
			node->setPosition(v);
		}

		driver->beginScene(true, true, video::SColor(255,113,113,133));

		smgr->drawAll(); // draw the 3d scene
		//update motion trail
		//------------------------------------------------------------
		motionTrail->updateTrail(trailStart->getAbsolutePosition(), trailEnd->getAbsolutePosition(), true);
		device->getGUIEnvironment()->drawAll(); // draw the gui environment (the logo)

		driver->endScene();

		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
			core::stringw tmp(L"Movement Example - Irrlicht Engine [");
			tmp += driver->getName();
			tmp += L"] fps: "; 
			tmp += fps;

			device->setWindowCaption(tmp.c_str());
			lastFPS = fps;
		}
	}

	/*
	In the end, delete the Irrlicht device.
	*/
	device->drop();
	
	return 0;
}


[/code]
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Why did you post the whole code? The links are all working! Moreover, the OP clearly states that it is OpenGL only, but easily portable. And finally, the volumetric scene node is *NOT* OpenGL only, it's even part of the engine already (SVN trunk).
doqkhanh
Posts: 158
Joined: Sat Mar 01, 2008 3:14 am
Location: Tokyo, Japan
Contact:

Post by doqkhanh »

Please help,
Where to find a "1-1" compare between DirectX function and OpenGL function? OpenGL like a "chinese" with me...

Code: Select all

if (trailList.Curr->verts) {
		//it's already created just render it
		glColorPointer(4, GL_UNSIGNED_BYTE, 0, trailList.Curr->colour);
		glTexCoordPointer(2, GL_FLOAT, sizeof(texcoords_s), trailList.Curr->texCoords);
		glVertexPointer(3, GL_FLOAT, sizeof(vertpoints_s), trailList.Curr->verts);
		glDrawElements(GL_QUADS, trailList.Curr->indices_count+1, GL_UNSIGNED_SHORT, trailList.Curr->indicies);
		return;
	}

Code: Select all

		clr.toOpenGLColor(&trailList.Curr->colour[clrCount]);

Code: Select all

			if (trailList.Curr->verts) {
		glColorPointer(4, GL_UNSIGNED_BYTE, 0, trailList.Curr->colour);
		glTexCoordPointer(2, GL_FLOAT, sizeof(texcoords_s), trailList.Curr->texCoords);
		glVertexPointer(3, GL_FLOAT, sizeof(vertpoints_s), trailList.Curr->verts);
		glDrawElements(GL_QUADS, trailList.Curr->indices_count+1, GL_UNSIGNED_SHORT, trailList.Curr->indicies);
	}


Code: Select all

//store settings to restore after rendering done
	GLboolean isBlendOn		= glIsEnabled(GL_BLEND);
	GLboolean isCullFace	= glIsEnabled(GL_CULL_FACE);
	GLboolean isDepthTest	= glIsEnabled(GL_DEPTH_TEST);
	GLboolean isTexture2D	= glIsEnabled(GL_TEXTURE_2D);
	GLboolean isAlphaOn		= glIsEnabled(GL_ALPHA_TEST);
	GLboolean isLightingOn	= glIsEnabled(GL_LIGHTING);
	GLboolean isDepthWritable = false;
	GLint blendSrcAlpha = 0, blendDstAlpha = 0;
	glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha);
	glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDstAlpha);
	glGetBooleanv(GL_DEPTH_WRITEMASK, &isDepthWritable);
	GLint textureModeEnv = 0;
	glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &textureModeEnv);
	GLint alphaTestFunc = 0;
	GLfloat alphaRef = 0.0f;
	glGetIntegerv(GL_ALPHA_TEST_FUNC, &alphaTestFunc);
	glGetFloatv(GL_ALPHA_TEST_REF, &alphaRef);
	//store settings to restore after rendering done

	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GEQUAL, 0.01f);
	glEnable(GL_TEXTURE_2D);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	if (!isBlendOn)
		glEnable(GL_BLEND);
	if (isLightingOn)
		glDisable(GL_LIGHTING);
	glDepthMask(GL_FALSE);
	
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_CULL_FACE);

	const video::ITexture* texture = trailMaterial.getTexture(0);
	if (texture) {
		glBindTexture(GL_TEXTURE_2D, static_cast<const video::COpenGLTexture*>(texture)->getOpenGLTextureName());
	}

	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

Code: Select all


//restore env
	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, textureModeEnv);
	glBlendFunc(blendSrcAlpha, blendDstAlpha);
	glAlphaFunc(alphaTestFunc, alphaRef);
	if (isDepthWritable)
		glDepthMask(GL_TRUE);
	if (!isDepthTest)
		glDisable(GL_DEPTH_TEST);
	if (isCullFace)
		glEnable(GL_CULL_FACE);
	if (!isBlendOn)
		glDisable(GL_BLEND);
	if (!isTexture2D)
		glDisable(GL_TEXTURE_2D);
	if (!isAlphaOn)
		glDisable(GL_ALPHA_TEST);
	if (isLightingOn)
		glEnable(GL_LIGHTING);

hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

It would be easier to port it to Irrlicht functions. Though you'll still need to know which parts of Irrlicht would do the same thing. But it looks possible without too much efforts.
doqkhanh
Posts: 158
Joined: Sat Mar 01, 2008 3:14 am
Location: Tokyo, Japan
Contact:

Post by doqkhanh »

hybrid wrote:It would be easier to port it to Irrlicht functions. Though you'll still need to know which parts of Irrlicht would do the same thing. But it looks possible without too much efforts.
Wow, I see. instead of using DirectX or OpenGL function, I can use some irrlicht data types and methods to make this cross platform.

Is that right? Thank you, Hybrid!
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, the first three are meshbuffer draw methods, the last two are material setup things. I didn't check which requirements the actual code fragments have, but it should be possible to put them into an Irrlicht scene node and make it cross platform that way.
timetokill
Posts: 74
Joined: Tue Jul 22, 2008 4:28 am
Location: Los Angeles

Post by timetokill »

In following the instructions provided by varmint, I seem to only get linker errors :(

Seems to be a problem with:

Code: Select all

static_cast<const video::COpenGLTexture*>(texture)->getOpenGLTextureName()
in render()
Adversus
Posts: 128
Joined: Sun Oct 05, 2008 10:58 pm
Contact:

Post by Adversus »

Did anyone ever port this completely to irrlicht?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

A different working motion trails packae is available in irrext.
detvog
Posts: 19
Joined: Sun Mar 02, 2008 8:49 am

Problem

Post by detvog »

I have a problem. I can't input this in irrlicht.
I become an error at compiling the sample. (main.cpp)

---> undefined reference to scene::CMotionTrailSceneNode.....

I have input the IMotionTrailSceneNode.h in irrlicht.h but what is wrong ?

I'am working with codeblocks.




Sorry for my bad english... :oops:
Radikalizm
Posts: 1215
Joined: Tue Jan 09, 2007 7:03 pm
Location: Leuven, Belgium

Re: Problem

Post by Radikalizm »

detvog wrote:I have a problem. I can't input this in irrlicht.
I become an error at compiling the sample. (main.cpp)

---> undefined reference to scene::CMotionTrailSceneNode.....

I have input the IMotionTrailSceneNode.h in irrlicht.h but what is wrong ?

I'am working with codeblocks.




Sorry for my bad english... :oops:
Just read your error code to find out what the problem is...
You probably didn't add the CMotionTrailSceneNode.h and CMotionTrailSceneNode.cpp to your project
detvog
Posts: 19
Joined: Sun Mar 02, 2008 8:49 am

Post by detvog »

This is the error message:


main.cpp|188|undefined reference to `irr::scene::CMotionTrailSceneNode::CMotionTrailSceneNode(irr::scene::ISceneNode*, irr::scene::ISceneManager*, int, irr::IrrlichtDevice*, irr::core::vector3d<float> const&, irr::core::vector3d<float> const&, irr::core::vector3d<float> const&)'|

I have no add CMotionTrailSceneNode.h and CMotionTrailSceneNode.cpp to my project.


Sorry for .....
Post Reply