Agregados dos tipos de disparos y mejora visual en los checkpoints.
[nespa.git] / src / e3d_object.cpp
blobee50a4cb586f0d7af8fc9ab7a2e3b0727e1b0305
1 #ifdef WIN32
2 #define WIN32_LEAN_AND_MEAN
3 #include <windows.h>
4 #endif
5 #if defined(__APPLE__) && defined(__MACH__)
6 #include <OpenGL/gl.h> // Header File For The OpenGL32 Library
7 #include <OpenGL/glu.h> // Header File For The GLu32 Library
8 #else
9 #include <GL/gl.h> // Header File For The OpenGL32 Library
10 #include <GL/glu.h> // Header File For The GLu32 Library
11 #endif
12 #include "SDL/SDL.h"
13 #include "SDL/SDL_image.h"
14 #include "SDL/SDL_timer.h"
15 #include "SDL/SDL_mixer.h"
17 #include "e3d_engine.h"
20 e3D_Object::e3D_Object(e3D_Render *render)
22 Parent=NULL;
23 Render=render;
24 body=0;
25 geom=0;
27 ObjectClassname="Object";
28 // future classes should be named like:
29 // Object.Planet
30 // Object.Ship
31 // Object.Particle
32 // Object.Particle.Atmosphere
33 // A distinctive ObjectClassname is needed when trying to guess the pass number in the render.
34 init_physics();
38 e3D_Object::e3D_Object(e3D_Object *parent)
40 if (parent)
42 // cout << "Child added to parent" << endl;
43 e3D_Object(parent->Render);
44 Parent=parent;
45 Parent->children.insert(Parent->children.begin(),this);
46 Render=Parent->Render;
48 ObjectClassname="Object";
49 init_physics();
52 void e3D_Object::init_physics()
54 // printf("init_physics\n");
55 body = dBodyCreate(Render->world);
58 dMassSetSphere(&mass,1,1);
59 dBodySetMass(body,&mass);
60 dBodySetPosition(body,0,0,0);
61 scale_x=scale_y=scale_z=1;
62 AutoDeleteAfterDraw=0;
65 void e3D_Object::init_physics(double size,double density)
67 // printf("init_physics\n");
68 body = dBodyCreate(Render->world);
70 dMass mass;
71 dMassSetSphere(&mass,density,size);
72 dBodySetMass(body,&mass);
73 dBodySetPosition(body,0,0,0);
74 scale_x=scale_y=scale_z=size;
75 AutoDeleteAfterDraw=0;
78 void e3D_Object::Free()
80 if (Parent)
82 Parent->children.remove(this);
83 Parent=0;
85 if (body)
87 dBodyDestroy (body);
89 if (geom)
91 dGeomDestroy (geom);
95 e3D_Object::~e3D_Object()
97 Free();
101 void e3D_Object::LoadPosition() {glLoadMatrixd(position);}
102 void e3D_Object::MultPosition() {glMultMatrixd(position);}
103 void e3D_Object::SavePosition() {glGetDoublev(GL_MODELVIEW_MATRIX,position);}
105 void e3D_Object::LoadInverse() {glLoadMatrixd(inverse);}
106 void e3D_Object::MultInverse() {glMultMatrixd(inverse);}
107 void e3D_Object::SaveInverse() {glGetDoublev(GL_MODELVIEW_MATRIX,inverse);}
109 void e3D_Object::LoadInverseO() {glLoadMatrixd(inverse_orientation);}
110 void e3D_Object::MultInverseO() {glMultMatrixd(inverse_orientation);}
111 void e3D_Object::SaveInverseO() {glGetDoublev(GL_MODELVIEW_MATRIX,inverse_orientation);}
113 void e3D_Object::ResetAtBody(dBodyID dest,double x, double y, double z, double vel_mult)
115 dVector3 p;
116 dBodyGetRelPointPos(dest,x,y,z,p);
117 const dReal *r = dBodyGetRotation(dest);
118 const dReal *AngularVel, *LinearVel;
119 AngularVel=dBodyGetAngularVel(dest);
120 LinearVel=dBodyGetLinearVel(dest);
122 dBodySetLinearVel(body,LinearVel[0]*vel_mult,LinearVel[1]*vel_mult,LinearVel[2]*vel_mult);
123 dBodySetPosition(body,p[0],p[1],p[2]);
124 dBodySetRotation(body,r);
127 void e3D_Object::LoadRealPosition()
130 const dReal *p = dBodyGetPosition(body);
131 const dReal *r = dBodyGetRotation(body);
133 double m[16];
135 m[ 0] = r[ 0];m[ 1] = r[ 4];m[ 2] = r[ 8];m[ 3] = 0;
136 m[ 4] = r[ 1];m[ 5] = r[ 5];m[ 6] = r[ 9];m[ 7] = 0;
137 m[ 8] = r[ 2];m[ 9] = r[ 6];m[10] = r[10];m[11] = 0;
138 m[12] = p[ 0];m[13] = p[ 1];m[14] = p[ 2];m[15] = 1;
139 glMultMatrixd(m);
140 glScaled(scale_x,scale_y,scale_z);
141 /* e3D_Object *Obj=this;
143 int n=0, i;
146 n++;
147 } while((Obj=Obj->Parent)!=NULL);
148 for (;n>0;n--)
150 Obj=this;
152 for (i=1;i<n;i++) Obj=Obj->Parent;
153 Obj->MultPosition();
158 void e3D_Object::GetXYZ(double *x, double *y,double *z)
160 const dReal *p = dBodyGetPosition(body);
161 *x=p[0];
162 *y=p[1];
163 *z=p[2];
165 return;
167 matriz M;
169 glPushMatrix();
170 LoadRealPosition();
171 glGetDoublev(GL_MODELVIEW_MATRIX,M);
172 matrix2point(M, x, y,z);
173 glPopMatrix();*/
176 void e3D_Object::GetCamera(double dx,double dy, double dz)
178 matriz M;
179 double eyeX,eyeY,eyeZ;
180 double centerX,centerY,centerZ;
181 double upX,upY,upZ;
183 glPushMatrix();
184 LoadRealPosition();
185 glTranslated(dx,dy,dz);
186 glGetDoublev(GL_MODELVIEW_MATRIX,M);
187 matrix2point(M, &eyeX, &eyeY, &eyeZ);
188 matrix2point(M, &centerX, &centerY, &centerZ,0,0,-10);
189 matrix2point(M, &upX, &upY, &upZ,0,10,0);
190 upX-=eyeX;
191 upY-=eyeY;
192 upZ-=eyeZ;
193 double camlag=10;
195 camera_eyeX=(camera_eyeX*camlag+eyeX)/(camlag+1);
196 camera_eyeY=(camera_eyeY*camlag+eyeY)/(camlag+1);
197 camera_eyeZ=(camera_eyeZ*camlag+eyeZ)/(camlag+1);
199 camera_centerX=(camera_centerX*camlag+centerX)/(camlag+1);
200 camera_centerY=(camera_centerY*camlag+centerY)/(camlag+1);
201 camera_centerZ=(camera_centerZ*camlag+centerZ)/(camlag+1);
203 camera_upX=(camera_upX*camlag+upX)/(camlag+1);
204 camera_upY=(camera_upY*camlag+upY)/(camlag+1);
205 camera_upZ=(camera_upZ*camlag+upZ)/(camlag+1);
208 glPopMatrix();
209 gluLookAt(eyeX,eyeY,eyeZ,
210 centerX, centerY, centerZ,
211 upX, upY, upZ);
213 /* gluLookAt(camera_eyeX,camera_eyeY,camera_eyeZ,
214 camera_centerX, camera_centerY, camera_centerZ,
215 camera_upX, camera_upY, camera_upZ);
219 void e3D_Object::Translate(double x, double y, double z)
221 double x1,y1,z1;
222 GetXYZ(&x1,&y1,&z1);
223 dBodySetPosition(body,x+x1,y+y1,z+z1);
225 glPushMatrix();
226 LoadPosition();
227 glTranslated(x,y,z);
228 SavePosition();
230 // if (Camera_follows_Translation)
231 // {
232 glLoadIdentity();
233 glTranslated(-x,-y,-z);
234 MultInverse();
235 SaveInverse();
236 // }
237 glPopMatrix();
241 void e3D_Object::Rotate(double angle,double x, double y, double z)
244 glPushMatrix();
245 LoadPosition();
246 glRotated(angle,x,y,z);
247 SavePosition();
249 // if (Camera_follows_Orientation)
250 // {
251 glLoadIdentity();
252 glRotated(-angle,x,y,z);
253 MultInverse();
254 SaveInverse();
255 // }
256 glLoadIdentity();
257 MultInverseO();
258 glRotated(angle,x,y,z);
259 SaveInverseO();
261 glPopMatrix();
265 void e3D_Object::Scale(double x, double y, double z)
267 scale_x*=x;
268 scale_y*=y;
269 scale_z*=z;
272 void e3D_Object::BeginDraw()
274 // Code to execute when at the beginning of a block of objects
275 // Recommended: using glPus/PopAttrib prevents
276 // future problems when mixing render types
277 glPushAttrib(GL_ALPHA_TEST | GL_POLYGON_SMOOTH | GL_TEXTURE_2D | GL_BLEND);
278 /*glDisable(GL_ALPHA_TEST);
279 glDisable(GL_BLEND);
280 glEnable(GL_COLOR_MATERIAL);
282 glDisable(GL_LIGHTING);*/
286 void e3D_Object::EndDraw()
288 // Code to execute when at the beginning of a block of objects
289 glPopAttrib();
292 void e3D_Object::Draw(int pass) // Example implementation for draw
295 glColor4f(1.0f,1.0f,1.0f,1.0f);
296 glBegin(GL_QUADS);
297 glNormal3f( 0.0f, 0.0f, -1.0f);
298 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f);
299 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
300 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
301 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f);
302 glEnd();
306 e3D_Object *e3D_Object::DrawBE(bool AutoBeginEnd, e3D_Object *o_begin)
309 // As a parameter, an e3D_Object indicates from what object started
310 // drawing the loop. For Begin/End control purposes only.
311 if (AutoBeginEnd)
313 if (o_begin)
315 if (o_begin->ObjectClassname!=ObjectClassname)
317 o_begin->EndDraw();
318 o_begin=NULL;
321 if (!o_begin)
323 o_begin=this;
324 o_begin->BeginDraw();
327 Draw();
329 return o_begin;
332 e3D_Object *e3D_Object::LocateAndDraw(bool AutoBeginEnd, e3D_Object *o_begin)
334 glPushMatrix();
335 LoadRealPosition();
336 o_begin=DrawBE(AutoBeginEnd,o_begin);
337 glPopMatrix();
339 return o_begin;
342 void e3D_Object::ApplyGravityFrom(e3D_Object *from)
344 double Amass=mass.mass,Bmass=from->mass.mass;
345 double Ax,Ay,Az;
346 double Bx,By,Bz;
347 GetXYZ(&Ax,&Ay,&Az);
348 from->GetXYZ(&Bx,&By,&Bz);
350 double ABx=Bx-Ax,ABy=By-Ay,ABz=Bz-Az;
351 double Rxy=sqrt(ABx*ABx+ABy*ABy);
352 double R2=Rxy*Rxy+ABz*ABz;
353 double R=sqrt(R2);
355 const double G=.0000001; // Universal Gravitation constant
356 double N=G*Amass*Bmass/R2; // Gravity force
357 //printf(" - %s - f: %.4f a:%.4f b:%.1f r:%.1f \n", ObjectClassname.c_str(),N,Amass,Bmass,R);
358 dBodyAddForceAtRelPos(body,ABx/R*N,ABy/R*N,ABz/R*N,0,0,-0.001);
362 void e3D_Object::ApplyGravityForces(e3D_Object *o_begin)
364 // Locates and draws all childrens.
365 //e3D_Object *obj=o_begin;
367 e3D_Object *c;
369 std::list<e3D_Object *>::iterator list_iter;
370 for (list_iter = o_begin->children.begin(); list_iter != o_begin->children.end(); list_iter++)
372 c=*list_iter;
373 ApplyGravityFrom(c);
377 e3D_Object *e3D_Object::DrawChildren(
378 bool AutoBeginEnd,
379 bool draw_this,
380 bool Recursive,
381 e3D_Object *o_begin)
383 // Locates and draws all childrens.
384 e3D_Object *obj=o_begin;
385 glPushMatrix();
386 LoadRealPosition();
387 if (draw_this)
389 obj=DrawBE(obj);
392 e3D_Object *c;
394 std::list<e3D_Object *>::iterator list_iter;
396 for (list_iter = children.begin(); list_iter != children.end(); list_iter++)
398 c=*list_iter;
399 // c->Draw();
400 // obj=c->LocateAndDraw(obj);
401 if (Recursive) obj=c->DrawChildren(AutoBeginEnd,true,true,obj);
402 else obj=c->LocateAndDraw(obj);
407 if (!o_begin && obj && AutoBeginEnd)
409 obj->EndDraw();
410 obj=NULL;
413 glPopMatrix();
415 return obj;
419 e3D_Ship::e3D_Ship(e3D_Object *parent, const char *fileobj, float size) : e3D_Object(parent)
421 //e3D_Ship(parent);
422 Ship.LoadObj(fileobj,size);
423 _shield_size=shield_size=6;
424 _bright_size=bright_size=0.1;
425 if (__E3D_ENGINE_DEBUG) cout << "Create ship:" << fileobj << endl;
426 init_physics();
427 quad=gluNewQuadric();
428 gluQuadricOrientation(quad, GLU_OUTSIDE);
429 Shield=new e3D_Sprite(this,"images/escudos.png");
430 Shield->Scale(shield_size,shield_size,shield_size);
432 Bright=new e3D_Sprite(this,"images/particles/brightstar-256-128.png");
433 Bright->Translate(0,0,100);
434 Bright->Scale(bright_size,bright_size,bright_size);
436 Bright2=new e3D_Sprite(Bright,"images/particles/hiddenplanet-256-128.png");
437 Bright2->Translate(0,0,-4);
438 Bright2->Scale(2,2,2);
440 geom=dCreateSphere(Render->space,6);
441 dMassSetSphere(&mass,10,6);
442 dGeomSetBody(geom,body);
443 // Camera_follows_Orientation=false;
444 rfriction=0.1;
445 dfriction=0.1;
446 dx=dy=dz=0;
447 rx=ry=rz=0;
448 hull=10;
449 energy=0;
450 maxenergy=10000;
451 set_inc_energy=50;
452 set_engine_energy=10;
453 set_rotor_energy=10;
454 used_fuel=0;
455 ObjectClassname="Ship";
458 void e3D_Ship::Draw(int pass) // Example implementation for draw
460 const dReal *AngularVel, *LinearVel;
462 AngularVel=dBodyGetAngularVel(body);
463 LinearVel=dBodyGetLinearVel(body);
465 double AngularVel_x=AngularVel[0],AngularVel_y=AngularVel[1],AngularVel_z=AngularVel[2];
466 double LinearVel_x=LinearVel[0],LinearVel_y=LinearVel[1],LinearVel_z=LinearVel[2];
469 lv=sqrt(LinearVel_x*LinearVel_x+LinearVel_y*LinearVel_y);
470 lv=sqrt(lv*lv+LinearVel_z*LinearVel_z);
472 if (rand()%5==0 && Render->Camera==this)
475 e3D_Shoot *shoot=new e3D_Shoot(
476 Render->OG_Particles,"images/particles/supernova-256-16.png",
477 0.2+log(lv+1),1);
478 shoot->Translate(
479 camera_eyeX+(rand()%200-100)/2.0,
480 camera_eyeY+(rand()%200-100)/2.0,
481 camera_eyeZ+(rand()%200-100)/2.0
483 shoot->Translate(
484 LinearVel_x*2,
485 LinearVel_y*2,
486 LinearVel_z*2
488 dMassSetSphere(&(shoot->mass),1,4);
489 shoot->life=7;
490 shoot->speed=0;
491 shoot->geom=0;
494 // Fricción simulada / irreal:
495 const double avd=.500;
496 dBodyAddTorque(body,-AngularVel_x*avd,-AngularVel_y*avd,-AngularVel_z*avd);
497 const double lvd=.500;
498 dBodyAddForce(body,-LinearVel_x*lvd,-LinearVel_y*lvd,-LinearVel_z*lvd);
499 double lv2=sqrt(LinearVel_x*lvd*LinearVel_x*lvd+LinearVel_y*lvd*LinearVel_y*lvd);
500 lv2=sqrt(lv2*lv2+LinearVel_z*lvd*LinearVel_z*lvd);
502 // ******************** FISICA
503 dBodyAddRelForce(body,-dx*(lvd+1),-dy*(lvd+1),-dz*(lvd+1)-lv2);
504 dBodyAddRelTorque(body,-rx*(avd+1),-ry*(avd+1),-rz*(avd+1));
505 float rxy=sqrt(rx*rx+ry*ry);
506 float rxyz=sqrt(rz*rz+rxy*rxy);
507 used_fuel+=rxyz/10.0;
509 float dxy=sqrt(dx*dx+dy*dy);
510 float dxyz=sqrt(dz*dz+dxy*dxy);
511 used_fuel+=dxyz/10.0;
513 //if (!pass || pass==PASS_SOLIDOBJECTS)
514 energy+=2+_shield_size/(energy/set_inc_energy+1);
515 /*energy-=fabs(dz)*set_engine_energy*dfriction;
516 energy-=fabs(dx)*set_engine_energy*dfriction;
517 energy-=fabs(dy)*set_engine_energy*dfriction;
519 energy-=fabs(rz)*set_rotor_energy*rfriction;
520 energy-=fabs(rx)*set_rotor_energy*rfriction;
521 energy-=fabs(ry)*set_rotor_energy*rfriction;
524 /*if (energy<=0)
526 if (bright_size<1)
528 dx/=2.0;
529 dy/=2.0;
530 dz/=2.0;
532 rx/=2.0;
533 ry/=2.0;
534 rz/=2.0;
536 energy=0;
538 if (energy>maxenergy) energy=maxenergy;
542 glDisable(GL_COLOR_MATERIAL);
543 glEnable(GL_LIGHTING);
544 Ship.Draw();
545 double _vel;
546 _vel=sqrt(LinearVel_x*LinearVel_x+LinearVel_y*LinearVel_y);
547 _vel=sqrt(_vel*_vel+LinearVel_z*LinearVel_z);
549 bright_size=_vel;
550 bright_size*=bright_size;
551 bright_size-=1500;
552 if (bright_size<0.01) bright_size=0.01;
553 if (bright_size>100) bright_size=100;*/
554 /*Translate(-dx,-dy,-dz);
555 Rotate(-rx,1,0,0);
556 Rotate(-ry,0,1,0);
557 Rotate(-rz,0,0,1);*/
559 if (hull<=0)
561 dfriction=10;
562 rfriction=0.1;
563 hull=0;
564 Scale(0.992,0.992,0.992);
565 Shield->Scale(1.05,1.05,1.05);
566 Bright->Scale(0.95,0.95,0.95);
567 Bright2->Scale(1.01,1.01,1.01);
568 shield_size=10;
569 bright_size=100;
572 dx/=1+dfriction;
573 dy/=1+dfriction;
574 dz/=1+dfriction;
576 rx/=1+rfriction+bright_size/100.0;
577 ry/=1+rfriction+bright_size/100.0;
578 rz/=1+rfriction+bright_size/100.0;
580 ApplyGravityForces(Render->OG_Planets);
581 // ***************************
582 if (_bright_size<0.1) shield_size+=hull/(shield_size)/1000.0;
583 if (_bright_size<0.1 && shield_size>50) shield_size/=1+(shield_size-15)/5000.0;
584 if (shield_size>hull*2) shield_size/=1.001;
585 if (shield_size<hull/5.0) shield_size=hull/5.0;
586 if (shield_size!=_shield_size)
588 double rx=shield_size/_shield_size;
589 rx-=1;
590 rx/=10;
591 rx+=1;
593 Shield->Scale(rx,rx,rx);
594 _shield_size*=rx;
596 if (bright_size!=_bright_size)
598 double rx=bright_size/_bright_size;
599 Bright2->angle+=rx*rx-0.95;
600 rx-=1;
601 rx/=60;
602 rx+=1;
603 Bright->angle-=rx*rx-0.98;
604 if (_bright_size>1)
606 if (rx<1) shield_size-=1-rx; else shield_size/=rx+.001;
608 Bright->Scale(rx,rx,rx);
609 _bright_size*=rx;
616 void e3D_Ship::Shoot(int type)
618 e3D_Shoot *shoot;
619 switch(type)
621 case 1:
622 shoot=new e3D_Shoot(Render->OG_Particles,"images/particles/shoot1.png",1,15);
623 shoot->ResetAtBody(this->body,0,0,-2-8-5);
624 shoot->speed=20000;
625 shoot->G=0.4;
626 shoot->B=0.7;
627 shoot->geom=dCreateSphere(Render->space,5);
628 dGeomSetBody(shoot->geom,shoot->body);
629 dMassSetSphere(&(shoot->mass),100,40);
630 break;
631 default:
632 case 0:
633 shoot=new e3D_Shoot(Render->OG_Particles,"images/particles/shoot1.png",1,.1);
634 shoot->ResetAtBody(this->body,0,0,-1-5-1);
635 shoot->speed=300;
636 shoot->geom=dCreateSphere(Render->space,0.5);
637 dGeomSetBody(shoot->geom,shoot->body);
638 dMassSetSphere(&(shoot->mass),1,4);
639 break;