Here the patch:
Code:
Index: Makefile
===================================================================
--- Makefile   (revisión: 798)
+++ Makefile   (copia de trabajo)
@@ -7,9 +7,9 @@
 CC = gcc
 AR = ar
 RANLIB = ranlib
-SYSTEM_LIBS =  -lGL -lGLU -lXinerama -lm -ljpeg -lopenal -lalut -lvorbis -lvorbisfile -logg -lresolv -lcrypt -lz -lcurl -lxml2 -lGLEW
+SYSTEM_LIBS =  -lGL -lGLU -lXinerama -lm -ljpeg -lopenal -lalut -lvorbis -lvorbisfile -logg -lresolv -lcrypt -lz -lcurl -lxml2 -lGLEW -lcal3d
 OTHER_LIBS =  raydium/ode/ode/src/libode.a raydium/php/libs/libphp5.a
-INCLUDE_PATH =  -Iraydium/ode/include/ -Iraydium/php/ -Iraydium/php/include -Iraydium/php/main/ -Iraydium/php/Zend -Iraydium/php/TSRM -I/usr/include/curl
+INCLUDE_PATH =  -Iraydium/ode/include/ -Iraydium/php/ -Iraydium/php/include -Iraydium/php/main/ -Iraydium/php/Zend -Iraydium/php/TSRM -I/usr/include/curl -I/usr/include/
 LIBS_PATH =  -L/usr/X11R6/lib/
 CFLAGS=-W
 COMPILE_OPTIONS=-g -D LIBRAY
@@ -17,7 +17,7 @@
 LINKING_OPTIONS=-Wl,-soname,libraydium.so.0
 AR_OPTIONS=
 
-HEADERS=raydium/headers/background.h raydium/headers/callback.h raydium/headers/camera.h raydium/headers/capture.h raydium/headers/clear.h raydium/headers/console.h raydium/headers/file.h raydium/headers/file_tri.h raydium/headers/fog.h raydium/headers/init.h raydium/headers/cli.h raydium/headers/internal.h raydium/headers/joy.h raydium/headers/key.h raydium/headers/land.h raydium/headers/light.h raydium/headers/log.h raydium/headers/main.h raydium/headers/mouse.h raydium/headers/network.h raydium/headers/normal.h raydium/headers/object.h raydium/headers/ode.h raydium/headers/osd.h raydium/headers/parser.h raydium/headers/particle2.h raydium/headers/php.h raydium/headers/profile.h raydium/headers/random.h raydium/headers/rayphp.h raydium/headers/register.h raydium/headers/render.h raydium/headers/signal.h raydium/headers/sky.h raydium/headers/sound.h raydium/headers/texture.h raydium/headers/timecall.h raydium/headers/math.h raydium/headers/vertex.h raydium/headers/window.h raydium/headers/reg_api.h raydium/headers/gui.h raydium/headers/live.h raydium/headers/video.h raydium/headers/shadow.h raydium/headers/myglut.h raydium/headers/web.h raydium/headers/hdr.h raydium/headers/shader.h raydium/headers/atexit.h raydium/headers/path.h raydium/headers/sprites.h
+HEADERS=raydium/headers/background.h raydium/headers/callback.h raydium/headers/camera.h raydium/headers/capture.h raydium/headers/clear.h raydium/headers/console.h raydium/headers/file.h raydium/headers/file_tri.h raydium/headers/fog.h raydium/headers/init.h raydium/headers/cli.h raydium/headers/internal.h raydium/headers/joy.h raydium/headers/key.h raydium/headers/land.h raydium/headers/light.h raydium/headers/log.h raydium/headers/main.h raydium/headers/mouse.h raydium/headers/network.h raydium/headers/normal.h raydium/headers/object.h raydium/headers/ode.h raydium/headers/osd.h raydium/headers/parser.h raydium/headers/particle2.h raydium/headers/php.h raydium/headers/profile.h raydium/headers/random.h raydium/headers/rayphp.h raydium/headers/register.h raydium/headers/render.h raydium/headers/signal.h raydium/headers/sky.h raydium/headers/sound.h raydium/headers/texture.h raydium/headers/timecall.h raydium/headers/math.h raydium/headers/vertex.h raydium/headers/window.h raydium/headers/reg_api.h raydium/headers/gui.h raydium/headers/live.h raydium/headers/video.h raydium/headers/shadow.h raydium/headers/myglut.h raydium/headers/web.h raydium/headers/hdr.h raydium/headers/shader.h raydium/headers/atexit.h raydium/headers/path.h raydium/headers/sprites.h raydium/headers/anim.h
 
 OBJECTS      = $(HEADERS:raydium/headers/%.h=raydium/compile/%.o)
 
