Browse Source

Still working on the scenegraph. The scenegraph will compile but the renderer and main.cpp wont

Panagiotis Christopoulos Charitos 16 years ago
parent
commit
ae37b3861c

+ 4 - 14
src/main.cpp

@@ -36,14 +36,10 @@ skel_model_node_t* imp;
 point_light_t* point_lights[10];
 spot_light_t* projlights[2];
 
-skel_anim_t walk_anim;
 
-
-/*
-=======================================================================================================================================
-Init                                                                                                                                  =
-=======================================================================================================================================
-*/
+//=====================================================================================================================================
+// Init                                                                                                                               =
+//=====================================================================================================================================
 void Init()
 {
 	#if defined( _DEBUG_ )
@@ -86,7 +82,6 @@ void Init()
 	imp = new skel_model_node_t();
 	imp->Init( "models/imp/imp.smdl" );
 	imp->SetLocalTransformation( vec3_t( 0.0, 2.11, 0.0 ), mat3_t( euler_t(-m::PI/2, 0.0, 0.0) ), 0.7 );
-	imp->mesh_nodes[0]->skel_controller = new mesh_node_t::skel_controller_t();
 	imp->mesh_nodes[0]->skel_controller->skel_node->skel_anim_controller->skel_anim = rsrc::skel_anims.Load( "models/imp/walk.imp.anim" );
 	imp->mesh_nodes[0]->skel_controller->skel_node->skel_anim_controller->step = 0.8;
 
@@ -110,13 +105,8 @@ void Init()
 //=====================================================================================================================================
 int main( int /*argc*/, char* /*argv*/[] )
 {
-
 	Init();
 
-
-	//===================================================================================================================================
-	//                                                          MAIN LOOP                                                               =
-	//===================================================================================================================================
 	PRINT( "Entering main loop" );
 	int ticks = hndl::GetTicks();
 	do
@@ -168,7 +158,7 @@ int main( int /*argc*/, char* /*argv*/[] )
 		mover->rotation_lspace.Reorthogonalize();
 
 
-		scene::UpdateAllSkeletonNodes();
+		scene::UpdateAllControllers();
 		scene::UpdateAllWorldStuff();
 
 		r::Render( main_cam );

+ 13 - 0
src/scene/controller.cpp

@@ -0,0 +1,13 @@
+#include "controller.h"
+#include "scene.h"
+
+controller_t::controller_t( type_e type_ ): 
+	type(type_) 
+{
+	scene::RegisterController( this );
+}
+
+controller_t::~controller_t()
+{
+	scene::UnregisterController( this );
+}

+ 2 - 2
src/scene/controller.h

@@ -20,8 +20,8 @@ class controller_t
 	PROPERTY_R( type_e, type, GetType ) ///< Once the type is set nothing can change it
 
 	public:
-		controller_t( type_e type_ ): type(type_) {}
-		virtual ~controller_t() {}
+		controller_t( type_e type_ );
+		virtual ~controller_t();
 		virtual void Update( float time ) = 0;
 };
 

+ 1 - 1
src/scene/light.cpp

@@ -7,7 +7,7 @@
 //=====================================================================================================================================
 // Init                                                                                                                               =
 //=====================================================================================================================================
-void light_t::Init( iostream* iostream_ )
+void light_t::Init( const char* filename )
 {
 	light_mtl = rsrc::light_mtls.Load( filename );
 }

+ 4 - 9
src/scene/light.h

@@ -29,17 +29,12 @@ class light_mtl_t;
 class light_t: public node_t
 {
 	public:
-		enum types_e { LT_POINT, LT_SPOT };
+		enum type_e { LT_POINT, LT_SPOT };
 
-	PROPERTY_R( types_e, type, GetType );
-
-	friend class point_light_t;
-	friend class spot_light_t;
-
-	public:
-		light_mtl_t* light_mtl;
+		type_e type;
+		light_mtl_t* light_mtl; ///< Later we will add a controller
 	
-		light_t( types_e type_ ): node_t(NT_LIGHT), type(type_) {}
+		light_t( type_e type_ ): node_t(NT_LIGHT), type(type_) {}
 		void Init( const char* );
 		void Deinit();
 };

+ 2 - 0
src/scene/mesh_node.cpp

@@ -5,6 +5,8 @@
 #include "material.h"
 #include "skel_node.h"
 #include "skeleton.h"
+#include "skel_controller.h"
+#include "skel_anim_controller.h"
 
 
 //=====================================================================================================================================

+ 5 - 20
src/scene/mesh_node.h

@@ -3,39 +3,24 @@
 
 #include "common.h"
 #include "node.h"
-#include "controller.h"
 
 
-class mesh_node_t;
-class skel_node_t;
+class skel_controller_t;
 class mesh_t;
-
-
-/// Skeleton controller
-class skel_controller_t: public controller_t<mesh_node_t>
-{
-	public:
-		skel_node_t* skel_node;
-		mesh_node_t* mesh_node;
-
-		skel_controller_t( skel_node_t* skel_node_, mesh_node_t* mesh_node_ ):
-			skel_node( skel_node_ ),
-			mesh_node( mesh_node_ ) 
-		{}
-		void Update() {}
-};
+class material_t;
 
 
 /// Mesh node
 class mesh_node_t: public node_t
 {
 	public:
+		// resources
 		mesh_t* mesh;
 		material_t* material;
+		// controllers
 		skel_controller_t* skel_controller;
-
+		// funcs
 		mesh_node_t(): node_t(NT_MESH), skel_controller(NULL) {}
-
 		void Render();
 		void RenderDepth();
 		void Init( const char* filename );

+ 15 - 1
src/scene/node.cpp

@@ -2,7 +2,13 @@
 #include "node.h"
 #include "renderer.h"
 #include "collision.h"
-#include "scene.h"
+#include "controller.h"
+
+
+namespace scene
+{
+	extern void RegisterNode( node_t* );
+}
 
 
 //=====================================================================================================================================
@@ -24,6 +30,14 @@ void node_t::CommonConstructorCode()
 }
 
 
+//=====================================================================================================================================
+// ~node_t                                                                                                                            =
+//=====================================================================================================================================
+node_t::~node_t()
+{
+}
+
+
 //=====================================================================================================================================
 // UpdateWorldTransform                                                                                                               =
 //=====================================================================================================================================

+ 3 - 5
src/scene/node.h

@@ -1,8 +1,7 @@
 #ifndef _NODE_H_
 #define _NODE_H_
 
-#include "common.h"
-
+#include <memory>
 #include "common.h"
 #include "gmath.h"
 
@@ -45,8 +44,6 @@ class node_t
 		bvolume_t* bvolume_wspace;
 
 		bool is_group_node;
-		
-		vec_t<controller_t*> controllers;
 
 	// funcs
 	private:
@@ -54,7 +51,8 @@ class node_t
 		
 	public:
 		node_t( type_e type_ ): type(type_) { CommonConstructorCode(); }
-		virtual ~node_t() { /* ToDo */ };
+		node_t( type_e type_, node_t* parent ): type(type_) { CommonConstructorCode(); parent->AddChild(this); }
+		virtual ~node_t();
 		virtual void Render() = 0;
 		virtual void Init( const char* ) = 0; ///< Init using a script
 		virtual void Deinit() = 0;

+ 32 - 5
src/scene/scene.cpp

@@ -2,6 +2,9 @@
 #include "scene.h"
 #include "skel_node.h"
 #include "camera.h"
+#include "mesh_node.h"
+#include "light.h"
+#include "controller.h"
 
 namespace scene {
 
@@ -18,6 +21,8 @@ container_camera_t     cameras;
 container_mesh_node_t  mesh_nodes;
 container_skel_node_t  skel_nodes;
 
+vec_t<controller_t*>   controllers;
+
 
 //=====================================================================================================================================
 // Static template funcs                                                                                                              =
@@ -92,6 +97,23 @@ void UnregisterNode( node_t* node )
 }
 
 
+//=====================================================================================================================================
+// Register and Unregister controllers                                                                                                =
+//=====================================================================================================================================
+void RegisterController( controller_t* controller )
+{
+	DEBUG_ERR( std::find( controllers.begin(), controllers.end(), controller ) != controllers.end() );
+	controllers.push_back( controller );
+}
+
+void UnregisterController( controller_t* controller )
+{
+	vec_t<controller_t*>::iterator it = std::find( controllers.begin(), controllers.end(), controller );
+	DEBUG_ERR( it == controllers.end() );
+	controllers.erase( it );
+}
+
+
 //=====================================================================================================================================
 // UpdateAllWorldStuff                                                                                                                =
 //=====================================================================================================================================
@@ -125,14 +147,19 @@ void UpdateAllWorldStuff()
 
 
 //=====================================================================================================================================
-// UpdateAllSkeletonNodes                                                                                                             =
+// UpdateAllCotrollers                                                                                                                =
 //=====================================================================================================================================
-void UpdateAllSkeletonNodes()
+void UpdateAllCotrollers()
 {
-	for( uint i=0; i<skel_nodes.size(); i++ )
+	/*for( container_node_t::iterator it=nodes.begin(); it!=nodes.end(); it++ )
 	{
-		skel_nodes[i]->skel_anim_controller->Update();
-	}
+		node_t* node = (*it);
+		for( vec_t<controller_t*>::iterator it1=node->controllers.begin(); it1!=node->controllers.end(); it1++ )
+			(*it1)->Update( 0.0 );
+	}*/
+	
+	for( vec_t<controller_t*>::iterator it=controllers.begin(); it!=controllers.end(); it++ )
+		(*it)->Update( 0.0 );
 }
 
 

+ 14 - 3
src/scene/scene.h

@@ -2,11 +2,17 @@
 #define _SCENE_H_
 
 #include "common.h"
-#include "light.h"
-#include "mesh_node.h"
 #include "skybox.h"
 
 
+class node_t;
+class light_t;
+class camera_t;
+class mesh_node_t;
+class skel_node_t;
+class controller_t;
+
+
 namespace scene {
 
 // misc
@@ -16,8 +22,11 @@ inline vec3_t GetAmbientColor() { return vec3_t( 0.1, 0.05, 0.05 )*1; }
 // funcs
 extern void RegisterNode( node_t* node );
 extern void UnregisterNode( node_t* node );
+extern void RegisterController( controller_t* controller );
+extern void UnregisterController( controller_t* controller );
+
 extern void UpdateAllWorldStuff();
-extern void UpdateAllSkeletonNodes();
+extern void UpdateAllCotrollers();
 
 
 // container_t
@@ -42,6 +51,8 @@ extern container_camera_t     cameras;
 extern container_mesh_node_t  mesh_nodes;
 extern container_skel_node_t  skel_nodes;
 
+extern vec_t<controller_t*>   controllers;
+
 
 } // end namespace
 #endif

+ 152 - 0
src/scene/skel_anim_controller.cpp

@@ -0,0 +1,152 @@
+#include "skel_anim_controller.h"
+#include "skel_anim.h"
+#include "skel_node.h"
+#include "skeleton.h"
+#include "renderer.h"
+
+
+//=====================================================================================================================================
+// Interpolate                                                                                                                        =
+//=====================================================================================================================================
+void skel_anim_controller_t::Interpolate( skel_anim_t* animation, float frame )
+{
+	DEBUG_ERR( frame >= skel_anim->frames_num );
+
+	// calculate the t (used in slerp and lerp) and
+	// calc the l_pose and r_pose witch indicate the pose ids in witch the frame lies between
+	const vec_t<uint>& keyframes = skel_anim->keyframes;
+	float t = 0.0;
+	uint l_pose = 0, r_pose = 0;
+	for( uint j=0; j<keyframes.size(); j++ )
+	{
+		if( (float)keyframes[j] == frame )
+		{
+			l_pose = r_pose = j;
+			t = 0.0;
+			break;
+		}
+		else if( (float)keyframes[j] > frame )
+		{
+			l_pose = j-1;
+			r_pose = j;
+			t = ( frame - (float)keyframes[l_pose] ) / float( keyframes[r_pose] - keyframes[l_pose] );
+			break;
+		}
+	}
+
+
+	// now for all bones update bone's poses
+	for( uint i=0; i<bone_rotations.size(); i++ )
+	{
+		const skel_anim_t::bone_anim_t& banim = skel_anim->bones[i];
+
+		mat3_t& local_rot = bone_rotations[i];
+		vec3_t& local_transl = bone_translations[i];
+
+		// if the bone has animations then slerp and lerp to find the rotation and translation
+		if( banim.keyframes.size() != 0 )
+		{
+			const skel_anim_t::bone_pose_t& l_bpose = banim.keyframes[l_pose];
+			const skel_anim_t::bone_pose_t& r_bpose = banim.keyframes[r_pose];
+
+			// rotation
+			const quat_t& q0 = l_bpose.rotation;
+			const quat_t& q1 = r_bpose.rotation;
+			local_rot = mat3_t( q0.Slerp(q1, t) );
+
+			// translation
+			const vec3_t& v0 = l_bpose.translation;
+			const vec3_t& v1 = r_bpose.translation;
+			local_transl = v0.Lerp( v1, t );
+		}
+		// else put the idents
+		else
+		{
+			local_rot = mat3_t::GetIdentity();
+			local_transl = vec3_t( 0.0, 0.0, 0.0 );
+		}
+	}
+}
+
+
+//=====================================================================================================================================
+// UpdateBoneTransforms                                                                                                               =
+//=====================================================================================================================================
+void skel_anim_controller_t::UpdateBoneTransforms()
+{
+	uint queue[ 128 ];
+	uint head = 0, tail = 0;
+
+	// put the roots
+	for( uint i=0; i<skel_node->skeleton->bones.size(); i++ )
+		if( skel_node->skeleton->bones[i].parent == NULL )
+			queue[tail++] = i; // queue push
+
+	// loop
+	while( head != tail ) // while queue not empty
+	{
+		uint bone_id = queue[head++]; // queue pop
+		const skeleton_t::bone_t& boned = skel_node->skeleton->bones[bone_id];
+
+		// bone.final_transform = MA * ANIM * MAi
+		// where MA is bone matrix at armature space and ANIM the interpolated transformation.
+		CombineTransformations( bone_translations[bone_id], bone_rotations[bone_id],
+		                        boned.tsl_skel_space_inv, boned.rot_skel_space_inv,
+		                        bone_translations[bone_id], bone_rotations[bone_id] );
+
+		CombineTransformations( boned.tsl_skel_space, boned.rot_skel_space,
+		                        bone_translations[bone_id], bone_rotations[bone_id],
+		                        bone_translations[bone_id], bone_rotations[bone_id] );
+
+		// and finaly add the parent's transform
+		if( boned.parent )
+		{
+			// bone.final_final_transform = parent.transf * bone.final_transform
+			CombineTransformations( bone_translations[boned.parent->id], bone_rotations[boned.parent->id],
+		                          bone_translations[bone_id], bone_rotations[bone_id],
+		                          bone_translations[bone_id], bone_rotations[bone_id] );
+		}
+
+		// now add the bone's childes
+		for( uint i=0; i<boned.childs_num; i++ )
+			queue[tail++] = boned.childs[i]->id;
+	}
+}
+
+
+//=====================================================================================================================================
+// Deform                                                                                                                             =
+//=====================================================================================================================================
+void skel_anim_controller_t::Deform()
+{
+	skeleton_t* skeleton = skel_node->skeleton;
+
+	for( uint i=0; i<skeleton->bones.size(); i++ )
+	{
+		const mat3_t& rot = bone_rotations[ i ];
+		const vec3_t& transl = bone_translations[ i ];
+
+		heads[i] = skeleton->bones[i].head.GetTransformed( transl, rot );
+		tails[i] = skeleton->bones[i].tail.GetTransformed( transl, rot );
+	}
+}
+
+
+//=====================================================================================================================================
+// Update                                                                                                                             =
+//=====================================================================================================================================
+void skel_anim_controller_t::Update( float )
+{
+	frame += step;
+	if( frame > skel_anim->frames_num ) // if the crnt is finished then play the next or loop the crnt
+	{
+		frame = 0.0;
+	}
+
+	Interpolate( skel_anim, frame );
+	UpdateBoneTransforms();
+	if( r::dbg::show_skeletons )
+	{
+		Deform();
+	}
+}

+ 36 - 0
src/scene/skel_anim_controller.h

@@ -0,0 +1,36 @@
+#ifndef _SKEL_ANIM_CONTROLLER_H_
+#define _SKEL_ANIM_CONTROLLER_H_
+
+#include "common.h"
+#include "controller.h"
+#include "gmath.h"
+
+class skeleton_t;
+class skel_anim_t;
+class skel_node_t;
+
+
+/// Skeleton animation controller
+class skel_anim_controller_t: public controller_t
+{
+	private:
+		void Interpolate( skel_anim_t* animation, float frame );
+		void UpdateBoneTransforms();
+		void Deform();
+
+	public:
+		skel_anim_t*  skel_anim; ///< Skeleton animation resource
+		skel_node_t*  skel_node;
+		vec_t<vec3_t> heads;
+		vec_t<vec3_t> tails;
+		vec_t<mat3_t> bone_rotations;
+		vec_t<vec3_t> bone_translations;
+		float step;
+		float frame;
+
+		skel_anim_controller_t( skel_node_t* skel_node_ ): controller_t(CT_SKEL_ANIM), skel_node( skel_node_ ) {}
+		void Update( float time );
+};
+
+
+#endif

+ 36 - 0
src/scene/skel_controller.h

@@ -0,0 +1,36 @@
+#ifndef _SKEL_CONTROLLER_H_
+#define _SKEL_CONTROLLER_H_
+
+#include "common.h"
+#include "controller.h"
+
+
+class mesh_node_t;
+class skel_node_t;
+class mesh_t;
+
+
+/**
+ * Skeleton controller
+ * It controls a mesh node using a skeleton node and the skeleton node's controllers
+ */
+class skel_controller_t: public controller_t
+{
+	public:
+		skel_node_t* skel_node;
+		mesh_node_t* mesh_node;
+
+		skel_controller_t( skel_node_t* skel_node_, mesh_node_t* mesh_node_ ):
+			controller_t( CT_SKEL ),
+			skel_node( skel_node_ ),
+			mesh_node( mesh_node_ ) 
+		{}
+		/**
+		 * Do nothing! We use HW skinning so its not necessary to update anything in the mesh_node. 
+		 * The skel_node's controllers provide us with sufficient data to do the trick.
+		 */
+		void Update( float ) {}
+};
+
+
+#endif

+ 48 - 70
src/scene/skel_model_node.cpp

@@ -1,86 +1,64 @@
 #include "skel_model_node.h"
-#include "scanner.h"
 #include "parser.h"
+#include "skel_node.h"
+#include "skel_controller.h"
 
-
+/// Create a skel_node and N mesh_nodes that have a skel_controller
 void skel_model_node_t::Init( const char* filename )
 {
 	scanner_t scanner;
-	if( !scanner.LoadFile( filename ) ) return false;
-
+	if( !scanner.LoadFile( filename ) ) return;
 	const scanner_t::token_t* token;
 
-	do
-	{
-		token = &scanner.GetNextToken();
 
-		//** MESHES **
-		if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "MESHES_NUM" ) )
-		{
-			token = &scanner.GetNextToken();
-			if( token->code != scanner_t::TC_NUMBER || token->code != scanner_t::DT_INTEGER )
-			{
-				PARSE_ERR_EXPECTED( "integer" );
-				return false;
-			}
-			
-			mesh_nodes.resize( token->value.int_ );
+	//** SKELETON **
+	token = &scanner.GetNextToken();
+	if( !(token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "SKELETON" )) )
+	{
+		PARSE_ERR_EXPECTED( "identifier SKELETON" );
+		return;
+	}
+	
+	token = &scanner.GetNextToken();
+	if( token->code != scanner_t::TC_STRING )
+	{
+		PARSE_ERR_EXPECTED( "string" );
+		return;
+	}
+	
+	skel_node = new skel_node_t;
+	skel_node->Init( token->value.string );
+	AddChild( skel_node );
+	
+	//** MESHES **
+	token = &scanner.GetNextToken();
+	if( !(token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "MESHES_NUM" )) )
+	{
+		PARSE_ERR_EXPECTED( "identifier MESHES_NUM" );
+		return;
+	}
+		
+	token = &scanner.GetNextToken();
+	if( token->code != scanner_t::TC_NUMBER || token->type != scanner_t::DT_INT )
+	{
+		PARSE_ERR_EXPECTED( "integer" );
+		return;
+	}
 			
