flow

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
radubolovan
Posts: 60
Joined: Tue Nov 13, 2007 7:03 pm
Location: Bucharest - Romania
Contact:

flow

Post by radubolovan »

I've realised some flow improvements. Well ... it's my opinion.
First of all you should separate the ISceneManager::drawAll() function in two:
1) ISceneManager::update( float fDeltaTime );
2) ISceneManager::drawAll();
as below:

Code: Select all

void CSceneManager::update()
{
	// reset attributes
	Parameters.setAttribute ( "culled", 0 );
	Parameters.setAttribute ( "calls", 0 );
	Parameters.setAttribute ( "drawn", 0 );

	// reset all transforms
	video::IVideoDriver* driver = getVideoDriver();
	if ( driver )
	{
		core::matrix4 identity;
		driver->setTransform ( video::ETS_PROJECTION, identity );
		driver->setTransform ( video::ETS_VIEW, identity );
		driver->setTransform ( video::ETS_WORLD, identity );
		driver->setTransform ( video::ETS_TEXTURE_0, identity );
		driver->setTransform ( video::ETS_TEXTURE_1, identity );
		driver->setTransform ( video::ETS_TEXTURE_2, identity );
		driver->setTransform ( video::ETS_TEXTURE_3, identity );
	}

	u32 currentTime = os::Timer::getTime();
	/*
	char string[1024];
	sprintf( string, "current time: %d\n", currentTime );
	appendToDebugLog( DS_IRRLICHT_DEBUG_CHANNEL, string );
	//*/

	// do animations and other stuff.
	OnAnimate( currentTime );

	/*!
	First Scene Node for prerendering should be the active camera
	consistent Camera is needed for culling
	 */
	camWorldPos.set(0,0,0);
	if ( ActiveCamera )
	{
		ActiveCamera->OnRegisterSceneNode();
		camWorldPos = ActiveCamera->getAbsolutePosition();
	}

	// let all nodes register themselves
	OnRegisterSceneNode();

	u32 i; // new ISO for scoping problem in some compilers

	//render camera scenes
	{
		CurrentRendertime = ESNRP_CAMERA;
		for (i=0; i<CameraList.size(); ++i)
			CameraList[i]->render();

		CameraList.set_used(0);
	}
}
and

Code: Select all

void CSceneManager::drawAll()
{
	if (!Driver)
		return;

	u32 i; // new ISO for scoping problem in some compilers

	//render lights scenes
	{
		CurrentRendertime = ESNRP_LIGHT;

		Driver->deleteAllDynamicLights();

		Driver->setAmbientLight(AmbientLight);

		LightList.sort ();		// on distance to camera

		u32 maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount (), LightList.size () );
		for (i=0; i< maxLights; ++i)
			LightList[i].node->render();

		LightList.set_used(0);
	}

	// render skyboxes
	{
		CurrentRendertime = ESNRP_SKY_BOX;

		for (i=0; i<SkyBoxList.size(); ++i)
			SkyBoxList[i]->render();

		SkyBoxList.set_used(0);
	}


	// render default objects
	{
		CurrentRendertime = ESNRP_SOLID;
		SolidNodeList.sort(); // sort by textures

		for (i=0; i<SolidNodeList.size(); ++i)
			SolidNodeList[i].node->render();

		Parameters.setAttribute ( "drawn", (s32) SolidNodeList.size () );

		SolidNodeList.set_used(0);
	}

	// render shadows
	{
		CurrentRendertime = ESNRP_SHADOW;
		for (i=0; i<ShadowNodeList.size(); ++i)
			ShadowNodeList[i]->render();

		if (!ShadowNodeList.empty())
			Driver->drawStencilShadow(true,ShadowColor, ShadowColor,
				ShadowColor, ShadowColor);

		ShadowNodeList.set_used(0);
	}

	// render transparent objects.
	{
		CurrentRendertime = ESNRP_TRANSPARENT;
		TransparentNodeList.sort(); // sort by distance from camera

		for (i=0; i<TransparentNodeList.size(); ++i)
			TransparentNodeList[i].node->render();

		TransparentNodeList.set_used(0);
	}

	// render shader objects.
	{
		for ( u32 g = 0; g!= ESNRP_SHADER_10 - ESNRP_SHADER_0 + 1; ++g )
		{
			CurrentRendertime = (scene::E_SCENE_NODE_RENDER_PASS) (ESNRP_SHADER_0 + g);

			const u32 size = ShaderNodeList[g].size ();
			if ( 0 == size )
				continue;

			ShaderNodeList[g].sort(); // sort by textures
			for (i=0; i< size; ++i)
				ShaderNodeList[g][i].node->render();

			ShaderNodeList[g].set_used(0);
		}
	}

	clearDeletionList();

	CurrentRendertime = ESNRP_COUNT;
}
I'll give you some considerations: pausing!
if you make a