Index: anim-test1.c
===================================================================
--- anim-test1.c   (revisión: 0)
+++ anim-test1.c   (revisión: 0)
@@ -0,0 +1,213 @@
+/*
+    Raydium - CQFD Corp.
+    http://raydium.org/
+    Released under both BSD license and Lesser GPL library license.
+    See "license.txt" file.
+*/
+
+#include "raydium/index.c"
+
+int modelo,modelo2;
+int instancia,instancia2;
+float instancia2_walk=0;
+int instancia2_flag=0;
+int rendermesh=0;
+int renderskel=1;
+
+void display(void)
+{      
+   raydium_anim_instance_update(instancia,raydium_frame_time);
+   raydium_anim_instance_update(instancia2,raydium_frame_time);
+   
+   raydium_joy_key_emul();
+
+   //escape
+   if(raydium_key_last==1027)      exit(0);   
+   
+   //F7 capture screen
+   if(raydium_key_last==7)raydium_capture_frame_auto();
+   //switch meshes
+   if(raydium_key_last==1)rendermesh=rendermesh?0:1;
+   //switch skel
+   if(raydium_key_last==2)renderskel=renderskel?0:1;
+   //meshes attachment
+   if(raydium_key_last==3)
+   {
+      raydium_anim_instance_attach_meshes(instancia);
+      raydium_anim_instance_attach_meshes(instancia2);
+   }
+   //materials apply
+   if(raydium_key_last==4)
+   {
+      raydium_anim_model_materials_apply(instancia,0);
+      raydium_anim_model_materials_apply(instancia2,0);
+   }   
+   //LOD setting
+   if(raydium_key_last==5)
+   {
+      raydium_anim_model_lod_set(instancia,0.05);
+      raydium_anim_model_lod_set(instancia2,0.05);
+   }
+   if(raydium_key_last==6)
+   {
+      raydium_anim_model_lod_set(instancia,1);
+      raydium_anim_model_lod_set(instancia2,1);
+   }
+   
+   //loop
+   if(raydium_key_last==1000+'1')
+   {
+      //remove actions
+      raydium_anim_action_remove(instancia,1);
+      raydium_anim_action_remove(instancia,5);         
+      raydium_anim_action_remove(instancia2,2);
+      //clear loops
+      raydium_anim_loop_clear(instancia,0,0.5);
+      raydium_anim_loop_clear(instancia,1,0.5);
+      raydium_anim_loop_clear(instancia,2,0.5);
+      raydium_anim_loop_clear(instancia,3,0.5);
+      raydium_anim_loop_clear(instancia,4,0.5);
+      raydium_anim_loop_clear(instancia,5,0.5);
+      raydium_anim_loop_clear(instancia2,1,3);
+      //setup loops
+      raydium_anim_loop_set(instancia,3,1,3);      
+      raydium_anim_loop_set(instancia2,0,1,3);         
+   }
+   //loop
+   if(raydium_key_last==1000+'2')
+   {
+      //remove actions
+      raydium_anim_action_remove(instancia,1);
+      raydium_anim_action_remove(instancia,5);         
+      raydium_anim_action_remove(instancia2,2);         
+      //clear loops      
+      raydium_anim_loop_clear(instancia,0,0.5);
+      raydium_anim_loop_clear(instancia,1,0.5);
+      raydium_anim_loop_clear(instancia,2,0.5);
+      raydium_anim_loop_clear(instancia,3,0.5);
+      raydium_anim_loop_clear(instancia,4,0.5);
+      raydium_anim_loop_clear(instancia,5,0.5);
+      raydium_anim_loop_clear(instancia2,0,3);
+      //set up loops
+      raydium_anim_loop_set(instancia,4,1,3);            
+      raydium_anim_loop_set(instancia2,1,1,3);      
+   }
+      //loop
+   if(raydium_key_last==1000+'3')
+   {
+      //remove actions
+      raydium_anim_action_remove(instancia,1);
+      raydium_anim_action_remove(instancia,5);         
+      raydium_anim_action_remove(instancia2,2);         
+      //clear loops      
+      raydium_anim_loop_clear(instancia,0,0.5);
+      raydium_anim_loop_clear(instancia,1,0.5);
+      raydium_anim_loop_clear(instancia,2,0.5);
+      raydium_anim_loop_clear(instancia,3,0.5);
+      raydium_anim_loop_clear(instancia,4,0.5);
+      raydium_anim_loop_clear(instancia2,0,3);
+      //set up loops
+      raydium_anim_loop_set(instancia,0,1,3);            
+         
+   }
+   //loop
+   if(raydium_key_last==1000+'4')
+   {
+      //remove actions
+      raydium_anim_action_remove(instancia,1);
+      raydium_anim_action_remove(instancia,5);         
+      raydium_anim_action_remove(instancia2,2);         
+      //clear loops      
+      raydium_anim_loop_clear(instancia,0,0.5);
+      raydium_anim_loop_clear(instancia,1,0.5);
+      raydium_anim_loop_clear(instancia,2,0.5);
+      raydium_anim_loop_clear(instancia,3,0.5);
+      raydium_anim_loop_clear(instancia,4,0.5);
+      raydium_anim_loop_clear(instancia,5,0.5);   
+      //launch action
+      raydium_anim_action_set(instancia,5,0.5f, 0.1f, 0);      
+            
+   }
+   //action   
+   if(raydium_key_last==1000+'5')
+   {
+      raydium_anim_loop_clear(instancia,3,0.3);
+      raydium_anim_loop_clear(instancia,4,0.3);
+      raydium_anim_action_set(instancia,1,1.0f, 0.3f, 1);   
+      raydium_anim_loop_clear(instancia2,1,0.3);            
+      raydium_anim_loop_clear(instancia2,0,0.3);
+      raydium_anim_action_set(instancia2,2,1.0f, 0.3f, 1);      
+   }
+   
+   
+   raydium_clear_frame();
+   raydium_camera_orbitmove(0,0,0.5);
+   
+   raydium_ode_draw_all(0);
+   
+   //render instances   
+   if(rendermesh)
+   {
+   raydium_anim_instance_render(instancia,1);
+   raydium_anim_instance_render(instancia2,1);      
+   }
+   if(renderskel)
+   {
+   raydium_anim_instance_render(instancia,2);
+   raydium_anim_instance_render(instancia2,2);      
+   }
+   raydium_osd_printf(5,5,14,0.45,"bitstream.tga","Elapsed time: %5.5f",raydium_frame_time);   
+   raydium_osd_printf(5,95,15,0.45,"bitstream.tga","F1: switch Render Mesh");   
+   raydium_osd_printf(5,92,15,0.45,"bitstream.tga","F2: switch Render Skeleton");
+   raydium_osd_printf(5,89,15,0.45,"bitstream.tga","F3: Aplly meshes (needed to mesh render)");
+   raydium_osd_printf(5,86,15,0.45,"bitstream.tga","F4: Aplly materials/textures");
+   raydium_osd_printf(5,83,15,0.45,"bitstream.tga","F5: LOD(level of detail) 10%% for \"paladin\"");
+   raydium_osd_printf(5,80,15,0.45,"bitstream.tga","F6: LOD(level of detail) 100%% for \"paladin\"");
+   raydium_osd_printf(5,77,15,0.45,"bitstream.tga","F7: Screen capture");
+   raydium_osd_printf(5,74,15,0.45,"bitstream.tga","1,2,3,4,5: Various animation loops/actions");
+
+   raydium_rendering_finish();
+}
+
+
+int main(int argc, char **argv)
+{
+raydium_init_args(argc,argv);
+raydium_window_create(800,600,RAYDIUM_RENDERING_WINDOW,"Cal3D Animation test 1");
+
+raydium_texture_filter_change(RAYDIUM_TEXTURE_FILTER_TRILINEAR);
+raydium_window_view_perspective(60,0.01,2500); // fov 60 + near and far planes
+
+raydium_fog_disable();    
+raydium_light_enable();
+raydium_light_on(0);
+
+raydium_light_conf_7f(0,50,150,200,1000000,1,0.9,0.7); // id, pos, intensity and color (RGB)
+raydium_background_color_change(1,0.9,0.7,1);
+
+raydium_sky_box_cache();
+raydium_anim_init();
+raydium_ode_ground_set_name("cocorobix.tri");
+
+//loading models
+raydium_log("Stating models load...");
+modelo=raydium_anim_model_load("paladin.cfg");
+modelo2=raydium_anim_model_load("trooper.cfg");
+raydium_log("End of model load.");
+//creating instances
+instancia=raydium_anim_instance_new(modelo);
+instancia2=raydium_anim_instance_new(modelo2);
+//placing/rotating instances
+raydium_anim_instance_move(instancia,0,-1,-1.28);
+raydium_anim_instance_rotate(instancia,140,0,0);
+raydium_anim_instance_move(instancia2,0,1,-1.3);
+raydium_anim_instance_rotate(instancia2,110,0,0);
+
+
+raydium_callback(&display);
+raydium_anim_instances_destroy();
+raydium_anim_models_destroy();
+return(0);
+}
+
+// EOF
Index: raydium/init.c
===================================================================
--- raydium/init.c   (revisión: 798)
+++ raydium/init.c   (copia de trabajo)
@@ -95,6 +95,7 @@
 raydium_osd_fade_init();
 raydium_console_init();
 raydium_gui_init();
+raydium_anim_init();
 //#ifndef WIN32
 raydium_live_init();
 //#endif
@@ -290,6 +291,7 @@
 raydium_sound_init();
 raydium_viewport_init();
 raydium_callback_set();
+raydium_anim_init();
 #ifdef PHP_SUPPORT
 raydium_php_init();
 #endif