-			for( uint i=0; i<mesh_nodes.size(); ++i )
-			{
-				token = &scanner.GetNextToken();
-				if( token->code != scanner_t::TC_STRING )
-				{
-					PARSE_ERR_EXPECTED( "string" );
-					return false;
-				}
-				
-				mesh_nodes[i] = new mesh_node_t;
-				mesh_nodes[i]->Init( token->value.string );
-			}			
-		}
-
-		//** SKELETON **
-		else if( token->code == scanner_t::TC_IDENTIFIER && !strcmp( token->value.string, "SKELETON" ) )
-		{
-			if( skel_node )
-			{
-				PARSE_ERR( "skel_node allready set" );
-				return false;
-			}
-
-			token = &scanner.GetNextToken();
-			if( token->code != scanner_t::TC_STRING )
-			{
-				PARSE_ERR_EXPECTED( "string" );
-				return false;
-			}
+	mesh_nodes.resize( token->value.int_ );
 			
-			skel_node = new skel_node;
-			skel_node->Init( token->value.string );
-		}
-
-		//** EOF **
-		else if( token->code == scanner_t::TC_EOF )
-		{
-			break;
-		}
-
-		//** other crap **
-		else
-		{
-			PARSE_ERR_UNEXPECTED();
-			return false;
-		}
-	}while( true ); // end do
-
-
-	AddChild( skel_node );
 	for( uint i=0; i<mesh_nodes.size(); ++i )
 	{
+		token = &scanner.GetNextToken();
+		if( token->code != scanner_t::TC_STRING )
+		{
+			PARSE_ERR_EXPECTED( "string" );
+			return;
+		}
+				
+		mesh_nodes[i] = new mesh_node_t;
+		mesh_nodes[i]->Init( token->value.string );
 		skel_node->AddChild( mesh_nodes[i] );
-		mesh_nodes[i]->skel_controller = new skel_controller( skel_node, mesh_nodes[i] );
+		mesh_nodes[i]->skel_controller = new skel_controller_t( skel_node, mesh_nodes[i] );
 	}