Code: Select all

bool m_bPaused;
a function

Code: Select all

inline void setPause( bool bPause ){ m_bPaused = bPause; }
and then in constructor:

Code: Select all

m_bPaused = false;
and in update function (at beginning):

Code: Select all

if( m_bPaused ) return;
will just freeze but the scene will still render! This is good for opening in game menus and pause the game ... let say that we have a game and want to change our weapon from an inventory ... we should pause the game but stii render the 3D scene behind 2d stuff(inventory).
About fDeltaTime ... it is the difference between 2 frames. It will also help with lerp motion. For example if I want to move a scene node from point a to point b but using smooth motion, I can use the function

Code: Select all

vector3df LerpValue( vector3df& current_point, vector3df& target_point, float fFactor )
{
    if( factor >= 1.0f )
       return target_point;
    return current_point * ( 1.0f - fFactor ) + target_point * fFactor );
}
And then assuming we have a

Code: Select all

void move( vector3df to_pos ){ m_targetPos = to_pos;}
the "object" will move smoothly from point a to point b using the function like this:

Code: Select all

m_pos = LerpValue( m_pos, m_targetPos, fDeltaTime * fSpeed );
SetPosition( m_pos );/* m_pos is the current position*/
Then the render function will render the "object: to the specific position.
That's all for now :) If you think that my ideeas are good I will continue.
Last edited by radubolovan on Fri Jan 18, 2008 11:14 pm, edited 1 time in total.
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

awesome!

just putting my post here so i can retrieve it later.
Image
Frosty Topaz
Posts: 107
Joined: Sat Nov 04, 2006 9:42 pm

Post by Frosty Topaz »

Why not just use the built in timer's pause ability? I believe animators use the timer to determine how much they move... so if it's stopped don't they stop as well? (Assuming you're using animators, and that any custom ones play nice with the timer)

And if the animator's don't use the timer... well why the heck don't they?!?!
Frosty Topaz
=========
It isn't easy being ice-encrusted aluminum silicate fluoride hydroxide...
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, the animators should pause when the timer stops. Moreover, rendering the scene with no changes just uses ressources which are not necessary. Just keep the image unchanged!
lerp functions are also available already, please check the API.
A split into several methods (which always need to be called) is not planned, instead we plan for a parameter whether to call the update or render stages of the drawAll call.
radubolovan
Posts: 60
Joined: Tue Nov 13, 2007 7:03 pm
Location: Bucharest - Romania
Contact:

Post by radubolovan »

And if you have objects that don't move using animations?
For example I've made a SunMoon class which draws textures(materials) for sun and moon at specific vertices and doesn't use the irrlicht animation system; the sun and the moon aren't meshes or derived from a irrlicht class. I'm not saying that irrlicht system isn't good; I'm saying that irrlicht system is a little bit limited. It doesn't give much flexibility.
Here is the update & draw functions of my cass:

Code: Select all