Index: raydium/anim.c
===================================================================
--- raydium/anim.c   (revisión: 0)
+++ raydium/anim.c   (revisión: 0)
@@ -0,0 +1,836 @@
+/*
+    Raydium - CQFD Corp.
+    http://raydium.org/
+    Released under both BSD license and Lesser GPL library license.
+    See "license.txt" file.
+*/
+
+#ifndef DONT_INCLUDE_HEADERS
+#include "index.h"
+#else
+#include "headers/anim.h"
+#endif
+
+//TODO: dont place these here
+#define RAYDIUM_ANIM_MAX_ANIMATIONS 32
+#define RAYDIUM_ANIM_MAX_INSTANCES 16
+#define RAYDIUM_ANIM_MAX_MESHES 30
+#define RAYDIUM_ANIM_MAX_MATERIALS 30
+
+//usage of coremodels
+int raydium_anim_model_use   [RAYDIUM_ANIM_MAX_MODELS];
+int raydium_anim_animations   [RAYDIUM_ANIM_MAX_MODELS];
+int raydium_anim_meshes      [RAYDIUM_ANIM_MAX_MODELS];
+int raydium_anim_materials  [RAYDIUM_ANIM_MAX_MODELS];
+int raydium_anim_animationid   [RAYDIUM_ANIM_MAX_MODELS][RAYDIUM_ANIM_MAX_ANIMATIONS];
+int raydium_anim_instance_use   [RAYDIUM_ANIM_MAX_INSTANCES];
+int raydium_anim_instance_model   [RAYDIUM_ANIM_MAX_INSTANCES];
+int raydium_anim_mesh_use   [RAYDIUM_ANIM_MAX_MESHES];
+int raydium_anim_meshid      [RAYDIUM_ANIM_MAX_MODELS][RAYDIUM_ANIM_MAX_MESHES];
+int raydium_anim_material_use   [RAYDIUM_ANIM_MAX_MESHES];
+int raydium_anim_materialid      [RAYDIUM_ANIM_MAX_MODELS][RAYDIUM_ANIM_MAX_MATERIALS];
+float raydium_anim_instance_pos_rot[RAYDIUM_ANIM_MAX_INSTANCES][6];
+
+//instances
+struct CalModel *raydium_anim_instance[RAYDIUM_ANIM_MAX_INSTANCES];
+//coremodels
+struct CalCoreModel *raydium_anim_model[RAYDIUM_ANIM_MAX_MODELS]; 
+//instances, beware with the non-friendly name
+struct CalModel* model;
+
+/*********************************************************************/
+/*******************  ANIM FUNCTIONS           ***********************/
+/*********************************************************************/
+   
+void raydium_anim_init(void)
+{
+   int a,b;
+   for(a=0;a<RAYDIUM_ANIM_MAX_MODELS;a++)
+   {
+      raydium_anim_model_use[a]=0;
+      raydium_anim_animations[a]=0;
+      raydium_anim_meshes[a]=0;
+      for(b=0;b<RAYDIUM_ANIM_MAX_ANIMATIONS;b++)
+      {
+         raydium_anim_animationid[a][b]=-1;
+      }
+      for(b=0;b<RAYDIUM_ANIM_MAX_MESHES;b++)
+      {         
+         raydium_anim_meshid[a][b]=-1;
+      }
+      for(b=0;b<RAYDIUM_ANIM_MAX_MATERIALS;b++)
+      {
+         raydium_anim_materialid[a][b]=-1;
+      }
+   }
+   for(a=0;a<RAYDIUM_ANIM_MAX_INSTANCES;a++)
+   {
+      raydium_anim_instance_use[a]=0;
+      raydium_anim_instance[a]=NULL;
+      raydium_anim_instance_model[a]=-1;
+      raydium_anim_instance_pos_rot[a][0]=0;
+      raydium_anim_instance_pos_rot[a][1]=0;
+      raydium_anim_instance_pos_rot[a][2]=0;
+      raydium_anim_instance_pos_rot[a][3]=0;
+      raydium_anim_instance_pos_rot[a][4]=0;
+      raydium_anim_instance_pos_rot[a][5]=0;
+   }
+   for(a=0;a<RAYDIUM_ANIM_MAX_MESHES;a++)
+   {
+      raydium_anim_mesh_use[a]=0;      
+   }
+   for(a=0;a<RAYDIUM_ANIM_MAX_MATERIALS;a++)
+   {
+      raydium_anim_material_use[a]=0;      
+   }
+   //TODO:This path_Ext be placed here?
+   raydium_path_ext("./data/anims/","cfg");   
+}
+void raydium_anim_model_destroy(int a)
+{   
+   CalCoreModel_Delete(raydium_anim_model[a]);
+   //WARNING:!!!
+   raydium_log("CAL3D:The instances using this model should be already destroy");   
+}
+void raydium_anim_models_destroy(void)
+{
+   int a;
+   for(a=0;a<RAYDIUM_ANIM_MAX_MODELS;a++)
+   {
+      if(raydium_anim_model_use[a])
+      {
+         raydium_anim_model_destroy(a);
+      }
+   }
+}
+int raydium_anim_model_load(char *filename)
+{
+   int a;
+   for(a=0;a<RAYDIUM_ANIM_MAX_MODELS;a++)
+   {
+      if(raydium_anim_model_use[a]==0)
+      {         
+         #ifdef RAYDIUM_ANIM_CAL3D
+         raydium_log("using cal3d specifics");
+         //raydium_anim_cal3d_model_load_internal return (int)boolean
+         if(raydium_anim_cal3d_model_load_internal(a,filename))
+            {
+            raydium_anim_model_use[a]=1;
+            return a;         
+            }         
+         #endif
+         break;
+      }
+   }
+   return -1;
+}
+void raydium_anim_instance_destroy(int instance)
+{
+   if(raydium_anim_instance_use[instance])
+   {
+      raydium_anim_cal3d_instance_destroy(instance);
+   }   
+}
+void raydium_anim_instances_destroy()
+{
+   int a;
+   for(a=0;a<RAYDIUM_ANIM_MAX_INSTANCES;a++)
+   {
+      raydium_anim_instance_destroy(a);
+   }
+}
+int raydium_anim_instance_new(int model)
+{
+   int a;
+   for(a=0;a<RAYDIUM_ANIM_MAX_INSTANCES;a++)
+   {
+      if(raydium_anim_instance_use[a]==0)
+      {         
+         if(raydium_anim_cal3d_instance_new_internal(a,model))
+         {
+            raydium_anim_instance_use[a]=1;
+            raydium_anim_instance_model[a]=model;
+            raydium_log("Created a new instance(%d) of model %d",a,model);
+            
+            return a;
+         }
+         else
+         {
+            raydium_log("ANIM:ERROR: creating instance %d",a);
+            return -1;
+         }
+      }
+   }
+   return -1;
+}
+void raydium_anim_instance_attach_meshes(int instance)
+{
+   if(!raydium_anim_instance_use[instance])
+   {
+      raydium_log("ANIM:ERROR: Instance index %d not valid. ",instance);
+   }
+   else
+   {
+      raydium_anim_cal3d_instance_attach_meshes(instance);
+   }
+}
+void raydium_anim_instance_render_skeleton(int instance)
+{
+   if(raydium_anim_instance_use[instance])
+      raydium_anim_cal3d_instance_render_skeleton(instance);
+   else
+      raydium_log("ANIM:ERROR: Not such instance %d. Nothing to render.",instance);
+}
+void raydium_anim_instance_update(int instance,float delta_time)
+{
+   if(raydium_anim_instance_use[instance] && delta_time>=0.0f)
+      raydium_anim_cal3d_instance_update(instance,delta_time);
+}
+void raydium_anim_animation_scale(int model,int animation,float scale)
+{
+   if(raydium_anim_model_use[model])
+      raydium_anim_cal3d_animation_scale(model,animation,scale);
+   else
+      raydium_log("ANIM:ERROR: Invalid model index");
+}
+void raydium_anim_skeleton_scale(int model,float scale)
+{
+   if(raydium_anim_model_use[model])
+      raydium_anim_cal3d_skeleton_scale( model, scale);
+}
+void raydium_anim_loop_set(int instance,int animation, float influence, float delay_seconds)
+{   
+   raydium_anim_cal3d_loop_set( instance, animation, influence, delay_seconds);
+}
+void raydium_anim_action_remove(int instance,int animation)
+{
+   raydium_anim_cal3d_action_remove(instance,animation);
+}
+void raydium_anim_instance_render(int instance, int type)
+{
+   glPushMatrix();
+   glTranslatef(   raydium_anim_instance_pos_rot[instance][0],
+               raydium_anim_instance_pos_rot[instance][1],
+               raydium_anim_instance_pos_rot[instance][2]);
+   glRotatef(   raydium_anim_instance_pos_rot[instance][3],0,0,1);
+   glRotatef(   raydium_anim_instance_pos_rot[instance][4],0,1,0);
+   glRotatef(   raydium_anim_instance_pos_rot[instance][5],1,0,0);
+   
+   switch(type)
+   {
+      case RAYDIUM_ANIM_RENDER_NONE:
+         //do nothing
+      break;
+      case RAYDIUM_ANIM_RENDER_MESH:
+         raydium_anim_instance_render_mesh(instance);
+      break;
+      case RAYDIUM_ANIM_RENDER_SKELETON:
+         raydium_anim_instance_render_skeleton(instance);
+      break;
+   }
+   glPopMatrix();   
+}
+void raydium_anim_instance_move(int instance,float x, float y, float z)
+{
+   if(raydium_anim_instance_use[instance])
+   {
+      raydium_anim_instance_pos_rot[instance][0]=x;
+      raydium_anim_instance_pos_rot[instance][1]=y;      
+      raydium_anim_instance_pos_rot[instance][2]=z;   
+   }      
+}
+void raydium_anim_instance_move_relative(int instance,float x, float y, float z)
+{
+   if(raydium_anim_instance_use[instance])
+   {
+      raydium_anim_instance_pos_rot[instance][0]+=x;
+      raydium_anim_instance_pos_rot[instance][1]+=y;      
+      raydium_anim_instance_pos_rot[instance][2]+=z;   
+   }      
+}
+void raydium_anim_instance_rotate(int instance,float x, float y, float z)
+{
+   if(raydium_anim_instance_use[instance])
+   {
+      raydium_anim_instance_pos_rot[instance][3]=x;
+      raydium_anim_instance_pos_rot[instance][4]=y;      
+      raydium_anim_instance_pos_rot[instance][5]=z;   
+   }      
+}
+void raydium_anim_instance_rotate_relative(int instance,float x, float y, float z)
+{
+   if(raydium_anim_instance_use[instance])
+   {
+      raydium_anim_instance_pos_rot[instance][3]+=x;
+      raydium_anim_instance_pos_rot[instance][4]+=y;      
+      raydium_anim_instance_pos_rot[instance][5]+=z;   
+   }      
+}
+
+void raydium_anim_instance_render_mesh(int instance)
+{
+   if(raydium_anim_instance_use[instance])
+      raydium_anim_cal3d_instance_render_mesh(instance);
+   else
+      raydium_log("ANIM:ERROR: Invalid instance index.");
+}
+void raydium_anim_model_materials_apply(int instance, int set)
+{
+   raydium_anim_cal3d_model_materials_apply(instance,set);
+}
+void raydium_anim_model_lod_set(int instance, float lod_level)
+{
+   raydium_anim_cal3d_model_lod_set(instance,lod_level);
+}
+void raydium_anim_action_set(int instance,int animation, float fadein_seconds, float fadeout_seconds, int autolock)
+{
+   raydium_anim_cal3d_action_set(instance,animation, fadein_seconds, fadeout_seconds,autolock);
+}
+void raydium_anim_loop_clear(int instance,int animation, float delay_seconds)
+{
+   raydium_anim_cal3d_loop_clear(instance,animation, delay_seconds);
+}
+
+/*********************************************************************/
+/*******************  CAL3D FUNCTIONS           **********************/
+/*********************************************************************/
+
+void raydium_anim_cal3d_instance_render_skeleton(int instance)
+{
+float lines[1024][2][3];
+int nrLines;
+float points[1024][3];
+int nrPoints;
+struct CalSkeleton *tmpskel;
+if(!raydium_anim_instance_use[instance])
+   {
+   raydium_log("ANIM:ERROR: Instance index %d not valid. ",instance);
+   }
+else
+   {
+   // draw the bone lines
+   //tmpskel=(struct CalSkeleton *)CalModel_GetSkeleton(raydium_anim_instance[instance]);
+   //nrLines=CalSkeleton_GetBoneLines(tmpskel,&lines[0][0][0]);
+   nrLines=CalSkeleton_GetBoneLines(CalModel_GetSkeleton(raydium_anim_instance[instance]),&lines[0][0][0]);
+
+   glLineWidth(3.0f);
+   glColor3f(1.0f, 1.0f, 1.0f);
+   glBegin(GL_LINES);
+   int currLine;
+   for(currLine = 0; currLine < nrLines; currLine++)
+      {
+      glVertex3f(lines[currLine][0][0], lines[currLine][0][1], lines[currLine][0][2]);
+      glVertex3f(lines[currLine][1][0], lines[currLine][1][1], lines[currLine][1][2]);
+      }
+   glEnd();
+   glLineWidth(1.0f);
+
+   // draw the bone points
+   nrPoints = CalSkeleton_GetBonePoints(CalModel_GetSkeleton(raydium_anim_instance[instance]),&points[0][0]);
+
+   glPointSize(4.0f);
+   glBegin(GL_POINTS);
+   glColor3f(0.0f, 0.0f, 1.0f);
+   int currPoint;
+   for(currPoint = 0; currPoint < nrPoints; currPoint++)
+      {
+      glVertex3f(points[currPoint][0], points[currPoint][1], points[currPoint][2]);
+      }
+   glEnd();
+   glPointSize(1.0f);
+   }
+}
+
+void raydium_anim_cal3d_instance_update(int instance,float delta_time)
+{   
+   if(raydium_anim_instance_use[instance] && delta_time>0.0f)
+      CalModel_Update(raydium_anim_instance[instance],delta_time);
+}
+
+void raydium_anim_cal3d_animation_scale(int model,int animation,float scale)
+{   
+   if(raydium_anim_model_use[model])
+      CalCoreAnimation_Scale(CalCoreModel_GetCoreAnimation(raydium_anim_model[model],animation),scale);
+   else
+      raydium_log("ANIM:ERROR: Invalid model index");
+}
+
+void raydium_anim_cal3d_skeleton_scale(int model,float scale)
+{
+   if(raydium_anim_model_use[model])
+      CalCoreSkeleton_Scale(CalCoreModel_GetCoreSkeleton(raydium_anim_model[model]),(float)scale);
+   else
+      raydium_log("ANIM:ERROR: Invalid model index");
+}
+
+void raydium_anim_cal3d_instance_render_mesh(int instance)
+{
+   if(raydium_anim_instance[instance])
+   {      
+      int bWireframe=0;
+      // get the renderer of the model
+      struct CalRenderer *pCalRenderer;      
+      pCalRenderer = CalModel_GetRenderer(raydium_anim_instance[instance]);
+
+      // begin the rendering loop      
+      if(!CalRenderer_BeginRendering(pCalRenderer)) return;
+
+      // set wireframe mode if necessary
+      if(bWireframe)
+      {
+         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+      }
+
+      // set the global OpenGL states
+      //glEnable(GL_DEPTH_TEST);
+      glShadeModel(GL_SMOOTH);
+      
+
+      // we will use vertex arrays, so enable them
+      glEnableClientState(GL_VERTEX_ARRAY);
+      glEnableClientState(GL_NORMAL_ARRAY);
+
+      // get the number of meshes
+      int meshCount;      
+      meshCount = CalRenderer_GetMeshCount(pCalRenderer);
+
+      // render all meshes of the model
+      int meshId;
+      for(meshId = 0; meshId < meshCount; meshId++)
+         {
+         // get the number of submeshes
+         int submeshCount;      
+         submeshCount = CalRenderer_GetSubmeshCount(pCalRenderer,meshId);
+
+         // render all submeshes of the mesh
+         int submeshId;
+         for(submeshId = 0; submeshId < submeshCount; submeshId++)
+            {
+            // select mesh and submesh for further data access        
+            if(CalRenderer_SelectMeshSubmesh(pCalRenderer,meshId,submeshId))
+               {
+               unsigned char meshColor[4];
+               GLfloat materialColor[4];
+
+               // set the material ambient color         
+               CalRenderer_GetAmbientColor(pCalRenderer, &meshColor[0]);
+               materialColor[0] = meshColor[0] / 255.0f;  materialColor[1] = meshColor[1] / 255.0f; materialColor[2] = meshColor[2] / 255.0f; materialColor[3] = meshColor[3] / 255.0f;
+               //glMaterialfv(GL_FRONT, GL_AMBIENT, materialColor);
+
+               // set the material diffuse color         
+               CalRenderer_GetDiffuseColor(pCalRenderer,&meshColor[0]);
+               materialColor[0] = meshColor[0] / 255.0f;  materialColor[1] = meshColor[1] / 255.0f; materialColor[2] = meshColor[2] / 255.0f; materialColor[3] = meshColor[3] / 255.0f;
+               //glMaterialfv(GL_FRONT, GL_DIFFUSE, materialColor);
+
+               // set the vertex color if we have no lights
+               if(1)
+               {
+                  glColor4fv(materialColor);
+               }
+
+               // set the material specular color         
+               CalRenderer_GetSpecularColor(pCalRenderer,&meshColor[0]);
+               materialColor[0] = meshColor[0] / 255.0f;  materialColor[1] = meshColor[1] / 255.0f; materialColor[2] = meshColor[2] / 255.0f; materialColor[3] = meshColor[3] / 255.0f;
+               //glMaterialfv(GL_FRONT, GL_SPECULAR, materialColor);
+
+               // set the material shininess factor
+               float shininess;
+               shininess = 50.0f; //TODO: pCalRenderer->getShininess();
+               shininess = CalRenderer_GetShininess(pCalRenderer);
+               //glMaterialfv(GL_FRONT, GL_SHININESS, &shininess);
+
+               // get the transformed vertices of the submesh
+               static float meshVertices[30000][3];
+               int vertexCount;         
+               vertexCount = CalRenderer_GetVertices(pCalRenderer,&meshVertices[0][0]);
+
+               // get the transformed normals of the submesh
+               static float meshNormals[30000][3];         
+               CalRenderer_GetNormals(pCalRenderer, &meshNormals[0][0]);
+
+               // get the texture coordinates of the submesh
+               static float meshTextureCoordinates[30000][2];
+               int textureCoordinateCount;
+               textureCoordinateCount = CalRenderer_GetTextureCoordinates(pCalRenderer,0,&meshTextureCoordinates[0][0]);
+
+               // get the faces of the submesh
+               static CalIndex meshFaces[50000][3];
+               int faceCount;
+               faceCount = CalRenderer_GetFaces(pCalRenderer,&meshFaces[0][0]);
+
+               // set the vertex and normal buffers
+               glVertexPointer(3, GL_FLOAT, 0, &meshVertices[0][0]);
+               glNormalPointer(GL_FLOAT, 0, &meshNormals[0][0]);
+
+               // set the texture coordinate buffer and state if necessary
+               if(CalRenderer_GetMapCount(pCalRenderer)>0 && (textureCoordinateCount > 0))
+                  {
+                  glEnable(GL_TEXTURE_2D);
+                  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+                  glEnable(GL_COLOR_MATERIAL);
+
+                  // set the texture id we stored in the map user data           
+                  glBindTexture(GL_TEXTURE_2D, (GLuint)CalRenderer_GetMapUserData(pCalRenderer,0));
+                  // set the texture coordenates buffer
+                  glColor4f(1.0f, 1.0f, 1.0f,1.0f);
+                  glTexCoordPointer(2, GL_FLOAT, 0, &meshTextureCoordinates[0][0]);
+                  glColor4f(1.0f, 1.0f, 1.0f,1.0f);
+                  }
+
+               // draw the submesh
+
+               if(sizeof(CalIndex)==2)
+               glDrawElements(GL_TRIANGLES, faceCount * 3, GL_UNSIGNED_SHORT, &meshFaces[0][0]);
+               else
+               glDrawElements(GL_TRIANGLES, faceCount * 3, GL_UNSIGNED_INT, &meshFaces[0][0]);
+
+               // disable the texture coordinate state if necessary
+               if(CalRenderer_GetMapCount(pCalRenderer)>0  && (textureCoordinateCount > 0))
+                  {
+                  glDisable(GL_COLOR_MATERIAL);
+                  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+                  glDisable(GL_TEXTURE_2D);
+                  }
+               ////////////////////////////////////////////////////////////////////////////////
+               //to show vertex normals do if(1)
+               if(0)
+                  {
+                  glBegin(GL_LINES);
+                  glColor3f(1.0f, 1.0f, 1.0f);
+                  int vertexId;
+                  for(vertexId = 0; vertexId < vertexCount; vertexId++)
+                  {
+                  const float scale = 0.3f;
+                  glVertex3f(meshVertices[vertexId][0], meshVertices[vertexId][1], meshVertices[vertexId][2]);
+                  glVertex3f(meshVertices[vertexId][0] + meshNormals[vertexId][0] * scale, meshVertices[vertexId][1] + meshNormals[vertexId][1] * scale, meshVertices[vertexId][2] + meshNormals[vertexId][2] * scale);
+                  }
+                  glEnd();
+                  }
+               ////////////////////////////////////////////////////////////////////////////////
+               GLfloat one[]={0.8f, 0.8f, 0.8f, 1.f};
+                 GLfloat zero[]={0.0,0.0,0.0,0.0};
+               glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, one);
+               glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, zero);
+               glEnable(GL_TEXTURE_2D);
+               glBindTexture(GL_TEXTURE_2D,0);
+               }
+            }
+         }
+
+      // clear vertex array state
+      glDisableClientState(GL_NORMAL_ARRAY);
+      glDisableClientState(GL_VERTEX_ARRAY);
+
+      // reset wireframe mode if necessary
+      if(bWireframe)
+      {
+         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+      }
+
+      // end the rendering
+      CalRenderer_EndRendering(pCalRenderer);
+   }
+}
+
+void raydium_anim_cal3d_loop_set(int instance,int animation, float influence, float delay_seconds)
+{
+   if(raydium_anim_instance_use[instance])
+      if(delay_seconds>=0)
+         if(influence>=0 && influence<=1   )         
+            CalMixer_BlendCycle(CalModel_GetMixer(raydium_anim_instance[instance]),raydium_anim_animationid[raydium_anim_instance_model[instance]][animation],influence,delay_seconds);   
+         else
+            raydium_log("ANIM:ERROR: Influence must be betwen 0 and 1");
+      else
+         raydium_log("ANIM:ERROR: invalid delay time for setting loop in instance %d",instance);
+   else
+      raydium_log("ANIM:ERROR: Invalid instance index");
+}   
+
+void raydium_anim_cal3d_loop_clear(int instance,int animation, float delay_seconds)
+{
+   if(raydium_anim_instance_use[instance])   
+      if(delay_seconds>=0)         
+         CalMixer_ClearCycle(CalModel_GetMixer(raydium_anim_instance[instance]),raydium_anim_animationid[raydium_anim_instance_model[instance]][animation],delay_seconds);   
+      else
+         raydium_log("ANIM:ERROR: invalid delay time for clearing loop in instance %d",instance);
+   else
+      raydium_log("ANIM:ERROR: Invalid instance index.");
+}
+
+void raydium_anim_cal3d_action_set(int instance,int animation, float fadein_seconds, float fadeout_seconds, int autolock)
+{
+   if(raydium_anim_instance_use[instance])
+      if(fadein_seconds>=0 && fadeout_seconds>=0)
+         CalMixer_ExecuteAction(CalModel_GetMixer(raydium_anim_instance[instance]),raydium_anim_animationid[raydium_anim_instance_model[instance]][animation],fadein_seconds, fadeout_seconds,autolock);
+      else
+         raydium_log("ANIM:ERROR: Fadein_seconds and fadeout seconds must be positive");
+   else
+      raydium_log("ANIM:ERROR: Invalid instance index.");
+}
+
+void raydium_anim_cal3d_model_lod_set(int instance, float lod_level)
+{
+   if(raydium_anim_instance_use[instance])
+      CalModel_SetLodLevel(raydium_anim_instance[instance],lod_level);
+   else
+      raydium_log("ANIM:ERROR: Invalid instance index.");
+}
+
+void raydium_anim_cal3d_model_materials_apply(int instance, int set)
+{
+   if(raydium_anim_instance_use[instance])
+      CalModel_SetMaterialSet(raydium_anim_instance[instance],set);
+   else
+      raydium_log("ANIM:ERROR: Invalid instance index.");
+}
+
+void raydium_anim_cal3d_action_remove(int instance, int animation)
+{   
+   if(raydium_anim_instance_use[instance])
+      CalMixer_RemoveAction((CalModel_GetMixer(raydium_anim_instance[instance])),animation);
+   else   
+      raydium_log("ANIM:ERROR: Invalid instance index.");
+}
+
+int raydium_anim_cal3d_instance_new_internal(int num,int model)
+{
+   if(!raydium_anim_instance_use[num])
+   {
+      raydium_anim_instance[num]=CalModel_New(raydium_anim_model[num]);
+      
+      if(raydium_anim_instance[num])
+         {
+         
+         return 1;
+         }
+      else
+         {
+         return 0;
+         }
+   }
+   else
+   {
+      raydium_log("ANIM:ERROR: that instance alread in use. Bad index");
+      return 0;
+   }
+}
+void raydium_anim_cal3d_instance_destroy(int instance)
+{
+   CalModel_Delete(raydium_anim_instance[instance]);
+}
+
+void raydium_anim_cal3d_instance_attach_meshes(int instance)
+{
+   int b;
+   int model;
+   if(raydium_anim_instance[instance])
+      {
+      model   =   raydium_anim_instance_model[instance];   
+      for(b=0;b<raydium_anim_meshes[model];b++)
+      {
+         CalModel_AttachMesh(raydium_anim_instance[instance], raydium_anim_meshid[model][b]);      
+      }
+      raydium_log("Added %d meshes to model %d for instancde %d",raydium_anim_meshes[model],model,instance);
+      }
+   else
+      {
+      raydium_log("ANIM:ERROR: Instance index %d not valid. ",instance);
+      }   
+}
+
+int raydium_anim_cal3d_model_load_internal(int a,char *filename)
+{
+   FILE *file;
+   char str[RAYDIUM_MAX_NAME_LEN];
+   char strpath[RAYDIUM_MAX_NAME_LEN];
+   char filename2[RAYDIUM_MAX_NAME_LEN];
+   char newstr[RAYDIUM_MAX_NAME_LEN];
+   int ret;
+   int error;
+   char var[RAYDIUM_MAX_NAME_LEN];
+   char val_s[RAYDIUM_MAX_NAME_LEN];
+   GLfloat val_f[5];
+   int size;   
+   //   counters
+   int ani_count;
+   int mesh_count;
+   int mat_count;   
+   float scale;
+   
+   ani_count=0;
+   mesh_count=0;
+   mat_count=0;
+   scale=1.0f;
+   error=0;
+   
+   //check if a is available
+   if(!raydium_anim_model[a])
+   {
+      sprintf(str,"raydium_model_%d",a);
+      
+      raydium_anim_model[a]=(struct CalCoreModel*)CalCoreModel_New(str);
+      //the filename should be a cfg!!!
+      //TODO:check 4 last letters
+      //convert filename into ray-path-compatible format
+      raydium_path_resolv(filename,filename2,'r');
+      if(file=raydium_file_fopen(filename2,"r"))
+      {
+         raydium_log("readed file cfg");
+         while( (ret=raydium_parser_read(var,val_s,val_f,&size,file))!=RAYDIUM_PARSER_TYPE_EOF)
+            {
+               
+               //*** PATH ***
+               if(!strcasecmp(var,"path"))
+               {
+                  raydium_file_dirname(strpath,filename2);
+                  strcat(strpath,val_s);
+                  raydium_log("The path will be: \"%s\"",strpath);
+               }
+               
+               //*** SKELETON ***
+               if(!strcasecmp(var,"skeleton"))
+               {
+                  raydium_log("Readed: %s",(char*)val_s);
+                  sprintf(newstr,"%s%s",strpath,val_s);   
+                  //load the skeleton
+                  if(CalCoreModel_LoadCoreSkeleton(raydium_anim_model[a],newstr))
+                  {
+                     //aply scale
+                     CalCoreSkeleton_Scale(CalCoreModel_GetCoreSkeleton(raydium_anim_model[a]),scale);
+                     raydium_log("Successfully loaded %s",newstr);
+                  }   
+                  else
+                  {
+                     raydium_log("ANIM:ERROR: Loading file %s",newstr);
+                     error=1;
+                  }               
+               }
+               
+               //*** SCALE ***
+               if(!strcasecmp(var,"scale"))
+               {   
+                  scale=val_f[0];
+               }
+               
+               //*** ANIMS ***
+               if(!strcasecmp(var,"animation"))
+               {
+                  
+                  raydium_log("Readed: %s",(char*)val_s);
+                  sprintf(newstr,"%s%s",strpath,val_s);   
+                  //load the animation
+                  raydium_anim_animationid[a][ani_count]=CalCoreModel_LoadCoreAnimation(raydium_anim_model[a],newstr);                  
+                  if(raydium_anim_animationid[a][ani_count]!=-1)
+                  {
+                     CalCoreAnimation_Scale(CalCoreModel_GetCoreAnimation(raydium_anim_model[a],raydium_anim_animationid[a][ani_count]),scale);                        
+                     ani_count++;
+                     raydium_log("Successfully loaded animation: %s",newstr);
+                     raydium_anim_animations[a]++;
+                  }         
+                  else
+                  {
+                     error=1;
+                  }                  
+               }
+               
+               //*** MESH ***
+               if(!strcasecmp(var,"mesh"))
+               {   
+                  raydium_log("Readed: %s",(char*)val_s);
+                  sprintf(newstr,"%s%s",strpath,val_s);
+                  raydium_anim_meshid[a][mesh_count]=CalCoreModel_LoadCoreMesh(raydium_anim_model[a],newstr);   
+                  if(raydium_anim_meshid[a][mesh_count]!=-1)
+                  {
+                     CalCoreMesh_Scale(CalCoreModel_GetCoreMesh(raydium_anim_model[a],raydium_anim_meshid[a][mesh_count]),scale);
+                     mesh_count++;
+                     raydium_log("Successfully loaded mesh:%s",newstr);
+                     raydium_anim_meshes[a]++;                     
+                  }      
+                  else
+                  {
+                     error=1;
+                  }            
+               }
+               
+               //*** MATERIALS ***
+               if(   !strcasecmp(var,"material"))
+               {
+                  raydium_log("Readed: %s",(char*)val_s);
+                  sprintf(newstr,"%s%s",strpath,val_s);
+                  raydium_anim_materialid[a][mat_count]=CalCoreModel_LoadCoreMaterial(raydium_anim_model[a],newstr);   
+                  if(raydium_anim_materialid[a][mat_count]!=-1)
+                  {                     
+                     mat_count++;
+                     raydium_log("Successfully loaded material:%s",newstr);
+                     raydium_anim_materials[a]++;                                       
+                  }
+                  else
+                  {
+                     error=1;
+                  }                  
+               }      
+            }                  
+         fclose(file);   
+         int c;
+         for(c=0;c<(raydium_anim_materials[a]);c++)
+         {
+            //load textures, if any
+            // get the current core material
+            struct CalCoreMaterial *pCoreMaterial;
+            //pCoreMaterial = myCoreModel.getCoreMaterial(materialId);
+            pCoreMaterial=CalCoreModel_GetCoreMaterial(raydium_anim_model[a],raydium_anim_materialid[a][c]);
+            
+            // dont use, just helper -> CalCoreMaterial_GetMapCount(CalCoreModel_GetCoreMaterial(raydium_anim_model[a]))
+            // loop through all the maps of the current core material
+            int mapid;
+            for(mapid = 0; mapid < CalCoreMaterial_GetMapCount(pCoreMaterial); mapid++)
+            {
+               // get the filename of the map
+               char strFilename[RAYDIUM_MAX_NAME_LEN];
+               strcpy(strFilename,CalCoreMaterial_GetMapFilename(pCoreMaterial,mapid));
+
+               // load the texture from the file
+               //Cal::UserData textureId;
+               //struct CalUserData textureid;
+               GLuint textureid;
+               //textureId = (Cal::UserData)myTextureLoadingFunction(strFilename);
+               //TODO:Ugly way to allow this path for textures
+               sprintf(newstr,"%s%s",strpath,strFilename);
+               raydium_path_add(strpath);
+               textureid=raydium_texture_load(strFilename);
+
+               // store the texture id in the user data of the map
+               //pCoreMaterial->setMapUserData(mapId, textureId);
+               //CalCoreMaterial_SetMapUserData(mapid,textureid);
+               CalCoreMaterial_SetMapUserData(pCoreMaterial,mapid,(int*)textureid);         
+            
+            }
+            
+            CalCoreModel_CreateCoreMaterialThread(raydium_anim_model[a],c);
+            
+            CalCoreModel_SetCoreMaterialId(raydium_anim_model[a],c,0,c);
+            
+            //CalCoreModel_SetCoreMaterialId(raydium_anim_model[a],c,0,c);
+            
+            //m_calCoreModel->createCoreMaterialThread(materialId);
+            // initialize the material thread
+            //m_calCoreModel->setCoreMaterialId(materialId, 0, materialId);
+         }      
+      }
+      else
+      {
+         raydium_log("ANIM:ERROR: Couldn't open file \"%s\".",filename);
+         error=1;
+      }
+   }
+   else
+   {
+      raydium_log("ANIM:ERROR:raydium_anim_model[%d] was not unset",a);
+      error=1;
+   }
+   
+   if(error)
+      return 0;
+   else      
+      return 1;      
+}
Index: raydium/index.c
===================================================================
--- raydium/index.c   (revisión: 798)
+++ raydium/index.c   (copia de trabajo)
@@ -63,6 +63,7 @@
 #include "hdr.c"
 #include "shader.c"
 #include "register.c"