-	
-	return true;
 }

+ 2 - 2
src/scene/skel_model_node.h

@@ -6,7 +6,7 @@
 
 
 class mesh_node_t;
-class skel_node
+class skel_node_t;
 
 
 /** 
@@ -22,7 +22,7 @@ class skel_model_node_t: public node_t
 		skel_model_node_t(): node_t(NT_SKEL_MODEL), skel_node(NULL) { is_group_node = true; }
 		void Init( const char* filename );
 		void Deinit() {} ///< Do nothing because it loads no resources
-		void Render() {}
+		void Render() {} ///< Do nothing
 };
 
 #endif

+ 11 - 0
src/scene/skel_node.cpp

@@ -2,6 +2,17 @@
 #include "renderer.h"
 #include "skel_anim.h"
 #include "skeleton.h"
+#include "skel_anim_controller.h"
+
+
+//=====================================================================================================================================
+// skel_node_t                                                                                                                        =
+//=====================================================================================================================================
+skel_node_t::skel_node_t(): 
+	node_t( NT_SKELETON )
+{
+	skel_anim_controller = new skel_anim_controller_t(this); // It allways have a controller
+}
 
 
 //=====================================================================================================================================

+ 6 - 3
src/scene/skel_node.h

@@ -6,15 +6,18 @@
 #include "controller.h"
 #include "gmath.h"
 
+class skeleton_t;
+class skel_anim_controller_t;
+
 
 /// Skeleton node
 class skel_node_t: public node_t
 {
 	public:
-		skeleton_t* skeleton;
-		skel_anim_controller_t* skel_anim_controller;
+		skeleton_t* skeleton; ///< The skeleton resource
+		skel_anim_controller_t* skel_anim_controller; ///< Hold the controller here as well
 
-		skel_node_t(): node_t( NT_SKELETON ) {}
+		skel_node_t();
 		void Render();
 		void Init( const char* filename );
 		void Deinit();

+ 18 - 0
src/scene/trf_controller.h

@@ -0,0 +1,18 @@
+#ifndef _TRF_CONTROLLER_H_
+#define _TRF_CONTROLLER_H_
+
+#include "common.h"
+#include "controller.h"
+
+
+/// Transform controller
+class trf_controller_t: public controller_t
+{
+	public:
+		node_t* node;
+	
+		trf_controller_t( node_t* node_ ): controller_t( CT_TRF ), node(node_) {}
+		void Update( float ) { /* ToDo */ }
+};
+
+#endif