Raydium 3D Game Engine

Official forum for everything about Raydium, ManiaDrive, MeMak, ...
It is currently Thu Mar 28, 2024 10:52 am

All times are UTC




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Spherical Gravity
PostPosted: Sun Sep 07, 2008 12:46 am 
Offline
User avatar

Joined: Thu Sep 29, 2005 2:59 pm
Posts: 828
Yerterday i had to take a break and I did this demo about spherical gravity.
I though it would be quite difficult, but in fact it's quite easy

Image

Here is the code (maybe I'll improve it a bit in the next breaktime)

Code:
/*
    Raydium - CQFD Corp.
    http://raydium.org/
    Released under both BSD license and Lesser GPL library license.
    See "license.txt" file.
*/

#include "raydium/index.c"
#define BREAK_FORCE     150
#define ROTFRICTION     0.0005
#define ERP_CFM         0.1,1.0
#define SPHERICAL 0
#define TYPE_BALANCIER          6

int crate[50];
int counter=0;
int starting=1;
int usegravity=1;
float force=6.0f;
float power=0;
int mode=0;
dReal gears[]={-0.4,0.4,0.6,0.8,0.9,1.0};
int gear=1;
int gravitytype=0;
int sound_boom,sound_engine;

//Show OSD info text on screen
void info(void)
{
  raydium_osd_color_change (0.5,0,0);
  raydium_osd_printf(2,98,16,0.5,"font2.tga","Use cursors and mouse to move the camera");
  raydium_osd_printf(2,95,16,0.5,"font2.tga","m to switch betwen free camera and driving buggy. Mode: %s",mode?"Driving":"Free camera");
  raydium_osd_printf(2,92,16,0.5,"font2.tga","b to restart the buggy");
  raydium_osd_printf(2,89,16,0.5,"font2.tga","c to create random crates. Crates: %d",counter);
  raydium_osd_printf(2,86,16,0.5,"font2.tga","1,2,3...0, + and - to change force of gravity(recomended force 6)");
  raydium_osd_printf(2,83,16,0.5,"font2.tga","s to switch on/off the gravity.");
  raydium_osd_printf(2,80,16,0.5,"font2.tga","t to switch the type of gravity.");
  raydium_osd_printf(2,77,16,0.5,"font2.tga","e to create an explosion.");

  raydium_osd_color_change (0.5,1,1);
  raydium_osd_printf(2,3,18,0.5,"font2.tga","Gravity type: %s",usegravity?(gravitytype?"Normal":"Spherical"):"Zero gravity");
  if (usegravity)
    raydium_osd_printf(2,7,18,0.5,"font2.tga","Gravity force: %3.2f",force);

}

//Creates a buggy, or reset it if recalled
int create_buggy()
{
  int a;
  raydium_ode_object_delete_name("BUGGY");

  a=raydium_ode_object_create("BUGGY");
  raydium_ode_object_box_add("buggy_corps",a,1,RAYDIUM_ODE_AUTODETECT,0,0,RAYDIUM_ODE_STANDARD,0,"buggy.tri");

  raydium_ode_network_next_local_only=1;
  raydium_ode_object_box_add("balancier",a,1.8,0.1,0.1,0.1,RAYDIUM_ODE_STANDARD,TYPE_BALANCIER,"");
  raydium_ode_element_move_name_3f("balancier",0,0,-0.5);
  raydium_ode_joint_attach_fixed_name("balanfixed","corps","balancier");

  raydium_ode_object_sphere_add("buggy_pneu_ag",a,0.2,RAYDIUM_ODE_AUTODETECT,RAYDIUM_ODE_STANDARD,0,"roue_barbare.tri");
  raydium_ode_element_rotfriction_name("buggy_pneu_ag",ROTFRICTION);
  raydium_ode_element_move_name_3f("buggy_pneu_ag",0.42,0.363,-0.430);
  raydium_ode_joint_attach_hinge2_name("buggy_suspet_ag","buggy_corps","buggy_pneu_ag",RAYDIUM_ODE_JOINT_SUSP_DEFAULT_AXES);
  raydium_ode_joint_break_force_name("buggy_suspet_ag",BREAK_FORCE);
  raydium_ode_joint_suspension_name("buggy_suspet_ag",ERP_CFM);

  raydium_ode_object_sphere_add("buggy_pneu_ad",a,0.2,RAYDIUM_ODE_AUTODETECT,RAYDIUM_ODE_STANDARD,0,"roue_barbare.tri");
  raydium_ode_element_rotfriction_name("buggy_pneu_ad",ROTFRICTION);
  raydium_ode_element_move_name_3f("buggy_pneu_ad",0.42,-0.363,-0.430);
  raydium_ode_joint_attach_hinge2_name("buggy_suspet_ad","buggy_corps","buggy_pneu_ad",RAYDIUM_ODE_JOINT_SUSP_DEFAULT_AXES);
  raydium_ode_joint_break_force_name("buggy_suspet_ad",BREAK_FORCE);
  raydium_ode_joint_suspension_name("buggy_suspet_ad",ERP_CFM);

  raydium_ode_object_sphere_add("buggy_pneu_rg",a,0.2,RAYDIUM_ODE_AUTODETECT,RAYDIUM_ODE_STANDARD,0,"roue_barbare.tri");
  raydium_ode_element_rotfriction_name("buggy_pneu_rg",ROTFRICTION);
  raydium_ode_element_move_name_3f("buggy_pneu_rg",-0.444,0.4,-0.400);
  raydium_ode_joint_attach_hinge2_name("buggy_suspet_rg","buggy_corps","buggy_pneu_rg",RAYDIUM_ODE_JOINT_SUSP_DEFAULT_AXES);
  raydium_ode_joint_hinge2_block_name("buggy_suspet_rg",1);
  raydium_ode_joint_break_force_name("buggy_suspet_rg",BREAK_FORCE);
  raydium_ode_joint_suspension_name("buggy_suspet_rg",ERP_CFM);

  raydium_ode_object_sphere_add("buggy_pneu_rd",a,0.2,RAYDIUM_ODE_AUTODETECT,RAYDIUM_ODE_STANDARD,0,"roue_barbare.tri");
  raydium_ode_element_rotfriction_name("buggy_pneu_rd",ROTFRICTION);
  raydium_ode_element_move_name_3f("buggy_pneu_rd",-0.444,-0.4,-0.400);
  raydium_ode_joint_attach_hinge2_name("buggy_suspet_rd","buggy_corps","buggy_pneu_rd",RAYDIUM_ODE_JOINT_SUSP_DEFAULT_AXES);
  raydium_ode_joint_hinge2_block_name("buggy_suspet_rd",1);
  raydium_ode_joint_break_force_name("buggy_suspet_rd",BREAK_FORCE);
  raydium_ode_joint_suspension_name("buggy_suspet_rd",ERP_CFM);

  raydium_ode_motor_create("buggy_moteur",a,RAYDIUM_ODE_MOTOR_ENGINE);
  raydium_ode_motor_attach_name("buggy_moteur","buggy_suspet_ag",1);
  raydium_ode_motor_attach_name("buggy_moteur","buggy_suspet_ad",1);
  raydium_ode_motor_attach_name("buggy_moteur","buggy_suspet_rg",1);
  raydium_ode_motor_attach_name("buggy_moteur","buggy_suspet_rd",1);
  raydium_ode_motor_power_max_name("buggy_moteur",0.1);
  raydium_ode_motor_gears_set_name("buggy_moteur",gears,6);
  raydium_ode_motor_gear_change_name("buggy_moteur",gear);

  raydium_ode_motor_create("buggy_direction",a,RAYDIUM_ODE_MOTOR_ANGULAR);
  raydium_ode_motor_attach_name("buggy_direction","buggy_suspet_ag",0);
  raydium_ode_motor_attach_name("buggy_direction","buggy_suspet_ad",0);
  raydium_ode_motor_power_max_name("buggy_direction",0.1);

  raydium_ode_element_ray_attach_name("buggy_corps",10,1,0,0);
  raydium_ode_element_ray_pos_name_3f("buggy_corps",0,0.2,0,0.225);
  raydium_ode_object_move_name_3f("BUGGY",0,0,15.3);
  return a;
}

//function to create crates randomly
int create_crate()
{
  char name[RAYDIUM_MAX_NAME_LEN];
  char name2[RAYDIUM_MAX_NAME_LEN];
  float x,y,z;
  int a;
  sprintf(name,"crate%d",counter);
  raydium_log("Go to create %s",name);
  a=raydium_ode_object_create(name);
  sprintf(name2,"%s.crate",name);
  raydium_ode_object_box_add(name2,a,1,RAYDIUM_ODE_AUTODETECT,0,0,RAYDIUM_ODE_STANDARD,0,"crate.tri");
  raydium_ode_element_material_name(name2,RAYDIUM_ODE_MATERIAL_HARD);
  raydium_log("Go to create element %s",name2);
  x=raydium_random_f(15.5,20);
  y=raydium_random_f(15.5,20);
  z=raydium_random_f(15.5,20);
  x=raydium_random_proba (0.5)?-x:x;
  y=raydium_random_proba (0.5)?-y:y;
  z=raydium_random_proba (0.5)?-z:z;
  raydium_ode_element_move_name_3f(name2,x,y,z);
  counter++;
  return a;
}

//function to apply spherical forces to all elements
void spherical_gravity(float forceg)
{
  int a;
  float direction[3];
  float *pos1,*pos2;
  float hipo=0.0f;

  //position of the planet
  pos2=raydium_ode_element_pos_get_name("ground");

  //apply an "spherical" force to each element
  for (a=1;a<RAYDIUM_ODE_MAX_ELEMENTS;a++)
    {
      //if the element is valid...
      if (raydium_ode_element_isvalid(a))
        {
          //...get its pos(ition)
          pos1=raydium_ode_element_pos_get(a);
          //calculate the direction vector
          direction[0]=pos2[0]-pos1[0];
          direction[1]=pos2[1]-pos1[1];
          direction[2]=pos2[2]-pos1[2];
          //normalize the vector
          hipo=sqrt(direction[0]*direction[0]+direction[1]*direction[1]);
          hipo=sqrt(hipo*hipo+direction[2]*direction[2]);
          if (hipo!=0)
            {
              direction[0]=(float)forceg*direction[0]/(float)hipo;
              direction[1]=(float)forceg*direction[1]/(float)hipo;
              direction[2]=(float)forceg*direction[2]/(float)hipo;
              //and if there is a force to apply, do it
              raydium_ode_element_addforce_3f (a,direction[0],direction[1],direction[2]);
            }
        }
    }
}

void explode(void)
{
  raydium_ode_explosion_blow_rand_3f(20,800,0.314,0,0,0);

  raydium_sound_SourceStop(sound_boom);
  raydium_sound_SourcePlay(sound_boom);
  raydium_ode_element_sound_update_name("ground",sound_boom);
  raydium_camera_rumble(1,-1,1);
}

void display(void)
{

  dReal speed, direct;
  float cam[3], *pos;
  float accel=0.2;
  int tag;

  /***********************/
  /*** INPUTS          ***/
  /***********************/

  raydium_joy_key_emul();

  if (raydium_key_last==1027)
    exit(0);

  if (raydium_key_last==1000+'m')mode=mode?0:1;
  if (raydium_key_last==1000+'c')crate[counter]=create_crate(2,2,2);
  if (raydium_key_last==1000+'s')usegravity=usegravity?0:1;
  if (raydium_key_last==1000+'1')force=1.0f;
  if (raydium_key_last==1000+'2')force=2.0f;
  if (raydium_key_last==1000+'3')force=4.0f;
  if (raydium_key_last==1000+'4')force=8.0f;
  if (raydium_key_last==1000+'5')force=16.0f;
  if (raydium_key_last==1000+'6')force=32.0f;
  if (raydium_key_last==1000+'7')force=64.0f;
  if (raydium_key_last==1000+'8')force=128.0f;
  if (raydium_key_last==1000+'9')force=256.0f;
  if (raydium_key_last==1000+'0')force=512.0f;
  if (raydium_key_last==1000+'+')force++;
  if (raydium_key_last==1000+'-')force--;
  if (raydium_key_last==1000+'b')create_buggy();
  if (raydium_key_last==1000+'t')gravitytype=gravitytype?0:1;
  if (raydium_key_last==1000+'e')explode();

  if (mode==0)
    {
      direct=raydium_joy_x*0.33;

      if (raydium_joy_y>0.3)
        {
          speed=raydium_joy_y*15;
          raydium_ode_motor_power_max_name("buggy_moteur",accel);
          tag=1;
        }
      else
        if (raydium_joy_y<-0.3)
          {
            speed=raydium_joy_y*3;
            raydium_ode_motor_power_max_name("buggy_moteur",0.2 * -raydium_joy_y);
            tag=1;
          }

      if (!tag)
        {
          speed=0;
          raydium_ode_motor_power_max_name("buggy_moteur",0.05);
        }

      raydium_ode_motor_speed_name("buggy_moteur",-speed);
      raydium_sound_SetSourcePitch(sound_engine,0.5f+(fabs(speed/5.f)));
      raydium_sound_SetSourceGain(sound_engine,1.0f+(fabs(speed/10.f)));
      raydium_ode_motor_angle_name("buggy_direction",direct);
    }


  /***********************/
  /*** PROCESSES       ***/
  /***********************/

  if (gravitytype==SPHERICAL)
    {
      raydium_ode_gravity_3f(0,0,0);
      if (usegravity)
        spherical_gravity(force);
    }
  else
    {
      raydium_ode_gravity_3f(0,0,-1);
    }

  if (mode==1)
    {
      raydium_camera_freemove(1);
    }
  else
    if (mode==0)
      {
        /*pos=raydium_ode_element_pos_get_name("buggy_corps");
        raydium_ode_element_RelPointPos_name("buggy_corps",-4,0,3,cam);
        raydium_camera_smooth(cam[0],cam[1],cam[2],pos[1],-pos[2],pos[0],70,0,raydium_frame_time*10);
        */
        raydium_ode_element_camera_inboard_name ("buggy_corps", -4,0,3,0,0,0);
      }



  /***********************/
  /*** RENDER PIPELINE ***/
  /***********************/
  raydium_clear_frame();
  raydium_ode_draw_all(0);
  if (raydium_key[GLUT_KEY_F1])
    {
      raydium_ode_draw_all(RAYDIUM_ODE_DRAW_DEBUG);
    }
  info(); //to show OSD info texts


  /***********************/
  /*** ENDING FRAME    ***/
  /***********************/
  raydium_rendering_finish();
}


int main(int argc, char **argv)
{
  raydium_init_args(argc,argv);
  raydium_window_create(640,480,RAYDIUM_RENDERING_WINDOW,"Raydium test Spherical Gravity ");

  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_on(1);

  raydium_light_conf_7f(0,0,150,200,25000000,1,0.9,0.9); // id, pos, intensity and color (RGB)
  raydium_background_color_change(1,0.9,0.7,1);
  raydium_light_conf_7f(1,0,-150,0 ,2500000,0.7,0.7,1); // id, pos, intensity and color (RGB)
  raydium_background_color_change(1,0.9,0.7,1);

  raydium_sky_box_cache();

  /* [ place base scene here ] */
  raydium_ode_ground_set_name("asteroid.tri");
  raydium_ode_gravity_3f(0,0,0);

//create the buggy before starting render the first frame
  create_buggy();
  raydium_shadow_enable();
  sound_boom=raydium_sound_LoadWav("bigboom.wav");
  sound_engine=raydium_sound_LoadWav("engine-rumble.wav");
  raydium_sound_SetSourceLoop(sound_boom,0);
  raydium_sound_SetSourceLoop(sound_engine,1);
  raydium_sound_SourcePlay(sound_engine);
  create_crate();
  create_crate();
  create_crate();
  create_crate();
  create_crate();
  create_crate();
  create_crate();
  raydium_camera_place(0,0,17,0,0,0);
  raydium_ode_element_material(0,RAYDIUM_ODE_MATERIAL_HARD);
  raydium_callback(&display);
  return(0);
}

// EOF

Your opinion?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 07, 2008 10:42 am 
Offline

Joined: Sun Oct 09, 2005 10:46 pm
Posts: 759
Hello,

some infos.

Gravity force is related to boject mass.

To have a more correct behaviour you need to get element mass.

I'll add this function to ode.c, but as my local copy integrate thoses changes and also autodisable functions i need to test further before commit.

Just use this function in your code if you want.

Code:
dReal raydium_ode_element_mass_get(int elem)
{
    dMass m;

    if(!raydium_ode_element_isvalid(elem))
    {
        raydium_log("ODE: Error: Cannot change mass of element: invalid index or name");
        return;
    }

    if(raydium_ode_element[elem].state==RAYDIUM_ODE_STATIC)
    {
        raydium_log("ODE: Error: Cannot change mass of a static element");
        return;
    }
   
    dBodyGetMass(raydium_ode_element[elem].body,&m);

    return (m.mass);
   
}


Your spherical gravity function will look like (with small math simplification).

Code:
          direction[0]=pos2[0]-pos1[0];
          direction[1]=pos2[1]-pos1[1];
          direction[2]=pos2[2]-pos1[2];
          //normalize the vector
          hipo=sqrt(direction[0]*direction[0]+direction[1]*direction[1]+direction[2]*direction[2]);
          mass=raydium_ode_element_mass_get(a);
          if (hipo!=0)
            {
              direction[0]=(float) mass*forceg*direction[0]/(float)hipo;
              direction[1]=(float) mass*forceg*direction[1]/(float)hipo;
              direction[2]=(float) mass*forceg*direction[2]/(float)hipo;
              //and if there is a force to apply, do it
              raydium_ode_element_addforce_3f (a,direction[0],direction[1],direction[2]);
            }


Be carrefull your joint to attach "balancier" to the car need to be attached to buggy_corps and not corps.

Last initialise tag to 0 or at least speed to 0 at begining of display function. Here it default to nan. Causing strange behaviour and openal error when no keys are touched.

Last but not least.
You apply spherical gravity at each frame, but physical solver iterate several times between two frames. So your physic will be frame rate (and thus hardware) dependant.

better way is to compute spherical gravity in an ode step callback
Quote:
raydium_ode_StepCallback=spherical_gravity;


Hope this will help you.

I find the idea is quite funny and apps to, need to be devolpped !

Have a nice day.
Ouille


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 07, 2008 12:19 pm 
Offline
User avatar

Joined: Thu Sep 29, 2005 2:59 pm
Posts: 828
Thanks
Eveything changed (with a few customs).

Anyway, adding Sphere_gravity to the ode callback is slowdowning the perfomance higly. However I understand this is the right way.

I'm trying to find an aproximated_distance function to avoid calculating hundreds of square roots each second.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 07, 2008 1:46 pm 
Offline
User avatar

Joined: Sun Mar 16, 2003 2:53 am
Posts: 2591
Location: gnniiiii (Scrat)
It looks very good ! What 3D engine did you use ? :)