void DSSunMoon::update( float fDeltaTime )
{
	/* update time */
	m_fTime += fDeltaTime * m_fTimeSpeed;

	if( m_fTime >= 1.0f )
	{
		m_fTime = 0.0f;
		DSSunMoon::m_nSunIndex++;
		DSSunMoon::m_nMoonIndex++;
		if( DSSunMoon::m_nSunIndex == SECONDS_PER_DAY )
		{
			DSSunMoon::m_nSunIndex = 0;
			DSSunMoon::m_nMoonIndex = SECONDS_PER_DAY / 2;
		}

		m_sunPos = m_positions[DSSunMoon::m_nSunIndex];
		m_moonPos = m_positions[DSSunMoon::m_nMoonIndex];
	}

	/* update sun */
	m_sunTargetPos = LerpValues( m_sunTargetPos, m_sunPos, fDeltaTime );

	vector3df sunDir = (m_sunTargetPos - m_campos).normalize();
	vector3df sunProjective = sunDir; sunProjective.Y = 0.0f;
	sunProjective.normalize();
	vector3df dir1 = (sunDir.crossProduct( sunProjective )).normalize();
	vector3df dir2 = (sunDir.crossProduct( dir1 )).normalize();

	vector3df texNormal = (m_sunTargetPos + m_campos).normalize();

	m_sunVerices[0].Pos = m_sunTargetPos + dir1 * SUN_RADIUS + dir2 * SUN_RADIUS;
	m_sunVerices[1].Pos = m_sunTargetPos - dir1 * SUN_RADIUS + dir2 * SUN_RADIUS;
	m_sunVerices[2].Pos = m_sunTargetPos - dir1 * SUN_RADIUS - dir2 * SUN_RADIUS;
	m_sunVerices[3].Pos = m_sunTargetPos + dir1 * SUN_RADIUS - dir2 * SUN_RADIUS;

	m_sunVerices[0].Normal = texNormal;
	m_sunVerices[1].Normal = texNormal;
	m_sunVerices[2].Normal = texNormal;
	m_sunVerices[3].Normal = texNormal;

	/* update moon */
	m_moonTargetPos = LerpValues( m_moonTargetPos, m_moonPos, fDeltaTime );

	sunDir = (m_moonTargetPos - m_campos).normalize();
	sunProjective = sunDir; sunProjective.Y = 0.0f;
	sunProjective.normalize();
	dir1 = (sunDir.crossProduct( sunProjective )).normalize();
	dir2 = (sunDir.crossProduct( dir1 )).normalize();

	texNormal = (m_moonTargetPos + m_campos).normalize();

	m_moonVerices[0].Pos = m_moonTargetPos + dir1 * SUN_RADIUS + dir2 * SUN_RADIUS;
	m_moonVerices[1].Pos = m_moonTargetPos - dir1 * SUN_RADIUS + dir2 * SUN_RADIUS;
	m_moonVerices[2].Pos = m_moonTargetPos - dir1 * SUN_RADIUS - dir2 * SUN_RADIUS;
	m_moonVerices[3].Pos = m_moonTargetPos + dir1 * SUN_RADIUS - dir2 * SUN_RADIUS;

	m_moonVerices[0].Normal = texNormal;
	m_moonVerices[1].Normal = texNormal;
	m_moonVerices[2].Normal = texNormal;
	m_moonVerices[3].Normal = texNormal;
}

void DSSunMoon::draw()
{
	/* drawing the sun */
	DSScene::instance()->videoDriver()->setMaterial( m_sunMat );
	DSScene::instance()->videoDriver()->drawIndexedTriangleFan( m_sunVerices, 4, m_indices, 2 );

	/* drawing the moon */
	DSScene::instance()->videoDriver()->setMaterial( m_moonMat );
	DSScene::instance()->videoDriver()->drawIndexedTriangleFan( m_moonVerices, 4, m_indices, 2 );
}
I can't use that class with actual irrlicht, can I? I had to modify some of it. If you are intrested in my modifications; here are source code: http://websvn.darkstarlinux.ro/listing. ... s%2Fsrc%2F
It is Open Source :)
(In Linux) you can download from svn with command:
svn co svn://svn.darkstarlinux.ro/svnroot/projects/trunk/playground/dswheels
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

In that case your fDeltaTime will simply stay at 0.0f. hence also your nodes will be paused. You'd put this into onAnimate. You could also put the code into a scene node animator if sun and moon are meshes (do you use some kind of billboard?).
radubolovan
Posts: 60
Joined: Tue Nov 13, 2007 7:03 pm
Location: Bucharest - Romania
Contact:

Post by radubolovan »

It is only a texture (for sun) and one for moon (you can download the code from link below).
For smooth animatoin fDeltaTime is the difference between 2 frames... for example if I hav 86 FPS, then the fDeltaTime = 1/86 = 0.11, but can be changed from frame to frame. Then you can move an object from point a to point b WITHIN 2 seconds hardware independently.
It is only my opinion, of course, that this system is more efficiently.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

I understand your parameter. However, in Irrlicht it should be calculated by taking the difference from ITimer values. Hence, when the timer is paused, you won't get any difference (even though it will take some milliseconds to render a frame) and so the complete scene is paused. In case you want to use the system time to calculate the offset (or even worse some guessed FPS number) be warned that you will get inconsistencies with Irrlicht's state. But as said it's perfectly possible with Irrlicht's current setup (besides the multiple render thing, which is not yet done).
Post Reply