+#include "anim.h"
 #ifdef PHP_SUPPORT
 #include "php.c"
 #include "rayphp.c"
Index: raydium/index.h
===================================================================
--- raydium/index.h   (revisión: 798)
+++ raydium/index.h   (copia de trabajo)
@@ -57,6 +57,7 @@
 #include "headers/hdr.h"
 #include "headers/shader.h"
 #include "headers/register.h"
+#include "headers/anim.h"
 #ifdef PHP_SUPPORT
 #include "headers/php.h"
 #include "headers/rayphp.h"
Index: raydium/headers/anim.h
===================================================================
--- raydium/headers/anim.h   (revisión: 0)
+++ raydium/headers/anim.h   (revisión: 0)
@@ -0,0 +1,227 @@
+#ifndef _ANIM_H
+#define _ANIM_H
+#include <cal3d/cal3d_wrapper.h>
+
+//TODO:This should be in other place
+#define RAYDIUM_ANIM_CAL3D
+#define RAYDIUM_ANIM_MAX_MODELS 20
+#define RAYDIUM_ANIM_RENDER_NONE 0
+#define RAYDIUM_ANIM_RENDER_MESH 1
+#define RAYDIUM_ANIM_RENDER_SKELETON 2
+
+//-----------------------------------------------------------
+//Doxygen testing doc
+/*! \page animatedmodels Animated Models
+ 
+Raydium allows you to use Animated Models in Cal3D(http://home.gna.org/cal3d/) format.
+It's important to know well how cal3d animation works before starting to suing it.
+
+A common cal3d model is compound of:
+ 
+-.cfg file with a few parameters and a list of used files
+-.csf file with the unique skeleton per model
+-.caf or .xaf files, each one is 1 animation loop/action for the current model
+-.crf or .xrf files, each one is a material
+-.cmf or .xmf files, each one is a mesh to apply in the model
+*
+Note: "x-starting" files are XML files and easy to edit. By other side "c-starting" files are binary compiled files. They can not be edited but are faster to load.
+
+
+So raydium will load the cfg file an, internally, it will load all needed subfiles.
+The models can NOT be used directly so, once loaded the model you MUST create instances of the model for your application.
+Then you can apply loops or actions to each instance independently.
+
+
+Types of animations:
+
+Even if the animation files are the same, you can apply that animation as a loop or as an action.
+Loops: the animation loops forever (until you deactivate it)
+Actions: The animation will play just once, and you can set a lock. If the action is locked, the instance will be keep in the last frame of the animation, else it will return to the previous animation fame(if any).
+
+Mixing:
+
+To achieve good animations you will have to mix diferent animations at time.
+For example your model could be walking and sometimes it could throw an arrow.
+
+TODO: more explanation about mixing
+*/
+
+//-----------------------------------------------------------
+
+
+/*=
+Animation System
+2200
+Raydium allows you to use Animated Models in Cal3D(http://home.gna.org/cal3d/) format.
+It's important to know well how cal3d animation works before starting to suing it.
+
+A common cal3d model is compound of:
+ 
+-.cfg file with a few parameters and a list of used files
+-.csf file with the unique skeleton per model
+-.caf or .xaf files, each one is 1 animation loop/action for the current model
+-.crf or .xrf files, each one is a material
+-.cmf or .xmf files, each one is a mesh to apply in the model
+*
+Note: "x-starting" files are XML files and easy to edit. By other side "c-starting" files are binary compiled files. They can not be edited but are faster to load.
+
+
+So raydium will load the cfg file an, internally, it will load all needed subfiles.
+The models can NOT be used directly so, once loaded the model you MUST create instances of the model for your application.
+Then you can apply loops or actions to each instance independently.
+
+
+Types of animations:
+
+Even if the animation files are the same, you can apply that animation as a loop or as an action.
+Loops: the animation loops forever (until you deactivate it)
+Actions: The animation will play just once, and you can set a lock. If the action is locked, the instance will be keep in the last frame of the animation, else it will return to the previous animation fame(if any).
+
+Mixing:
+
+To achieve good animations you will have to mix diferent animations at time.
+For example your model could be walking and sometimes it could throw an arrow.
+
+TODO: more explanation about mixing 
+
+**/
+
+// Introduction
+/**
+EXPERIMENTAL: DONT USE!
+Animation system
+Based on Cal3D.
+**/
+
+
+__rayapi int raydium_anim_model_load(char *filename);
+/**
+EXPERIMENTAL: DONT USE!
+This function loads a model.
+Currently only Cal3D models are allowed. So you have to specify a *.cfg file in
+the ##filename##.
+
+##Parameters:##
+##model##:the index of the model to instanciate
+
+##Returns:##
+the index of the new model, or -1 if fails
+
+##Example:##
+%%(c)
+int paladin_model;
+int create_model_paladin(void)
+   {
+   paladin_model=raydium_anim_model_load("paladin.cfg");
+   return 
+   }
+%%
+**/
+
+__rayapi int raydium_anim_cal3d_model_load_internal(int a,char *filename);
+/**
+EXPERIMENTAL: DONT USE!
+Internal.
+**/
+
+__rayapi void raydium_anim_models_destroy(void);
+/**
+EXPERIMENTAL: DONT USE!
+Destroy all models used in raydium.
+Beware. You should destroy all instances BEFORE call this function.
+**/
+
+__rayapi void raydium_anim_init(void);
+/**
+EXPERIMENTAL: DONT USE!
+Init the animation system of raydium.
+**/
+
+
+__rayapi int raydium_anim_instance_new(int model);
+/**
+EXPERIMENTAL: DONT USE!
+Creates a new instance from a ##model##.
+
+##Parameters:##
+##model##:the index of the model to instanciate
+
+##Returns:##
+The index of the new instance
+
+##Example:##
+%%(c)
+int paladin_instance[2];
+int paladin_model;
+void create_paladin_instances(void)
+   {
+      paladin_model=create_model_paladin();
+      paladin_instance[0]=raydium_anim_instance_new(paladin_model);
+      paladin_instance[1]=raydium_anim_instance_new(paladin_model);      
+   }
+%%
+**/
+
+__rayapi void raydium_anim_instance_update(int instance,float time);
+/**
+EXPERIMENTAL: DONT USE!
+This function is a must if you want to animate you models(instances).
+
+##Parameters:##
+##instance##:the index of the instance
+##time##: The time betwen the last call to thin function and this call. 
+Commonly this value is equal to ##raydium_frame_time##
+
+##Returns:##
+
+##Example:##
+%%(c)
+void display(void)
+   {
+   if(raydium_key_last==1027)
+   exit(0);
+   raydium_clear_frame();
+   raydium_camera_freemove(RAYDIUM_CAMERA_FREEEMOVE_NORMAL);   
+   raydium_ode_draw_all(0);
+   raydium_anim_instance_update(character,raydium_frame_time);   
+   raydium_anim_instance_render_mesh(character);
+   raydium_rendering_finish();
+   }
+%%
+**/
+__rayapi void raydium_anim_instance_update(int instance,float delta_time);
+__rayapi void raydium_anim_instance_render_skeleton(int instance);
+__rayapi int raydium_anim_model_load(char *filename);
+__rayapi int raydium_anim_instance_new(int model);
+__rayapi void raydium_anim_instances_destroy();
+__rayapi void raydium_anim_models_destroy(void);
+__rayapi void raydium_anim_instance_attach_meshes(int instance);
+__rayapi void raydium_anim_cal3d_instance_attach_meshes(int instance);
+__rayapi void raydium_anim_cal3d_instance_render_mesh(int instance);
+__rayapi void raydium_anim_loop_set(int instance,int animation, float influence, float delay_seconds);
+__rayapi void raydium_anim_cal3d_loop_set(int instance,int animation, float influence, float delay_seconds);
+__rayapi void raydium_anim_loop_clear(int instance,int animation, float delay_seconds);
+__rayapi void raydium_anim_cal3d_loop_clear(int instance,int animation, float delay_seconds);
+__rayapi void raydium_anim_action_set(int instance,int animation, float fadein_seconds, float fadeout_seconds, int autolock);
+__rayapi void raydium_anim_cal3d_action_set(int instance,int animation, float fadein_seconds, float fadeout_seconds, int autolock);
+__rayapi void raydium_anim_cal3d_model_lod_set(int instance, float lod_level);
+__rayapi void raydium_anim_model_lod_set(int instance, float lod_level);
+__rayapi void raydium_anim_cal3d_model_materials_apply(int instance, int set);
+__rayapi void raydium_anim_model_materials_apply(int instance, int set);
+__rayapi void raydium_anim_instance_render_mesh(int instance);
+__rayapi void raydium_anim_cal3d_action_remove(int instance, int animation);
+__rayapi void raydium_anim_action_remove(int instance,int animation);
+__rayapi void raydium_anim_cal3d_instance_render_skeleton(int instance);
+__rayapi void raydium_anim_skeleton_scale(int model,float scale);
+__rayapi void raydium_anim_cal3d_instance_update(int instance, float time);
+__rayapi void raydium_anim_cal3d_animation_scale(int model,int animation,float scale);
+__rayapi void raydium_anim_cal3d_skeleton_scale(int model,float scale);
+__rayapi void raydium_anim_cal3d_instance_destroy(int instance);
+__rayapi void raydium_anim_instance_render(int instance, int type);
+__rayapi void raydium_anim_instance_move(int instance,float x, float y, float z);
+__rayapi void raydium_anim_instance_move_relative(int instance,float x, float y, float z);
+__rayapi void raydium_anim_instance_rotate(int instance,float x, float y, float z);
+__rayapi void raydium_anim_instance_rotate_relative(int instance,float x, float y, float z);
+
+#endif
+
Here the data folder(needed for tests):
http://www.guadagames.com/versusrx/data.tar.bz2After apply the patch, do "make" and after that:
./odyncomp.sh anim-test1.c
The app has OSD instructions.
TODO: Complete the doc(W.I.P)
New test app with moving character(W.I.P.)