Reminds me some renders of Spore :
Image

edit : about square roots ,can't you use some good old pre-calc tables approximation ?


Top
 Profile  
 
 Post subject: Re: Spherical Gravity
PostPosted: Sun Sep 07, 2008 8:04 pm 
Offline
User avatar

Joined: Thu Sep 29, 2005 2:59 pm
Posts: 828
3D engine? Raydium :lol:
For developing the asteroid I used blender+Blender Worls Forge (a python plugin. http://www.selleri.org/Blender/scripts/BWF-0.1.0.zip)

About pre-calc tables approximation: Do you have something done over there?
Anyway I have found the problem is not the sqrt's the problem is the collision internal function when a lot of crates are touching the surface of the planet but they are not stables(they are sliding always).

Go to try with the new function that Ouille has commit


Top
 Profile  
 
 Post subject: Re: Spherical Gravity
PostPosted: Sun Sep 07, 2008 8:32 pm 
Offline

Joined: Sun Oct 09, 2005 10:46 pm
Posts: 759
Hello,

Autodisable will not be very usefull as you add force, so i need to re enable body each step / frame.

Colliding with asteroid surface seems to be very time comsuption.

Perhaps try to tune asteroid materiel (or erp cfm) to stick boxes.

Have a nice day
Ouille.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 33 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group