/* Raydium - CQFD Corp. http://raydium.org/ License: GPL - GNU General Public License, see "gpl.txt" file. */ #ifndef DONT_INCLUDE_HEADERS #include "index.h" #else #include "headers/ode.h" #endif // TODO: // load object from file // delete callbaks (objects, motors, ... ?) (done for joints, elements) // parametric frictions // other joints // allow full RayODE reset (almost done now) // multiple grounds // bugfix for rotation friction #include "ode.h" void raydium_ode_name_auto(char *prefix, char *dest) { static int counter; sprintf(dest,"%s_ode_%i",prefix,counter); counter++; } void raydium_ode_init_object(int i) { raydium_ode_object[i].id=i; raydium_ode_object[i].name[0]=0; raydium_ode_object[i].state=0; raydium_ode_object[i].colliding=0; raydium_ode_object[i].group=NULL; } void raydium_ode_init_element(int i) { int j; raydium_ode_element[i].id=i; raydium_ode_element[i].name[0]=0; raydium_ode_element[i].state=0; raydium_ode_element[i].object=-1; raydium_ode_element[i].mesh=-1; raydium_ode_element[i]._touched=0; raydium_ode_element[i]._movesfrom=-1; raydium_ode_element[i].isplayer=0; raydium_ode_element[i].playerangle=0; raydium_ode_element[i].slip=0; raydium_ode_element[i].rotfriction=0; raydium_ode_element[i].geom=NULL; raydium_ode_element[i].body=NULL; raydium_ode_element[i].erp=0; raydium_ode_element[i].cfm=0; raydium_ode_element[i].user_data=NULL; raydium_ode_element[i].user_tag=0; // I consider every fixed element is already free() for(j=0;j=0 && i=0 && i<=RAYDIUM_ODE_MAX_ELEMENTS && /* "<=" is important, see ode.h ! */ raydium_ode_element[i].state) return 1; return 0; } signed char raydium_ode_joint_isvalid(int i) { if(i>=0 && i=0 && i=0 && iname); //printf("%i\n",one); //e->ground_texture=raydium_vertex_texture[one]; max_val= ((pos[0]-raydium_vertex_x[TriIndices[0]*3+offset]) + (pos[1]-raydium_vertex_y[TriIndices[0]*3+offset]) + (pos[2]-raydium_vertex_z[TriIndices[0]*3+offset]) ); max_index=0; for(i=1;iname,TriIndices[0],TriIndices[1]); e->ground_texture=raydium_vertex_texture[TriIndices[max_index]*3+offset]; raydium_vertex_tag[TriIndices[max_index]*3+offset]=1; } int raydium_ode_ground_dTriCallback( dGeomID TriMesh, dGeomID RefObject, int TriangleIndex) { //printf("%i\n",TriangleIndex); raydium_vertex_tag[TriangleIndex*3]=1; return 1; } void raydium_ode_ground_set_name(char *name) { int i,j,k; int obj,size; static dTriMeshDataID Data; static int *Indices; static dReal *Vertices; static dGeomID geom; int global; char replace=0; if(raydium_ode_ground_mesh>=0) { //raydium_log("ODE: Error: Cannot change ground at runtime"); //return; // OR replace=1; dGeomDestroy(geom); dGeomTriMeshDataDestroy(Data); /* Data=dGeomTriMeshDataCreate(); dGeomTriMeshDataBuildSingle(Data,&Vertices[0],sizeof(dReal)*3,size,&Indices[0],size,3*sizeof(int)); geom=dCreateTriMesh(raydium_ode_space, Data, 0, 0, 0); */ free(Indices); free(Vertices); } obj=raydium_object_find_load(name); if(obj<0) { raydium_log("ODE: Error: cannot load ground (%s)",name); return; } // let's transform tri file format to ODE format ... size=raydium_object_end[obj]-raydium_object_start[obj]; Indices=malloc(size*sizeof(int)); Vertices=malloc(size*sizeof(dReal)*3); raydium_ode_ground_mesh=obj; for(i=raydium_object_start[obj],j=k=0;i=0) { raydium_log("ODE: Error: Cannot add object \"%s\": name already exists",name); return -1; } for(i=0;i=0) { raydium_log("ODE: Error: cannot rename '%s' to '%s': name already exists"); return 0; } strcpy(raydium_ode_object[o].name,newname); return 1; } signed char raydium_ode_object_rename_name(char *o, char *newname) { return raydium_ode_object_rename(raydium_ode_object_find(o),newname); } signed char raydium_ode_object_colliding(int o, signed char colliding) { if(!raydium_ode_object_isvalid(o)) { raydium_log("ODE: Error: cannot set object internal colliding flag: invalid name or index"); return 0; } raydium_ode_object[o].colliding=colliding; return 1; } signed char raydium_ode_object_colliding_name(char *o, signed char colliding) { return raydium_ode_object_colliding(raydium_ode_object_find(o),colliding); } void raydium_ode_object_linearvelocity_set(int o, dReal *vect) { int i; if(!raydium_ode_object_isvalid(o)) { raydium_log("ODE: Error: cannot set object linear velocity: invalid name or index"); return; } for(i=0;i=0) { raydium_log("ODE: Error: Cannot add element \"%s\": name already exists",name); return -1; } if(!raydium_ode_object_isvalid(group)) { raydium_log("ODE: Error: object not found while adding \"%s\"",name); return -1; } if(tag<0) { raydium_log("ODE: Error: Element creation failed: negative tags are forbidden"); return -1; } // First element is reserved for(i=1;i=0) { raydium_log("ODE: Cannot add element \"%s\": name already exists",name); return -1; } if(!raydium_ode_object_isvalid(group)) { raydium_log("ODE: Error: object not found while adding \"%s\"",name); return -1; } if(tag<0) { raydium_log("ODE: Error: Element creation failed: negative tags are forbidden"); return -1; } // First element is reserved for(i=1;iray.state) { e->ray.geom=dCreateRay(raydium_ode_object[raydium_ode_object_find("GLOBAL")].group,length); dGeomSetData(e->ray.geom,e); e->ray.state=1; } dGeomRaySetLength(e->ray.geom,length); e->ray.rel_dir[0]=dirx; e->ray.rel_dir[1]=diry; e->ray.rel_dir[2]=dirz; return 1; } signed char raydium_ode_element_ray_attach_name(char *element, dReal length, dReal dirx, dReal diry, dReal dirz) { return raydium_ode_element_ray_attach(raydium_ode_element_find(element),length,dirx,diry,dirz); } signed char raydium_ode_element_ray_delete(int element) { raydium_ode_Element *e; if(!raydium_ode_element_isvalid(element)) { raydium_log("ODE: Error: Cannot delete ray from element: element is not valid"); return 0; } e=&raydium_ode_element[element]; if(!e->ray.state) { raydium_log("ODE: Error: Cannot delete ray from element: there's no ray"); return 0; } dGeomDestroy(e->ray.geom); e->ray.state=0; return 1; } signed char raydium_ode_element_ray_delete_name(char *element) { return raydium_ode_element_ray_delete(raydium_ode_element_find(element)); } signed char raydium_ode_element_ray_get(int element, raydium_ode_Ray *result) { raydium_ode_Element *e; if(!raydium_ode_element_isvalid(element)) { raydium_log("ODE: Error: Cannot get ray informations: element is not valid"); return 0; } e=&raydium_ode_element[element]; if(!e->ray.state) { raydium_log("ODE: Error: Cannot get ray informations: there's no ray"); return 0; } memcpy(result,&e->ray,sizeof(raydium_ode_Ray)); return 1; } signed char raydium_ode_element_ray_get_name(char *element, raydium_ode_Ray *result) { return raydium_ode_element_ray_get(raydium_ode_element_find(element),result); } int raydium_ode_element_fix(char *name, int *elem, int nelems, signed char keepgeoms) { dReal aabb[6]; dReal aabbR[6]; dReal bounding[3]; dReal position[3]; int group; int elemN; int i,j; int done; dReal *data; dMass m; dReal mass; if(keepgeoms) raydium_log("ODE: element_fix: keepgeoms not implemented yet !"); if(raydium_ode_element_find(name)>=0) { raydium_log("ODE: Error: Cannot fix elements as \"%s\": name already exists",name); return -1; } if(nelems<1) { raydium_log("ODE: Error: Must fix at least one element"); return -1; } for(i=0;iname,raydium_ode_element[elem[i]].name); raydium_ode_element[elemN].fixed_elements[j]->type=dGeomGetClass(raydium_ode_element[elem[i]].geom); dGeomBoxGetLengths(raydium_ode_element[elem[i]].geom,raydium_ode_element[elemN].fixed_elements[j]->box_sizes); raydium_ode_element[elemN].fixed_elements[j]->sphere_radius=dGeomSphereGetRadius(raydium_ode_element[elem[i]].geom); dBodyGetMass(raydium_ode_element[elem[i]].body,&m); raydium_ode_element[elemN].fixed_elements[j]->mass=m.mass; raydium_ode_element[elemN].fixed_elements[j]->object=raydium_ode_element[elem[i]].object; raydium_ode_element[elemN].fixed_elements[j]->mesh=raydium_ode_element[elem[i]].mesh; raydium_ode_element[elemN].fixed_elements[j]->slip=raydium_ode_element[elem[i]].slip; raydium_ode_element[elemN].fixed_elements[j]->cfm=raydium_ode_element[elem[i]].cfm; raydium_ode_element[elemN].fixed_elements[j]->erp=raydium_ode_element[elem[i]].erp; data=(dReal *)dGeomGetPosition(raydium_ode_element[elem[i]].geom); memcpy(raydium_ode_element[elemN].fixed_elements[j]->rel_pos,data,sizeof(dReal)*3); raydium_ode_element[elemN].fixed_elements[j]->rel_pos[0]-=position[0]; raydium_ode_element[elemN].fixed_elements[j]->rel_pos[1]-=position[1]; raydium_ode_element[elemN].fixed_elements[j]->rel_pos[2]-=position[2]; dGeomGetQuaternion(raydium_ode_element[elem[i]].geom,raydium_ode_element[elemN].fixed_elements[j]->rel_rot); raydium_ode_element[elemN].fixed_elements[j]->user_data=raydium_ode_element[elem[i]].user_data; raydium_ode_element[elemN].fixed_elements[j]->user_tag=raydium_ode_element[elem[i]].user_tag; dBodyGetMass(raydium_ode_element[elem[i]].body,&m); raydium_ode_element[elemN].fixed_elements[j]->OnBlow=raydium_ode_element[elem[i]].OnBlow; raydium_ode_element[elemN].fixed_elements[j]->OnDelete=raydium_ode_element[elem[i]].OnDelete; mass+=m.mass; done++; j=RAYDIUM_ODE_ELEMENT_MAX_FIXING; // jump to next element to save } if(done!=nelems) raydium_log("ODE: Error: only %i/%i elems were fixed to %s ! Continue anyway...",done,nelems,name); // 4 - delete elements for(i=0;iid,pos); for(i=1;iid,diff); } } void raydium_ode_object_move_name(char *name, dReal *pos) { raydium_ode_object_move(raydium_ode_object_find(name),pos); } void raydium_ode_object_move_name_3f(char *name, dReal x,dReal y, dReal z) { dReal pos[3]; pos[0]=x; pos[1]=y; pos[2]=z; raydium_ode_object_move_name(name,pos); } // rotate object (rotation is done around LAST element of obj) void raydium_ode_object_rotateq(int obj, dReal *rot) { int i,n; raydium_ode_Element *e; raydium_ode_Element *ref; dBodyID body; dReal *pos; dReal *epos; // allocated by raydium_ode_element_pos_get(), see below //dReal vect[3]; dVector3 res; //raydium_log("obj rotate unimplemented"); return; if(!raydium_ode_object_isvalid(obj)) { raydium_log("ODE: Error: Cannot rotateq object: invalid index or name"); return; } n=dSpaceGetNumGeoms(raydium_ode_object[obj].group); if(!n) return; // 1 - rotate elements (THIS IS NOT THE CORRECT WAY TO DO IT !) for(i=1;iid,rot); } // 2 - create a temporary body (based on reference element) body=dBodyCreate(raydium_ode_world); ref=dGeomGetData(dSpaceGetGeom(raydium_ode_object[obj].group,0)); pos=raydium_ode_element_pos_get(ref->id); dBodySetPosition(body,pos[0],pos[1],pos[2]); dBodySetQuaternion(body,rot); // 3 - replace rotated elements for(i=1;iid); dBodyGetPosRelPoint(ref->body,epos[0],epos[1],epos[2],res); //printf("---> %s %f %f %f\n",e->name,res[0],res[1],res[2]); // 3 - 2 - Apply relative point to world with "fake" body dBodyGetRelPointPos(body,res[0],res[1],res[2],epos); // 3 - 3 - Change position raydium_ode_element_move(e->id,epos); } dBodyDestroy(body); raydium_ode_element_rotateq(ref->id,rot); } void raydium_ode_object_rotateq_name(char *obj, dReal *rot) { raydium_ode_object_rotateq(raydium_ode_object_find(obj),rot); } void raydium_ode_object_rotate(int obj, dReal *rot) { dMatrix3 R; dQuaternion Q; dRFromEulerAngles(R,rot[0],rot[1],rot[2]); dRtoQ(R,Q); raydium_ode_object_rotateq(obj,Q); } void raydium_ode_object_rotate_name(char *obj, dReal *rot) { raydium_ode_object_rotate(raydium_ode_object_find(obj),rot); } void raydium_ode_object_rotate_name_3f(char *obj, dReal rx, dReal ry, dReal rz) { dReal r[3]; r[0]=rx; r[1]=ry; r[2]=rz; raydium_ode_object_rotate_name(obj,r); } void raydium_ode_joint_suspension(int j, dReal erp, dReal cfm) { void (*f)(dJointID,int,dReal); int type; if(!raydium_ode_joint_isvalid(j)) { raydium_log("ODE: Cannot set ERP and CFM for this joint: invalid name or index"); return; } type=dJointGetType(raydium_ode_joint[j].joint); switch(type) { case dJointTypeHinge2: f=dJointSetHinge2Param; break; case dJointTypeHinge: f=dJointSetHingeParam; break; default: raydium_log("ODE: ERROR: suspension: joint type not supported!"); } f(raydium_ode_joint[j].joint,dParamSuspensionERP,erp); f(raydium_ode_joint[j].joint,dParamSuspensionCFM,cfm); } void raydium_ode_joint_suspension_name(char *j, dReal erp, dReal cfm) { raydium_ode_joint_suspension(raydium_ode_joint_find(j),erp,cfm); } int raydium_ode_joint_attach_hinge2(char *name, int elem1, int elem2, dReal axe1x, dReal axe1y, dReal axe1z, dReal axe2x, dReal axe2y, dReal axe2z) { int i; const dReal *a; if(raydium_ode_joint_find(name)>=0) { raydium_log("ODE: Cannot add (hinge2) joint \"%s\": name already exists",name); return -1; } if(elem1==RAYDIUM_ODE_JOINT_FIXED) elem1=RAYDIUM_ODE_MAX_ELEMENTS; if(elem2==RAYDIUM_ODE_JOINT_FIXED) elem2=RAYDIUM_ODE_MAX_ELEMENTS; if(!raydium_ode_element_isvalid(elem1) || !raydium_ode_element_isvalid(elem2)) { raydium_log("ODE: Error: Cannot attach hinge2: one element is not valid"); return -1; } if( raydium_ode_element[elem1].state==RAYDIUM_ODE_STATIC || raydium_ode_element[elem2].state==RAYDIUM_ODE_STATIC ) { raydium_log("ODE: Error: Cannot attach a static element"); return -1; } for(i=0;i=0) { raydium_log("ODE: Cannot add (universal) joint \"%s\": name already exists",name); return -1; } if(elem1==RAYDIUM_ODE_JOINT_FIXED) elem1=RAYDIUM_ODE_MAX_ELEMENTS; if(elem2==RAYDIUM_ODE_JOINT_FIXED) elem2=RAYDIUM_ODE_MAX_ELEMENTS; if(!raydium_ode_element_isvalid(elem1) || !raydium_ode_element_isvalid(elem2)) { raydium_log("ODE: Error: Cannot attach universal: one element is not valid"); return -1; } if( raydium_ode_element[elem1].state==RAYDIUM_ODE_STATIC || raydium_ode_element[elem2].state==RAYDIUM_ODE_STATIC ) { raydium_log("ODE: Error: Cannot attach a static element"); return -1; } for(i=0;i=0) { raydium_log("ODE: Cannot add (hinge) joint \"%s\": name already exists",name); return -1; } if(elem1==RAYDIUM_ODE_JOINT_FIXED) elem1=RAYDIUM_ODE_MAX_ELEMENTS; if(elem2==RAYDIUM_ODE_JOINT_FIXED) elem2=RAYDIUM_ODE_MAX_ELEMENTS; if(!raydium_ode_element_isvalid(elem1) || !raydium_ode_element_isvalid(elem2)) { raydium_log("ODE: Error: Cannot attach hinge: one element is not valid"); return -1; } if( raydium_ode_element[elem1].state==RAYDIUM_ODE_STATIC || raydium_ode_element[elem2].state==RAYDIUM_ODE_STATIC ) { raydium_log("ODE: Error: Cannot attach a static element"); return -1; } for(i=0;i=0) { raydium_log("ODE: Cannot add (fixed) joint \"%s\": name already exists",name); return -1; } if(elem1==RAYDIUM_ODE_JOINT_FIXED) elem1=RAYDIUM_ODE_MAX_ELEMENTS; if(elem2==RAYDIUM_ODE_JOINT_FIXED) elem2=RAYDIUM_ODE_MAX_ELEMENTS; if(!raydium_ode_element_isvalid(elem1) || !raydium_ode_element_isvalid(elem2)) { raydium_log("ODE: Error: Cannot attach fixed: one element is not valid"); return -1; } if( raydium_ode_element[elem1].state==RAYDIUM_ODE_STATIC || raydium_ode_element[elem2].state==RAYDIUM_ODE_STATIC ) { raydium_log("ODE: Error: Cannot attach a static element"); return -1; } //raydium_log("ODE: Warning: fixed joint slows down physics !"); for(i=0;iid; *e2=elem2->id; } void raydium_ode_joint_elements_get_name(char *j, int *e1, int *e2) { raydium_ode_joint_elements_get(raydium_ode_joint_find(j),e1,e2); } void raydium_ode_motor_update_joints_data_internal(int j) { int i; if(raydium_ode_motor_isvalid(j)) { if(raydium_ode_motor[j].state==RAYDIUM_ODE_MOTOR_ROCKET) { dReal speed; // test if element is attached: if(raydium_ode_motor[j].rocket_element<0) return; speed=raydium_ode_motor[j].speed; if(raydium_ode_motor[j].rocket_playermovement && !raydium_ode_element[raydium_ode_motor[j].rocket_element]._touched ) speed=0; if(speed!=0.f) dBodyAddRelForceAtRelPos(raydium_ode_element[raydium_ode_motor[j].rocket_element].body, raydium_ode_motor[j].rocket_direction[0], raydium_ode_motor[j].rocket_direction[1], raydium_ode_motor[j].rocket_direction[2], raydium_ode_motor[j].rocket_position[0], raydium_ode_motor[j].rocket_position[1], raydium_ode_motor[j].rocket_position[2]); return; } // if motor is anything else than a rocket: for(i=0;i=0) { void (*SetParam)(dJointID,int,dReal); dReal (*GetAngle)(dJointID); int vel; int fmax; int type; char cancel=0; switch(raydium_ode_motor[j].joints_axe[i]) { case 0: vel=dParamVel; fmax=dParamFMax; break; case 1: vel=dParamVel2; fmax=dParamFMax2; break; case 2: vel=dParamVel3; fmax=dParamFMax3; break; default: cancel=1; raydium_log("ODE: Motor: Invalid axe for this joint (%s, motor is %s)",raydium_ode_joint[raydium_ode_motor[j].joints[i]].name,raydium_ode_motor[j].name); } type=dJointGetType(raydium_ode_joint[raydium_ode_motor[j].joints[i]].joint); switch(type) { case dJointTypeHinge2: SetParam=dJointSetHinge2Param; GetAngle=dJointGetHinge2Angle1; if(raydium_ode_motor[j].joints_axe[i]!=0 && raydium_ode_motor[j].state==RAYDIUM_ODE_MOTOR_ANGULAR) { cancel=1; raydium_log("ODE: Only axe Hinge2 axe 0 is supported with angular motors (%s, motor is %s)",raydium_ode_joint[raydium_ode_motor[j].joints[i]].name,raydium_ode_motor[j].name); } break; case dJointTypeHinge: SetParam=dJointSetHingeParam; GetAngle=dJointGetHingeAngle; break; default: cancel=1; raydium_log("ODE: Motor: Invalid joint type (%s, motor is %s)",raydium_ode_joint[raydium_ode_motor[j].joints[i]].name,raydium_ode_motor[j].name); } if(cancel) continue; // previous tests failed if(raydium_ode_motor[j].state==RAYDIUM_ODE_MOTOR_ENGINE) { dReal speed; dReal force; speed=raydium_ode_motor[j].speed*raydium_ode_motor[j].gears[raydium_ode_motor[j].gear]; if(raydium_ode_motor[j].gears[raydium_ode_motor[j].gear]==0.0) force=0; else force=raydium_ode_motor[j].force*(1/raydium_ode_motor[j].gears[raydium_ode_motor[j].gear]); // force=raydium_ode_motor[j].force; // raydium_log("speed=%f force=%f",speed,force); SetParam(raydium_ode_joint[raydium_ode_motor[j].joints[i]].joint,vel,speed); SetParam(raydium_ode_joint[raydium_ode_motor[j].joints[i]].joint,fmax,force); } if(raydium_ode_motor[j].state==RAYDIUM_ODE_MOTOR_ANGULAR) { dReal v; SetParam(raydium_ode_joint[raydium_ode_motor[j].joints[i]].joint,fmax,raydium_ode_motor[j].force); v = raydium_ode_motor[j].angle - GetAngle(raydium_ode_joint[raydium_ode_motor[j].joints[i]].joint); SetParam(raydium_ode_joint[raydium_ode_motor[j].joints[i]].joint,vel,v*10); } } return; } raydium_log("ODE: Error (internal): motor update failed: not found"); } void raydium_ode_motor_speed(int j, dReal force) { if(raydium_ode_motor_isvalid(j)) { raydium_ode_motor[j].speed=force; // refresh direction using direction and speed: if(raydium_ode_motor[j].state==RAYDIUM_ODE_MOTOR_ROCKET) raydium_ode_motor_rocket_orientation(j,raydium_ode_motor[j].rocket_orientation[0],raydium_ode_motor[j].rocket_orientation[1],raydium_ode_motor[j].rocket_orientation[2]); return; } raydium_log("ODE: Error: cannot set motor's speed: invalid index or name"); } void raydium_ode_motor_speed_name(char *name, dReal force) { raydium_ode_motor_speed(raydium_ode_motor_find(name),force); } // power = 0 means motor has no effect on joints (free moves) void raydium_ode_motor_power_max(int j, dReal power) { if(raydium_ode_motor_isvalid(j)) { raydium_ode_motor[j].force=power; return; } raydium_log("ODE: Error: cannot set max motor's power: invalid index or name"); } void raydium_ode_motor_power_max_name(char *name, dReal power) { raydium_ode_motor_power_max(raydium_ode_motor_find(name),power); } void raydium_ode_motor_angle(int j, dReal angle) { if(raydium_ode_motor_isvalid(j)) { raydium_ode_motor[j].angle=angle; return; } raydium_log("ODE: Error: cannot set motor's angle: invalid index or name"); } void raydium_ode_motor_angle_name(char *motor, dReal angle) { raydium_ode_motor_angle(raydium_ode_motor_find(motor),angle); } void raydium_ode_motor_gears_set(int m,dReal *gears, int n_gears) { if(raydium_ode_motor_isvalid(m)) { if(raydium_ode_motor[m].state!=RAYDIUM_ODE_MOTOR_ENGINE) { raydium_log("ODE: Error: cannot use a gearbox with a non-engine motor"); return; } memcpy(raydium_ode_motor[m].gears,gears,sizeof(dReal)*n_gears); raydium_ode_motor[m].gear_max=n_gears-1; return; } raydium_log("ODE: Error: cannot configure motor's gears: invalid index or name"); } void raydium_ode_motor_gears_set_name(char *m,dReal *gears,int n_gears) { raydium_ode_motor_gears_set(raydium_ode_motor_find(m),gears,n_gears); } void raydium_ode_motor_gear_change(int m, int gear) { if(raydium_ode_motor_isvalid(m)) { if(gear<0 || gear>raydium_ode_motor[m].gear_max) { raydium_log("ODE: Error: invalid gear (%i)",gear); return; } raydium_ode_motor[m].gear=gear; return; } raydium_log("ODE: Error: cannot set motor's gear: invalid index or name"); } void raydium_ode_motor_gear_change_name(char *m, int gear) { raydium_ode_motor_gear_change(raydium_ode_motor_find(m),gear); } dReal *raydium_ode_element_pos_get(int j) { if(raydium_ode_element_isvalid(j)) { return (dReal *)dGeomGetPosition(raydium_ode_element[j].geom); } raydium_log("ODE: Error: cannot get element position: invalid index or name"); return NULL; } dReal *raydium_ode_element_pos_get_name(char *name) { return raydium_ode_element_pos_get(raydium_ode_element_find(name)); } signed char raydium_ode_element_rotq_get(int j, dReal * res) { if(raydium_ode_element_isvalid(j)) { dGeomGetQuaternion(raydium_ode_element[j].geom,res); return 1; } raydium_log("ODE: Error: cannot get element rotation (quaternion): invalid index or name"); return 0; } signed char raydium_ode_element_rotq_get_name(char *name, dReal * res) { return raydium_ode_element_rotq_get(raydium_ode_element_find(name),res); } /* signed char raydium_ode_element_rot_get(int e, dReal *rx, dReal *ry, dReal *rz) { // From Andrzej Szombierski (ODE ML) // patched by Daniel Monteiro Basso (ODE ML) // but it's not what i want, again.. arrrgh ;) const dReal epsilon=0.0000001; dReal *matrix; dReal c; if(raydium_ode_element_isvalid(e)) { matrix=(dReal *)dGeomGetRotation(raydium_ode_element[e].geom); if(matrix[2] < 1-epsilon && matrix[2] > -1+epsilon) { *ry=-asin(matrix[2]); c=cos(*ry); *rx= atan2(matrix[6]/c,matrix[10]/c); *rz= atan2(matrix[1]/c,matrix[0]/c); } else { *rz=0; *ry=-atan2(matrix[2],0); *rx= atan2(-matrix[9],matrix[5]); } // rad to deg //(*rx)*=180/PI; //(*ry)*=180/PI; //(*rz)*=180/PI; return 1; } raydium_log("ODE: Error: cannot get element rotation (3f): invalid index or name"); return 0; } */ signed char raydium_ode_element_rot_get(int e, dReal *rx, dReal *ry, dReal *rz) { // From Andrzej Szombierski (ODE ML) // Original code version: "absolute" angles // Do not apply back returned angles ! (not ODE "formated") const dReal epsilon=0.0000001; dReal *matrix; dReal c; if(raydium_ode_element_isvalid(e)) { matrix=(dReal *)dGeomGetRotation(raydium_ode_element[e].geom); if(matrix[8] < 1-epsilon && matrix[8] > -1+epsilon) { *ry=-asin(matrix[8]); c=cos(*ry); *rx= atan2(matrix[9]/c,matrix[10]/c); *rz= atan2(matrix[4]/c,matrix[0]/c); } else { *rz=0; *ry=-atan2(matrix[8],0); *rx= atan2(-matrix[6],matrix[5]); } // rad to deg //(*rx)*=180/PI; //(*ry)*=180/PI; //(*rz)*=180/PI; return 1; } raydium_log("ODE: Error: cannot get element rotation (3f): invalid index or name"); return 0; } signed char raydium_ode_element_rot_get_name(char *e, dReal *rx, dReal *ry, dReal *rz) { return raydium_ode_element_rot_get(raydium_ode_element_find(e),rx,ry,rz); } void raydium_ode_element_sound_update(int e, int source) { if(raydium_ode_element_isvalid(e)) { dReal *pos; pos=raydium_ode_element_pos_get(e); raydium_sound_SetSourcePos(source,pos); return; } raydium_log("ODE: Error: cannot update source: invalid index or name"); return; } void raydium_ode_element_sound_update_name(char *e, int source) { raydium_ode_element_sound_update(raydium_ode_element_find(e),source); } void raydium_ode_element_RelPointPos(int e, dReal px, dReal py, dReal pz, dReal *res) { if(!raydium_ode_element_isvalid(e)) { raydium_log("ODE: Error: cannot get RelPointPos: invalid index or name"); return; } if(raydium_ode_element[e].state==RAYDIUM_ODE_STATIC) { raydium_log("ODE: Error: Cannot get RelPointPos on a static element"); return; } dBodyGetRelPointPos(raydium_ode_element[e].body,px,py,pz,res); } void raydium_ode_element_RelPointPos_name(char *e, dReal px, dReal py, dReal pz, dReal *res) { raydium_ode_element_RelPointPos(raydium_ode_element_find(e),px,py,pz,res); } int raydium_ode_motor_create(char *name, int obj, signed char type) { int i; if(raydium_ode_motor_find(name)>=0) { raydium_log("ODE: Cannot add motor \"%s\": name already exists",name); return -1; } if(!raydium_ode_object_isvalid(obj)) { raydium_log("ODE: Cannot add motor \"%s\": parent object is invalid",name); return -1; } for(i=0;iid; e2=elem2->id; if(raydium_ode_motor[motor].object!=raydium_ode_element[e1].object && raydium_ode_motor[motor].object!=raydium_ode_element[e2].object ) { raydium_log("ODE: Cannot attach motor: joint must be attached to at least one element from motor's object"); return; } for(i=0;i=0) { body=dJointGetBody(raydium_ode_joint[raydium_ode_motor[m].joints[i]].joint,raydium_ode_motor[m].joints_axe[i]); vel=(dReal *)dBodyGetAngularVel(body); velf+=sqrt(vel[0]*vel[0] + vel[1]*vel[1] + vel[2]*vel[2]); n++; } if(n) { velf/=n; if(gears) velf*=(1/raydium_trigo_abs(raydium_ode_motor[m].gears[raydium_ode_motor[m].gear])); } else velf=0; return velf; } dReal raydium_ode_motor_speed_get_name(char *name, int gears) { return raydium_ode_motor_speed_get(raydium_ode_motor_find(name),gears); } void raydium_ode_motor_rocket_set(int m, int element, dReal x, dReal y, dReal z) { if(!raydium_ode_motor_isvalid(m) || !raydium_ode_element_isvalid(element)) { raydium_log("ODE: Error: Cannot set rocket element: invalid name or index"); return; } if(raydium_ode_motor[m].state!=RAYDIUM_ODE_MOTOR_ROCKET) { raydium_log("ODE: Error: Cannot set rocket element: motor is not a rocket"); return; } raydium_ode_motor[m].rocket_element=element; raydium_ode_motor[m].rocket_position[0]=x; raydium_ode_motor[m].rocket_position[1]=y; raydium_ode_motor[m].rocket_position[2]=z; } void raydium_ode_motor_rocket_set_name(char *motor,char *element, dReal x, dReal y, dReal z) { raydium_ode_motor_rocket_set(raydium_ode_motor_find(motor),raydium_ode_element_find(element),x,y,z); } void raydium_ode_motor_rocket_orientation(int m, dReal rx, dReal ry, dReal rz) { GLfloat res[3]; GLfloat dir[3]={0,0,1}; if(!raydium_ode_motor_isvalid(m)) { raydium_log("ODE: Error: Cannot set rocket orientation: invalid name or index"); return; } if(raydium_ode_motor[m].state!=RAYDIUM_ODE_MOTOR_ROCKET) { raydium_log("ODE: Error: Cannot set rocket orientation: motor is not a rocket"); return; } raydium_ode_motor[m].rocket_orientation[0]=rx; raydium_ode_motor[m].rocket_orientation[1]=ry; raydium_ode_motor[m].rocket_orientation[2]=rz; raydium_trigo_rotate(dir,rx,ry,rz,res); res[0]*=raydium_ode_motor[m].speed; res[1]*=raydium_ode_motor[m].speed; res[2]*=raydium_ode_motor[m].speed; raydium_ode_motor[m].rocket_direction[0]=res[0]; raydium_ode_motor[m].rocket_direction[1]=res[1]; raydium_ode_motor[m].rocket_direction[2]=res[2]; } void raydium_ode_motor_rocket_orientation_name(char *name, dReal rx, dReal ry, dReal rz) { raydium_ode_motor_rocket_orientation(raydium_ode_motor_find(name),rx,ry,rz); } void raydium_ode_motor_rocket_playermovement(int m, signed char isplayermovement) { if(!raydium_ode_motor_isvalid(m)) { raydium_log("ODE: Error: Cannot set rocket type (player movement): invalid name or index"); return; } if(raydium_ode_motor[m].state!=RAYDIUM_ODE_MOTOR_ROCKET) { raydium_log("ODE: Error: Cannot set rocket type (player movement): motor is not a rocket"); return; } raydium_ode_motor[m].rocket_playermovement=isplayermovement; } void raydium_ode_motor_rocket_playermovement_name(char *m, signed char isplayermovement) { return raydium_ode_motor_rocket_playermovement(raydium_ode_motor_find(m),isplayermovement); } signed char raydium_ode_motor_delete(int e) { if(!raydium_ode_motor_isvalid(e)) { raydium_log("ODE: Error: Cannot delete motor: invalid name or index"); return 0; } raydium_ode_init_motor(e); return 1; } signed char raydium_ode_motor_delete_name(char *name) { return raydium_ode_motor_delete(raydium_ode_motor_find(name)); } signed char raydium_ode_joint_delete(int joint) { int i,j; void (*f)(int); if(!raydium_ode_joint_isvalid(joint)) { raydium_log("ODE: Error: Cannot delete joint: invalid name or index"); return 0; } for(i=0;iid; else to_delete[i]=-1; } // ... and delete joints for(i=0;i=0) raydium_ode_joint_delete(to_delete[i]); free(to_delete); } } if(raydium_ode_element[e].ray.state) raydium_ode_element_ray_delete(e); dGeomSetData(raydium_ode_element[e].geom,NULL); // no more linked to this structure dGeomDestroy(raydium_ode_element[e].geom); if(raydium_ode_element[e].body) dBodyDestroy(raydium_ode_element[e].body); for(i=0;i=0) raydium_particle_generator_delete(raydium_ode_element[e].particle); raydium_ode_init_element(e); return 1; } signed char raydium_ode_element_delete_name(char *name, signed char deletejoints) { return raydium_ode_element_delete(raydium_ode_element_find(name),deletejoints); } signed char raydium_ode_object_delete(int obj) { int i; //raydium_ode_Element *e; if(!raydium_ode_object_isvalid(obj)) { raydium_log("ODE: Error: Cannot delete object: invalid name or index"); return 0; } if(obj == raydium_ode_object_find("GLOBAL")) { raydium_log("ODE: Error: Cannot delete special \"GLOBAL\" object"); return 0; } for(i=0;iid,1); // } // So i'll search for bodies in my own structures for(i=0;i=0) raydium_ode_element_delete(raydium_ode_explosion[e].element,0); raydium_ode_init_explosion(e); return 1; } signed char raydium_ode_element_moveto(int element, int object, signed char deletejoints) { int i; raydium_ode_Joint *j; dBodyID e1,e2; if(!raydium_ode_element_isvalid(element) || !raydium_ode_object_isvalid(object) ) { raydium_log("ODE: Error: Cannot move element to object: invalid index/name"); return 0; } for(i=0;iid); else { e1=dJointGetBody(j->joint,0); e2=dJointGetBody(j->joint,1); if(e1==raydium_ode_element[element].body) e1=0; if(e2==raydium_ode_element[element].body) e2=0; dJointAttach(j->joint,e1,e2); } } // Well well well.. donno if dGeomGroupAdd removes body from previous // GeomGroup, so i do it myself. raydium_ode_element[element]._movesfrom=raydium_ode_element[element].object; dSpaceRemove(raydium_ode_object[raydium_ode_element[element].object].group, raydium_ode_element[element].geom); raydium_ode_element[element].object=object; dSpaceAdd(raydium_ode_object[raydium_ode_element[element].object].group, raydium_ode_element[element].geom); return 1; } signed char raydium_ode_element_moveto_name(char *element, char *object, char signed deletejoints) { return raydium_ode_element_moveto(raydium_ode_element_find(element),raydium_ode_object_find(object),deletejoints); } void raydium_ode_joint_break(int j) { dJointFeedback *jf; dReal force=0; if(!raydium_ode_joint[j].breakableforce) return; if(!raydium_ode_joint_isvalid(j)) { raydium_log("ODE: Error: cannot test joint breaking: invalid index/name"); return; } jf=dJointGetFeedback(raydium_ode_joint[j].joint); if(!jf) return; force+=raydium_trigo_abs(jf->f1[0]); force+=raydium_trigo_abs(jf->f1[1]); force+=raydium_trigo_abs(jf->f1[2]); force+=raydium_trigo_abs(jf->f2[0]); force+=raydium_trigo_abs(jf->f2[1]); force+=raydium_trigo_abs(jf->f2[2]); //raydium_log("%f %s",force,raydium_ode_joint[j].name); if(force>raydium_ode_joint[j].breakableforce) { raydium_ode_joint[j].breaking=1; raydium_ode_joint_delete(j); } } signed char raydium_ode_launcher(int element, int from_element, dReal *rot, dReal force) { dReal res[3]; dReal *initial; dVector3 final; dReal dir[3]={0,0,1}; if(!raydium_ode_element_isvalid(element) || !raydium_ode_element_isvalid(from_element) ) { raydium_log("ODE: Cannot launch element: invalid name or index"); return 0; } if( raydium_ode_element[from_element].state==RAYDIUM_ODE_STATIC || raydium_ode_element[element].state==RAYDIUM_ODE_STATIC ) { raydium_log("ODE: Cannot launch element: you must use non-static elements"); return 0; } raydium_trigo_rotate(dir,rot[0],rot[1],rot[2],res); res[0]*=force; res[1]*=force; res[2]*=force; dBodyVectorToWorld(raydium_ode_element[from_element].body,res[0],res[1],res[2],final); initial=(dReal *)dBodyGetLinearVel(raydium_ode_element[from_element].body); final[0]+=initial[0]; final[1]+=initial[1]; final[2]+=initial[2]; dBodyAddForce(raydium_ode_element[element].body,final[0],final[1],final[2]); return 1; } signed char raydium_ode_launcher_name(char *element, char *from_element, dReal *rot, dReal force) { return raydium_ode_launcher(raydium_ode_element_find(element),raydium_ode_element_find(from_element),rot,force); } signed char raydium_ode_launcher_name_3f(char *element, char *from_element, dReal rx, dReal ry, dReal rz, dReal force) { dReal tmp[3]; tmp[0]=rx; tmp[1]=ry; tmp[2]=rz; return raydium_ode_launcher_name(element,from_element,tmp,force); } signed char raydium_ode_launcher_simple(int element, int from_element, dReal *lrot, dReal force) { dReal *pos; dQuaternion rot; if(!raydium_ode_element_isvalid(element) || !raydium_ode_element_isvalid(from_element) ) { raydium_log("ODE: Cannot (simple) launch element: invalid name or index"); return 0; } // test if element and from_element are from the same objet if(raydium_ode_element[element].object!=raydium_ode_element[from_element].object) { raydium_log("ODE: Cannot (simple) launch element: element and from_element are not from the same object"); return 0; } pos=raydium_ode_element_pos_get(from_element); raydium_ode_element_rotq_get(from_element,rot); raydium_ode_element_move(element,pos); raydium_ode_element_rotateq(element,rot); raydium_ode_launcher(element,from_element,lrot,force); raydium_ode_element_moveto(element,raydium_ode_object_find("GLOBAL"),0); return 1; } signed char raydium_ode_launcher_simple_name(char *element, char *from_element, dReal *rot, dReal force) { return raydium_ode_launcher_simple(raydium_ode_element_find(element),raydium_ode_element_find(from_element),rot,force); } signed char raydium_ode_launcher_simple_name_3f(char *element, char *from_element, dReal rx, dReal ry, dReal rz, dReal force) { dReal tmp[3]; tmp[0]=rx; tmp[1]=ry; tmp[2]=rz; return raydium_ode_launcher_simple_name(element,from_element,tmp,force); } void raydium_ode_explosion_blow_rand(dReal radius, dReal max_force, dReal rand_factor, dReal *pos) { int i; void (*f)(signed char, dReal, dReal, dReal *); void (*g)(int, dReal, dReal); float rmx[3]; float minrandtorq, maxrandtorq; if(raydium_network_mode==RAYDIUM_NETWORK_MODE_CLIENT && !raydium_ode_network_explosion_create) { // propag over network raydium_ode_network_Explosion exp; exp.type=RAYDIUM_ODE_NETWORK_EXPLOSION_BLOW; exp.radius=radius; memcpy(exp.pos,pos,sizeof(dReal)*3); exp.force=max_force; raydium_ode_network_explosion_send(&exp); return; } raydium_ode_network_explosion_create=0; for(i=0;iradius) continue; force = ((radius*radius) - (len*len)) / (radius * radius) * max_force; // raydium_log("resulting force: %f (max force at core=%f)",force,max_force); vect[0]*=force; vect[1]*=force; vect[2]*=force; // raydium_log("resulting impulse vector: [%f %f %f]",vect[0],vect[1],vect[2]); dBodyAddForce(raydium_ode_element[i].body,vect[0],vect[1],vect[2]); if(rand_factor) { //ugly way of get a random float array minrandtorq=-rand_factor; maxrandtorq= rand_factor; rmx[0]=raydium_random_f(minrandtorq,maxrandtorq)*force; rmx[1]=raydium_random_f(minrandtorq,maxrandtorq)*force; rmx[2]=raydium_random_f(minrandtorq,maxrandtorq)*force; //added random torque to the pieces dBodyAddTorque(raydium_ode_element[i].body,rmx[0],rmx[1],rmx[2]); } g=raydium_ode_element[i].OnBlow; if(g) g(i,force,max_force); } f=raydium_ode_ExplosionCallback; if(f) f(RAYDIUM_ODE_NETWORK_EXPLOSION_BLOW,radius,max_force,pos); } void raydium_ode_explosion_blow(dReal radius, dReal max_force, dReal *pos) { raydium_ode_explosion_blow_rand(radius,max_force,0,pos); } void raydium_ode_explosion_blow_3f(dReal radius, dReal max_force, dReal px, dReal py, dReal pz) { dReal pos[3]; pos[0]=px; pos[1]=py; pos[2]=pz; raydium_ode_explosion_blow(radius,max_force,pos); } void raydium_ode_explosion_blow_rand_3f(dReal radius, dReal max_force, dReal rand_factor, dReal px, dReal py, dReal pz) { dReal pos[3]; pos[0]=px; pos[1]=py; pos[2]=pz; raydium_ode_explosion_blow_rand(radius,max_force,rand_factor,pos); } int raydium_ode_explosion_create(char *name, dReal final_radius, dReal propag, dReal *pos) { int i; void (*f)(signed char, dReal, dReal, dReal *); if(raydium_network_mode==RAYDIUM_NETWORK_MODE_CLIENT && !raydium_ode_network_explosion_create) { // propag over network raydium_ode_network_Explosion exp; exp.type=RAYDIUM_ODE_NETWORK_EXPLOSION_EXPL; exp.radius=final_radius; memcpy(exp.pos,pos,sizeof(dReal)*3); exp.propag=propag; raydium_ode_network_explosion_send(&exp); return -1; // WARNING: During networked games, this function always returns -1 } raydium_ode_network_explosion_create=0; if(raydium_ode_explosion_find(name)>=0) { raydium_log("ODE: Cannot add explosion \"%s\": name already exists",name); return -1; } for(i=0;i",raydium_ode_joint[i].name); } } for(i=0;i=0) { if(raydium_shadow_rendering) raydium_shadow_object_draw(raydium_ode_element[i].mesh); else raydium_object_draw(raydium_ode_element[i].mesh); } if(names!=RAYDIUM_ODE_DRAW_SHADOWERS && aft) aft(i); if(raydium_ode_element[i].particle>=0 && names!=RAYDIUM_ODE_DRAW_SHADOWERS) { dVector3 res; // if element is static, fake a temporary body if(raydium_ode_element[i].state==RAYDIUM_ODE_STATIC) { dBodyID body; dReal *pos; dQuaternion rot; body=dBodyCreate(raydium_ode_world); pos=raydium_ode_element_pos_get(i); raydium_ode_element_rotq_get(i,rot); dBodySetPosition(body,pos[0],pos[1],pos[2]); dBodySetQuaternion(body,rot); dBodyGetRelPointPos(body, raydium_ode_element[i].particle_offset[0], raydium_ode_element[i].particle_offset[1], raydium_ode_element[i].particle_offset[2], res); dBodyDestroy(body); } else if(raydium_ode_element[i].state==RAYDIUM_ODE_STANDARD) { dBodyGetRelPointPos(raydium_ode_element[i].body, raydium_ode_element[i].particle_offset[0], raydium_ode_element[i].particle_offset[1], raydium_ode_element[i].particle_offset[2], res); } raydium_particle_generator_move( raydium_ode_element[i].particle,res); } for(j=0;jrel_pos[0], raydium_ode_element[i].fixed_elements[j]->rel_pos[1], raydium_ode_element[i].fixed_elements[j]->rel_pos[2]); { dMatrix3 R; GLfloat matrix[16]; dQtoR(raydium_ode_element[i].fixed_elements[j]->rel_rot,R); matrix[0]=R[0]; matrix[1]=R[4]; matrix[2]=R[8]; matrix[3]=0; matrix[4]=R[1]; matrix[5]=R[5]; matrix[6]=R[9]; matrix[7]=0; matrix[8]=R[2]; matrix[9]=R[6]; matrix[10]=R[10]; matrix[11]=0; matrix[12]=0; matrix[13]=0; matrix[14]=0; matrix[15]=1; glMultMatrixf (matrix); } raydium_object_draw(raydium_ode_element[i].fixed_elements[j]->mesh); glPopMatrix(); } } else { const dReal *p; if(names==RAYDIUM_ODE_DRAW_DEBUG) // draw shape { raydium_rendering_internal_prepare_texture_render(0); // !!! raydium_texture_current_set_name("rgb(1,0,0)"); raydium_camera_replace_go((dReal *)dGeomGetPosition(raydium_ode_element[i].geom), (dReal *)dGeomGetRotation(raydium_ode_element[i].geom)); raydium_rendering_internal_prepare_texture_render(raydium_texture_current_main); if(dGeomGetClass(raydium_ode_element[i].geom)==dBoxClass) { dVector3 sides; float lx; float ly; float lz; dGeomBoxGetLengths(raydium_ode_element[i].geom,sides); lx = sides[0]*0.5f; ly = sides[1]*0.5f; lz = sides[2]*0.5f; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // sides glBegin (GL_TRIANGLE_STRIP); glNormal3f (-1,0,0); glVertex3f (-lx,-ly,-lz); glVertex3f (-lx,-ly,lz); glVertex3f (-lx,ly,-lz); glVertex3f (-lx,ly,lz); glNormal3f (0,1,0); glVertex3f (lx,ly,-lz); glVertex3f (lx,ly,lz); glNormal3f (1,0,0); glVertex3f (lx,-ly,-lz); glVertex3f (lx,-ly,lz); glNormal3f (0,-1,0); glVertex3f (-lx,-ly,-lz); glVertex3f (-lx,-ly,lz); glEnd(); // top face glBegin (GL_TRIANGLE_FAN); glNormal3f (0,0,1); glVertex3f (-lx,-ly,lz); glVertex3f (lx,-ly,lz); glVertex3f (lx,ly,lz); glVertex3f (-lx,ly,lz); glEnd(); // bottom face glBegin (GL_TRIANGLE_FAN); glNormal3f (0,0,-1); glVertex3f (-lx,-ly,-lz); glVertex3f (-lx,ly,-lz); glVertex3f (lx,ly,-lz); glVertex3f (lx,-ly,-lz); glEnd(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } else //if(dGeomGetClass(raydium_ode_element[i].geom)==dSphereClass) { glutWireSphere(dGeomSphereGetRadius(raydium_ode_element[i].geom),10,10); } p=dGeomGetPosition(raydium_ode_element[i].geom); if(raydium_ode_element[i]._touched) raydium_osd_color_ega('c'); else raydium_osd_color_ega('f'); if(raydium_ode_element[i]._avoidedcol) raydium_osd_color_ega('d'); if(!dGeomIsEnabled(raydium_ode_element[i].geom)) raydium_osd_color_ega('a'); if( raydium_ode_element[i].state==RAYDIUM_ODE_STANDARD && !dBodyIsEnabled(raydium_ode_element[i].body) ) raydium_osd_color_ega('0'); raydium_osd_printf_3D(p[0],p[1],p[2],12,0.6,"font2.tga","%i %s (%s) @ %i",i,raydium_ode_element[i].name,raydium_ode_object[raydium_ode_element[i].object].name,raydium_ode_element[i].distant_owner); } if(names==RAYDIUM_ODE_DRAW_AABB) // draw AABB { dReal aabb[6]; raydium_camera_replace(); raydium_rendering_internal_prepare_texture_render(0); // !! raydium_texture_current_set_name("rgb(0,0,1)"); raydium_rendering_internal_prepare_texture_render(raydium_texture_current_main); dGeomGetAABB(raydium_ode_element[i].geom,aabb); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // sides glBegin (GL_TRIANGLE_STRIP); glNormal3f (-1,0,0); glVertex3f (aabb[0],aabb[2],aabb[4]); glVertex3f (aabb[0],aabb[2],aabb[5]); glVertex3f (aabb[0],aabb[3],aabb[4]); glVertex3f (aabb[0],aabb[3],aabb[5]); glNormal3f (0,1,0); glVertex3f (aabb[1],aabb[3],aabb[4]); glVertex3f (aabb[1],aabb[3],aabb[5]); glNormal3f (1,0,0); glVertex3f (aabb[1],aabb[2],aabb[4]); glVertex3f (aabb[1],aabb[2],aabb[5]); glNormal3f (0,-1,0); glVertex3f (aabb[0],aabb[2],aabb[4]); glVertex3f (aabb[0],aabb[2],aabb[5]); glEnd(); // top face glBegin (GL_TRIANGLE_FAN); glNormal3f (0,0,1); glVertex3f (aabb[0],aabb[2],aabb[5]); glVertex3f (aabb[1],aabb[2],aabb[5]); glVertex3f (aabb[1],aabb[3],aabb[5]); glVertex3f (aabb[0],aabb[3],aabb[5]); glEnd(); // bottom face glBegin (GL_TRIANGLE_FAN); glNormal3f (0,0,-1); glVertex3f (aabb[0],aabb[2],aabb[4]); glVertex3f (aabb[0],aabb[3],aabb[4]); glVertex3f (aabb[1],aabb[3],aabb[4]); glVertex3f (aabb[1],aabb[2],aabb[4]); glEnd(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } if(names==RAYDIUM_ODE_DRAW_RAY) { if(raydium_ode_element[i].ray.state) { dVector3 start,dir; dReal len; raydium_rendering_internal_prepare_texture_render(0); // !!! raydium_texture_current_set_name("rgb(1,0,0)"); raydium_rendering_internal_prepare_texture_render(raydium_texture_current_main); dGeomRayGet(raydium_ode_element[i].ray.geom,start,dir); len=dGeomRayGetLength(raydium_ode_element[i].ray.geom); raydium_camera_replace(); glBegin(GL_LINES); //printf("%f %f %f | %f %f %f\n",start[0],start[1],start[2],dir[0],dir[1],dir[2]); glVertex3f(start[0],start[1],start[2]); glVertex3f(start[0]+(dir[0]*len),start[1]+(dir[1]*len),start[2]+(dir[2]*len)); glEnd(); } } } } if(names==RAYDIUM_ODE_DRAW_NORMAL) // but not RAYDIUM_ODE_DRAW_NORMAL_NO_POST { raydium_hdr_map(); // create HDR map raydium_shadow_map_render(); } } void raydium_ode_near_callback(void *data, dGeomID o1, dGeomID o2) { int i,n; // dirty, but... #define N 400 static dContact contact[N]; dJointID c; raydium_ode_Element *e1, *e2; int ground_elem_id,distan_obj_id; dReal erp=0; dReal cfm=0; dReal slip=0; int count=0; signed char (*f)(int,int, dContact *); signed char (*r)(int,int, dContact *); f=raydium_ode_CollideCallback; r=raydium_ode_RayCallback; if(dGeomIsSpace (o1) || dGeomIsSpace (o2)) { raydium_ode_Object *oo1, *oo2; signed char (*g)(int,int); oo1=dGeomGetData(o1); oo2=dGeomGetData(o2); g=raydium_ode_ObjectNearCollide; if(g && !g(oo1->id,oo2->id)) return; dSpaceCollide2 (o1,o2,data,&raydium_ode_near_callback); return; } ground_elem_id=raydium_ode_element_find("ground"); distan_obj_id=raydium_ode_object_find("DISTANT"); e1=dGeomGetData(o1); e2=dGeomGetData(o2); /* // avoid "ground - distant elements" contacts (may do it for all static-static contacts ?) if(e1->id == ground_elem_id && e2->object == distan_obj_id) return; if(e2->id == ground_elem_id && e1->object == distan_obj_id) return; // . */ // As said above, we will avoid all static-statics contacts. // I think we must provide a "pre-filter" callback, since the user // may need this contact infos if(e1->state==RAYDIUM_ODE_STATIC && e2->state==RAYDIUM_ODE_STATIC) return; n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact)); if(n>=N-1) raydium_log("ODE: WARNING ! Not enought contact points available ! (%i max)",N); if (n > 0) { for (i=0; imarked_as_deleted) return; if(e2 && e2->marked_as_deleted) return; if( e1 && e2 && e1->_movesfrom>=0 && e1->_movesfrom==e2->object) { e1->_avoidedcol=1; continue; // avoid collision ! (where are moving from this object) } if( e1 && e2 && e2->_movesfrom>=0 && e2->_movesfrom==e1->object) { e2->_avoidedcol=1; continue; // avoid collision ! (where are moving from this object) } erp=cfm=slip=0; if(e1) { erp=e1->erp; cfm=e1->cfm; slip=e1->slip; count=1; } if(e2) { erp+=e2->erp; cfm+=e2->cfm; slip+=e2->slip; count++; } if(count) { erp/=count; cfm/=count; slip/=count; } contact[i].surface.mode = dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM | dContactApprox1; contact[i].surface.mu = dInfinity; contact[i].surface.slip1 = slip; contact[i].surface.slip2 = slip; contact[i].surface.soft_erp = erp; contact[i].surface.soft_cfm = cfm; if(dGeomGetClass(contact[i].geom.g1)==dRayClass) { // raydium_ode_RayCallback (1) if(r) { int id1,id2; id1=id2=-1; if(e1) id1=e1->id; if(e2) id2=e2->id; if(!r(id1,id2,&contact[i])) continue; } if(e1 && e2 && (e1->ray.min_dist > contact[i].geom.depth || e1->ray.min_dist==0) ) { e1->ray.min_dist=contact[i].geom.depth; e1->ray.min_elem=e2->id; memcpy(e1->ray.min_pos,contact[i].geom.pos,sizeof(dReal)*3); } if(e1 && e2 && e1->ray.max_dist < contact[i].geom.depth) { e1->ray.max_dist=contact[i].geom.depth; e1->ray.max_elem=e2->id; memcpy(e1->ray.max_pos,contact[i].geom.pos,sizeof(dReal)*3); } continue; } if(dGeomGetClass(contact[i].geom.g2)==dRayClass) { // raydium_ode_RayCallback (2) if(r) { int id1,id2; id1=id2=-1; if(e1) id1=e1->id; if(e2) id2=e2->id; if(!r(id1,id2,&contact[i])) continue; } if(e1 && e2 && (e2->ray.min_dist > contact[i].geom.depth || e2->ray.min_dist==0) ) { e2->ray.min_dist=contact[i].geom.depth; e2->ray.min_elem=e1->id; memcpy(e2->ray.min_pos,contact[i].geom.pos,sizeof(dReal)*3); } if(e1 && e2 && e2->ray.max_dist < contact[i].geom.depth) { e2->ray.max_dist=contact[i].geom.depth; e2->ray.max_elem=e1->id; memcpy(e2->ray.max_pos,contact[i].geom.pos,sizeof(dReal)*3); } continue; } // raydium_ode_CollideCallback if(f) { int id1,id2; id1=id2=-1; if(e1) id1=e1->id; if(e2) id2=e2->id; if(!f(id1,id2,&contact[i])) continue; } if(e1) e1->_touched=1; // may use it as a counter ? if(e2) e2->_touched=1; // ... //printf("%s <-> %s\n",e1->name,e2->name); // let's flood :) c = dJointCreateContact (raydium_ode_world,raydium_ode_contactgroup,&contact[i]); dJointAttach (c,dGeomGetBody(contact[i].geom.g1),dGeomGetBody(contact[i].geom.g2)); } } } void raydium_ode_callback(void) { int i; void (*f)(void); f=raydium_ode_StepCallback; raydium_ode_network_read(); if(f) f(); /* for(i=0;irel_dir[0], r->rel_dir[1], r->rel_dir[2], dir); //printf("set : %f %f %f\n",dir[0],dir[1],dir[2]); pos=(dReal *)dBodyGetPosition(raydium_ode_element[i].body); dGeomRaySet(r->geom,pos[0],pos[1],pos[2],dir[0],dir[1],dir[2]); r->max_dist=0; r->min_dist=0; r->max_elem=r->min_elem=-1; } } for(i=0;i config_radius (and then delete explosion) if(raydium_ode_explosion[i].radius>raydium_ode_explosion[i].config_radius) raydium_ode_explosion_delete(i); else { // 2 - increment radius raydium_ode_explosion[i].radius+=raydium_ode_explosion[i].config_propag; // 3 - delete previous element if exists if(raydium_ode_explosion[i].element>=0) raydium_ode_element_delete(raydium_ode_explosion[i].element,0); // 4 - create new element // (not really a distant element, but we don't want progap' ...) raydium_ode_network_distant_create=1; raydium_ode_explosion[i].element= raydium_ode_object_sphere_add(raydium_ode_explosion[i].name, raydium_ode_object_find("GLOBAL"), 0, raydium_ode_explosion[i].radius, RAYDIUM_ODE_STATIC, 0, /* see below */ ""); raydium_ode_element[raydium_ode_explosion[i].element].user_tag=RAYDIUM_ODE_TAG_EXPLOSION; raydium_ode_element_material(raydium_ode_explosion[i].element,RAYDIUM_ODE_MATERIAL_SOFT2); raydium_ode_element_move(raydium_ode_explosion[i].element,raydium_ode_explosion[i].position); } } raydium_ode_element_delete_LOCK=1; //raydium_profile_start(); dSpaceCollide (raydium_ode_space,0,&raydium_ode_near_callback); for(i=0;i=0 && !raydium_ode_element[i]._avoidedcol ) raydium_ode_element[i]._movesfrom=-1; for(i=0;i=0 && raydium_ode_element[i].distant) raydium_ode_network_element_trajectory_correct(i); for(i=0;i=0) { int end; dBodyID body; dReal *pos; dQuaternion rot; body=dBodyCreate(raydium_ode_world); pos=raydium_ode_element_pos_get(i); raydium_ode_element_rotq_get(i,rot); dBodySetPosition(body,pos[0],pos[1],pos[2]); dBodySetQuaternion(body,rot); k=raydium_ode_element[i].mesh; // should prepare "ode" instance here, too ... if(raydium_object_anims[k]>0) end=raydium_object_start[k]+raydium_object_anim_len[k]; else end=raydium_object_end[k]; for(j=raydium_object_start[k];j