#include "MarbleSphere.h" MarbleSphere::MarbleSphere(void) {} MarbleSphere::~MarbleSphere(void) {} void MarbleSphere::CreateSphere(Point3f c,double r,int n) { int i,j; double theta1,theta2,theta3; Point3f e,p; if (r < 0) r = -r; if (n < 0) n = -n; if (n < 4 || r <= 0) { glBegin(GL_POINTS); glVertex3f(c.x(),c.y(),c.z()); glEnd(); return; } for (j=0;j<n/2;j++) { theta1 = j * (2*M_PI)/ n -(M_PI/2); theta2 = (j + 1) * (2*M_PI)/ n -(M_PI/2); glBegin(GL_QUAD_STRIP); for (i=0;i<=n;i++) { theta3 = i * 2*M_PI / n; e[XX] = cos(theta2) * cos(theta3); e[YY] = sin(theta2); e[ZZ]= cos(theta2) * sin(theta3); p[XX] = c.x() + r * e.x(); p[YY] = c.y() + r * e.y(); p[ZZ] = c.z() + r * e.z(); glNormal3f(e.x(),e.y(),e.z()); glTexCoord2f(i/(double)n,2*(j+1)/(double)n); glVertex3f(p.x(),p.y(),p.z()); e[XX] = cos(theta1) * cos(theta3); e[YY] = sin(theta1); e[ZZ] = cos(theta1) * sin(theta3); p[XX] = c.x() + r * e.x(); p[YY] = c.y() + r * e.y(); p[ZZ] = c.z() + r * e.z(); glNormal3f(e.x(),e.y(),e.z()); glTexCoord2f(i/(double)n,2*j/(double)n); glVertex3f(p.x(),p.y(),p.z()); } glEnd(); } } void MarbleSphere::Rotate(float dt) { Point3f asse_verticale; asse_verticale.Zero(); asse_verticale[1] = 1.0; angolo_rotazione = ((normavel*dt/(attrito))/lung_arco_per_grado); vettore_rotazione = vet_pos_ris ^ asse_verticale ; } void MarbleSphere::setTexture(char *str) { ilInit(); iluInit(); ilutRenderer(ILUT_OPENGL); ti=ilutGLLoadImage(str); ilutGLBuildMipmaps(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE ); } void MarbleSphere::Update(MadMap *mp,float delta_t) { if (palla_viva) { //=================================aggiungo comp mouse===================================== vet_velocita=vet_velocita+vet_compon_controllo; //========================================================================================= //=======la risultante delle varie velocita non vince l'attrito e mi fermo================= if(vet_velocita.Norm()<=vet_compon_vel_attrito.Norm()) { vet_velocita.Zero();return; } //========================================================================================= //======================================= ricavo il triangolo ============================= mp->getTriangle(vet_posizione[0],vet_posizione[2],&triangolo); //ricavo il triangolo...(3 vertici) //========================================================================================= //=============ricavo la tile su cui si trova la palla per le caratteristiche fisiche ===== int x=0; int z=0; x = floor(vet_posizione.x()); z = floor(vet_posizione.z()); //========================================================================================= //==============ricavo l'attrito e la gravita della tile su cui si trova la palla========== vet_compon_vel_gravita.Zero(); if ((x<0)||(z<0)||(z>=MAXMAP)||(x>=MAXMAP)) { vet_compon_vel_gravita[1]=-160; attrito=7; } else { vet_compon_vel_gravita[1]=(float)mp->Map[x][z].grav; //qui interrogo la mappa con ceil e floor del vet pos per leggere le info di attrito e gravita delle tile attrito=(float)mp->Map[x][z].attr;} //=========================================================================================== //=================ricavo la reazione al piano============================================= float normaG; float normaR; normaG = vet_compon_vel_gravita.Norm(); //norma di G normaR = (normaG * cos(triangolo.pendenza())); triangolo.normale=triangolo.normale*normaR; //adesso triangolo.normale e' la reazione calcolata normaR = triangolo.normale.Norm(); //norma reazione vera //========================================================================================= //==================================aggiungo comp gravita ================================= vet_velocita=vet_velocita+vet_compon_vel_gravita; //G e' sempre presente //========================================================================================= //adesso cerco di capire se la palla tocca o meno la mappa per aggiungere la reazione e l'attrito oppure no //==============================se tocco la mappa ================================================================== if (( tocca_mappa_inclinata ) || ( tocca_mappa_piana )) // tocco la mappa aggiungo attr e reaz { //aggiungo reazione vet_velocita=vet_velocita+triangolo.normale; //calcolo attrito vet_compon_vel_attrito=-(vet_velocita/(vet_velocita.Norm()/attrito)); //aggiungo attrito vet_velocita= vet_velocita + vet_compon_vel_attrito ; //==============================controllo morte===================== if (vet_velocita[1] < -VELOCITA_DI_MORTE ) palla_viva=false; muro_di_morte=4; //=================================================================== //===========================rimbalsi verticali====================== vet_velocita[1]= -vet_velocita[1]/1.5; if (triangolo.pendenza()!= 0) vet_velocita[1]= -vet_velocita[1]/1.5;//per evitare i salti nei piani inclinati if( vet_velocita[1]<0) //per evitare le vibrazioni { if ( vet_velocita[1] > -800.0) vet_velocita[1]=0; } if ( vet_velocita[1]>0) { if ( vet_velocita[1] < 800.0) vet_velocita[1]=0; } } //========================================================================================== //================================calcolo il vet pos risultante========= normavel=vet_velocita.Norm(); normapos=normavel*delta_t; vet_pos_ris=vet_velocita*delta_t/200.0; normavettpos=vet_pos_ris.Norm(); if ((normavettpos >=0.5)&& (( tocca_mappa_inclinata ) || ( tocca_mappa_piana )) ) //il vettore pos massimo in norma e' 1.0 { vet_pos_ris=vet_pos_ris*(0.5/normavettpos); normavettpos=vet_pos_ris.Norm(); } normavettpos=vet_pos_ris.Norm(); //====================================================================== //====================rotazione pallina================================ if (vet_compon_controllo.Norm()>0) Rotate(-delta_t); //rotazione attiva else Rotate(delta_t); //===================================================================== //=========================nuovo vet posizione aggiornato============== old_vet_pos=vet_posizione; //per il collision verticale vet_posizione=vet_posizione+vet_pos_ris; //======================================================================= //==================================collision detection verticale====================== mp->getTriangle(vet_posizione[0],vet_posizione[2],&triangolo); //ricavo il triangolo...(3 vertici) float alpha =triangolo.pendenza(); //pendenza del piano float dislivello ; float a; float b; float c; float d; float altezza_punto_centrale; float altezza_punto_controllo; float altezza_punto_controllo_obl_1;//punto obliquo di sinistra float altezza_punto_controllo_obl_2;//punto obliquo di destra Point3f controllo[4]; for (int i=0;i<4;i++) controllo[i].Zero(); controllo[0][0]=vet_posizione[0]; controllo[0][1]=vet_posizione[1]; controllo[0][2]=vet_posizione[2]-0.5; // nord controllo[1][0]=vet_posizione[0]+0.5; controllo[1][1]=vet_posizione[1]; controllo[1][2]=vet_posizione[2]; // est controllo[2][0]=vet_posizione[0]; controllo[2][1]=vet_posizione[1]; controllo[2][2]=vet_posizione[2]+0.5; // sud controllo[3][0]=vet_posizione[0]-0.5; controllo[3][1]=vet_posizione[1]; controllo[3][2]=vet_posizione[2]; // ovest //fin qui ho settato le posizioni dei punti di controllo //=========================================== Point3f controllo_or[4]; for (int i=0;i<4;i++) controllo_or[i].Zero(); controllo_or[0][0]=vet_posizione[0]-0.3535; controllo_or[0][1]=vet_posizione[1]; controllo_or[0][2]=vet_posizione[2]-0.3535; //nord ovest controllo_or[1][0]=vet_posizione[0]+0.3535; controllo_or[1][1]=vet_posizione[1]; controllo_or[1][2]=vet_posizione[2]-0.3535; //nord est controllo_or[2][0]=vet_posizione[0]+0.3535; controllo_or[2][1]=vet_posizione[1]; controllo_or[2][2]=vet_posizione[2]+0.3535; //sud est controllo_or[3][0]=vet_posizione[0]-0.3535; controllo_or[3][1]=vet_posizione[1]; controllo_or[3][2]=vet_posizione[2]+0.3535; //sud ovest //fin qui ho settato le posizioni dei punti di controllo //=========================================== altezza_punto_centrale =( mp->getY( vet_posizione.x() , vet_posizione.z() ));//!!!! for (int i=0;i<4;i++) { float differ =(mp->getY(controllo[i][0],controllo[i][2]) -((old_vet_pos[1])-0.5 )); switch (i) { case 0: altezza_punto_controllo=( mp->getY(controllo[(i)][0],controllo[(i)][2])); //nord //============================== altezza_punto_controllo_obl_1=( mp->getY(controllo_or[(i)][0],controllo_or[(i)][2])); //nord ovest altezza_punto_controllo_obl_2=( mp->getY(controllo_or[(i+1)][0],controllo_or[(i+1)][2])); //nord est //============================== if (vet_pos_ris.z()<=0) { x = floor(controllo[i][0]); z = floor(controllo[i][2]); a= mp->Map[x][z].SW; b=mp->Map[x][z].SE; c=mp->Map[x][z+1].NW; d=mp->Map[x][z+1].NE; dislivello= altezza_punto_controllo -altezza_punto_centrale;//mi serve nel collision quando la palla sta rimbalzando if((( ( ((a-c)>0.25)||((b-d)>0.25))&&( dislivello>0 ) && (altezza_punto_controllo>(vet_posizione.y()-0.5))) && alpha==0) ||(alpha!=0 && differ>0.6)) //obliquio approssimato a 0.6 ,implica che non sale su pendenze con derivata >0.6 { vet_posizione[1]= old_vet_pos[1]; vet_posizione[2]= ceil(vet_posizione[2])-0.5; vet_velocita[2]= -vet_velocita[2]/1.2; //rimbalso parzialmente anelastico if ((vet_velocita[2] < -VELOCITA_DI_MORTE )|| (vet_velocita[2] > VELOCITA_DI_MORTE )) palla_viva=false; muro_di_morte = 0; } if (((altezza_punto_controllo_obl_1>(vet_posizione.y())) && //nord ovest (controllo[i][1]-0.25 ) >= ( mp->getY(controllo[i][0],controllo[i][2])) && (controllo[3][1]-0.25) >= ( mp->getY(controllo[3][0],controllo[3][2])) &&alpha==0 ) || ((altezza_punto_controllo_obl_1>(vet_posizione.y())) && (controllo[i][1]) >= ( mp->getY(controllo[i][0],controllo[i][2])) && //controllo il punto obliquo (controllo[3][1]) >= ( mp->getY(controllo[3][0],controllo[3][2])) &&alpha!=0 ) ) //ho preso lo spigolo { vet_posizione[1]= old_vet_pos[1]; vet_posizione[2]= ceil(vet_posizione[2])-0.65; vet_velocita[2]=-vet_velocita[2]/1.2; if ((vet_velocita[2] < -VELOCITA_DI_MORTE )|| (vet_velocita[2] > VELOCITA_DI_MORTE )) palla_viva=false; muro_di_morte = 0; } if(((altezza_punto_controllo_obl_2>(vet_posizione.y()))&& //nord est (controllo[i][1]-0.25) >= ( mp->getY(controllo[i][0],controllo[i][2])) && (controllo[1][1]-0.25) >= ( mp->getY(controllo[1][0],controllo[1][2])) &&alpha==0 ) || ((altezza_punto_controllo_obl_2>(vet_posizione.y()))&& //controllo il punto obliquo (controllo[i][1]) >= ( mp->getY(controllo[i][0],controllo[i][2])) && (controllo[1][1]) >= ( mp->getY(controllo[1][0],controllo[1][2])) &&alpha !=0 )) { vet_posizione[1]= old_vet_pos[1]; vet_posizione[2]= ceil(vet_posizione[2])-0.65; vet_velocita[2]=-vet_velocita[2]/1.2; if ((vet_velocita[2] < -VELOCITA_DI_MORTE )|| (vet_velocita[2] > VELOCITA_DI_MORTE )) palla_viva=false; muro_di_morte = 0; } } break; case 1: altezza_punto_controllo=( mp->getY(controllo[(i)][0],controllo[(i)][2])); //est //============================== altezza_punto_controllo_obl_1=( mp->getY(controllo_or[(i)][0],controllo_or[(i)][2])); //nord est altezza_punto_controllo_obl_2=( mp->getY(controllo_or[(i+1)][0],controllo_or[(i+1)][2])); //sud est //===================================== if (vet_pos_ris.x()>=0) { x = floor(controllo[i][0]); z = floor(controllo[i][2]); a= mp->Map[x][z].NW; b=mp->Map[x][z].SW; c=mp->Map[x-1][z].NE; d=mp->Map[x-1][z].SE; dislivello= altezza_punto_controllo -altezza_punto_centrale;//mi serve nel collision quando la palla sta rimbalzando if((( ( ((a-c)>0.25)||((b-d)>0.25))&&( dislivello>0 ) && (altezza_punto_controllo>(vet_posizione.y()-0.5))) && alpha==0) ||(alpha!=0 && differ>0.6)) { vet_posizione[1]= old_vet_pos[1]; vet_posizione[0]= floor(vet_posizione[0])+0.5; vet_velocita[0]= -vet_velocita[0]/1.2; //rimbalso parzialmente anelastico if ((vet_velocita[0] < -VELOCITA_DI_MORTE ) || (vet_velocita[0] > VELOCITA_DI_MORTE ))palla_viva=false; muro_di_morte = 1; } if (((altezza_punto_controllo_obl_1>(vet_posizione.y()))&& //nord est (controllo[i][1]-0.25) >= ( mp->getY(controllo[i][0],controllo[i][2])) && (controllo[0][1]-0.25 )>= ( mp->getY(controllo[0][0],controllo[0][2])) && alpha==0 ) || ((altezza_punto_controllo_obl_1>(vet_posizione.y()) )&& (controllo[i][1]) >= ( mp->getY(controllo[i][0],controllo[i][2])) && (controllo[0][1]) >= ( mp->getY(controllo[0][0],controllo[0][2])) && alpha!=0 )) { vet_posizione[1]= old_vet_pos[1]; vet_posizione[0]= ceil(vet_posizione[0])-0.3535; vet_velocita[0]= -vet_velocita[0]/1.2; if ((vet_velocita[0] < -VELOCITA_DI_MORTE ) || (vet_velocita[0] > VELOCITA_DI_MORTE ))palla_viva=false; muro_di_morte = 1; } if (((altezza_punto_controllo_obl_2>(vet_posizione.y()))&& //sud est ( controllo[i][1]-0.25) >= ( mp->getY(controllo[i][0],controllo[i][2])) && ( controllo[2][1]-0.25) >= ( mp->getY(controllo[2][0],controllo[2][2]))&& alpha==0 ) || ((altezza_punto_controllo_obl_2>(vet_posizione.y()))&& ( controllo[i][1]) >= ( mp->getY(controllo[i][0],controllo[i][2])) && ( controllo[2][1]) >= ( mp->getY(controllo[2][0],controllo[2][2]))&& alpha!=0 )) { vet_posizione[1]= old_vet_pos[1]; vet_posizione[0]= ceil(vet_posizione[0])-0.3535; vet_velocita[0]= -vet_velocita[0]/1.2; if ((vet_velocita[0] < -VELOCITA_DI_MORTE ) || (vet_velocita[0] > VELOCITA_DI_MORTE ))palla_viva=false; muro_di_morte = 1; } } break; case 2: altezza_punto_controllo=( mp->getY(controllo[(i)][0],controllo[(i)][2])); //sud //============================== altezza_punto_controllo_obl_1=( mp->getY(controllo_or[(i)][0],controllo_or[(i)][2])); //sud est altezza_punto_controllo_obl_2=( mp->getY(controllo_or[(3)][0],controllo_or[(3)][2])); //sud ovest //===================================== if (vet_pos_ris.z()>=0) { x = floor(controllo[i][0]); z = floor(controllo[i][2]); a= mp->Map[x][z].NE; b=mp->Map[x][z].NW; c=mp->Map[x][z-1].SE; d=mp->Map[x][z-1].SW; dislivello= altezza_punto_controllo -altezza_punto_centrale;//mi serve nel collision quando la palla sta rimbalzando if((( ( ((a-c)>0.25)||((b-d)>0.25))&&( dislivello>0 ) && (altezza_punto_controllo>(vet_posizione.y()-0.5))) && alpha==0) ||(alpha!=0 && differ>0.6)) { vet_posizione[1]= old_vet_pos[1]; vet_posizione[2]= floor(vet_posizione[2])+0.5; vet_velocita[2]= -vet_velocita[2]/1.2; //rimbalso parzialmente anelastico if ((vet_velocita[2] < -VELOCITA_DI_MORTE )||(vet_velocita[2] > VELOCITA_DI_MORTE )) palla_viva=false; muro_di_morte = 2; } if (((altezza_punto_controllo_obl_1>(vet_posizione.y()))&& //sud est ( controllo[i][1]-0.25) >= ( mp->getY(controllo[(i)][0],controllo[(i)][2])) && ( controllo[1][1]-0.25) >= ( mp->getY(controllo[(1)][0],controllo[(1)][2])) && alpha==0 ) || ((altezza_punto_controllo_obl_1>(vet_posizione.y()))&& ( controllo[i][1]) >= ( mp->getY(controllo[(i)][0],controllo[(i)][2])) && ( controllo[1][1]) >= ( mp->getY(controllo[(1)][0],controllo[(1)][2])) && alpha !=0 )) { vet_posizione[1]= old_vet_pos[1]; vet_posizione[2]= ceil(vet_posizione[2])-0.3535; vet_velocita[2]=-vet_velocita[2]/1.2; if ((vet_velocita[2] < -VELOCITA_DI_MORTE )||(vet_velocita[2] > VELOCITA_DI_MORTE )) palla_viva=false; muro_di_morte = 2; } if (((altezza_punto_controllo_obl_2>(vet_posizione.y()))&& //sud ovest ( controllo[i][1]-0.25) >= ( mp->getY(controllo[i][0],controllo[i][2])) && ( controllo[3][1]-0.25) >= ( mp->getY(controllo[3][0],controllo[3][2])) && alpha==0 ) || ((altezza_punto_controllo_obl_2>(vet_posizione.y()))&& ( controllo[i][1]) >= ( mp->getY(controllo[i][0],controllo[i][2])) && ( controllo[3][1]) >= ( mp->getY(controllo[3][0],controllo[3][2])) && alpha!=0 ) ) { vet_posizione[1]= old_vet_pos[1]; vet_posizione[2]= ceil(vet_posizione[2])-0.3535; vet_velocita[2]=-vet_velocita[2]/1.2; if ((vet_velocita[2] < -VELOCITA_DI_MORTE )||(vet_velocita[2] > VELOCITA_DI_MORTE )) palla_viva=false; muro_di_morte = 2; } } break; case 3: altezza_punto_controllo=( mp->getY(controllo[(i)][0],controllo[(i)][2])); //ovest //============================== altezza_punto_controllo_obl_1=( mp->getY(controllo_or[(i)][0],controllo_or[(i)][2])); //sud ovest altezza_punto_controllo_obl_2=( mp->getY(controllo_or[(0)][0],controllo_or[(0)][2])); //nord ovest //===================================== if (vet_pos_ris.x()<=0) { x = floor(controllo[i][0]); z = floor(controllo[i][2]); a= mp->Map[x][z].NE; b=mp->Map[x][z].SE; c=mp->Map[x+1][z].NW; d=mp->Map[x+1][z].SW; dislivello= altezza_punto_controllo -altezza_punto_centrale;//mi serve nel collision quando la palla sta rimbalzando if((( ( ((a-c)>0.25)||((b-d)>0.25))&&( dislivello>0 ) && (altezza_punto_controllo>(vet_posizione.y()-0.5))) && alpha==0) ||(alpha!=0 && differ>0.6)) { vet_posizione[1]= old_vet_pos[1]; vet_posizione[0]= ceil(vet_posizione[0])-0.5; vet_velocita[0]= -vet_velocita[0]/1.2; //rimbalso parzialmente anelastico if ((vet_velocita[0] < -VELOCITA_DI_MORTE )||(vet_velocita[0] > VELOCITA_DI_MORTE )) palla_viva=false; muro_di_morte = 3; } if (((altezza_punto_controllo_obl_1>(vet_posizione.y()))&& //sud ovest (controllo[i][1]-0.25) >= ( mp->getY(controllo[i][0],controllo[i][2])) && (controllo[2][1]-0.25) >= ( mp->getY(controllo[2][0],controllo[2][2])) && alpha==0) || ((altezza_punto_controllo_obl_1>(vet_posizione.y()))&& (controllo[i][1]) >= ( mp->getY(controllo[i][0],controllo[i][2])) && (controllo[2][1]) >= ( mp->getY(controllo[2][0],controllo[2][2]))&& alpha!=0)) { vet_posizione[1]= old_vet_pos[1]; vet_posizione[0]= ceil(vet_posizione[0])-0.65; vet_velocita[0]= -vet_velocita[0]/1.2; if ((vet_velocita[0] < -VELOCITA_DI_MORTE )||(vet_velocita[0] > VELOCITA_DI_MORTE )) palla_viva=false; muro_di_morte = 3; } if ( ((altezza_punto_controllo_obl_2>(vet_posizione.y()))&& //nord ovest (controllo[i][1]-0.25) >= ( mp->getY(controllo[i][0],controllo[i][2])) && (controllo[0][1]-0.25) >= ( mp->getY(controllo[0][0],controllo[0][2]))&& alpha==0) || ((altezza_punto_controllo_obl_2>(vet_posizione.y()))&& (controllo[i][1]) >= ( mp->getY(controllo[i][0],controllo[i][2])) && (controllo[0][1]) >= ( mp->getY(controllo[0][0],controllo[0][2]))&& alpha!=0)) { vet_posizione[1]= old_vet_pos[1]; vet_posizione[0]= ceil(vet_posizione[0])-0.65; vet_velocita[0]=-vet_velocita[0]/1.2; if ((vet_velocita[2] < -VELOCITA_DI_MORTE )|| (vet_velocita[2] > VELOCITA_DI_MORTE )) palla_viva=false; muro_di_morte = 3; } } break; } } //============================================collision det inclinato==================================== for (int i=0;i<4;i++) controllo[i].Zero(); controllo[0][0]=vet_posizione[0]; controllo[0][1]=vet_posizione[1]; controllo[0][2]=vet_posizione[2]-0.5; controllo[1][0]=vet_posizione[0]+0.5; controllo[1][1]=vet_posizione[1]; controllo[1][2]=vet_posizione[2]; controllo[2][0]=vet_posizione[0]; controllo[2][1]=vet_posizione[1]; controllo[2][2]=vet_posizione[2]+0.5; controllo[3][0]=vet_posizione[0]-0.5; controllo[3][1]=vet_posizione[1]; controllo[3][2]=vet_posizione[2]; //fin qui ho settato le posizioni dei punti di controllo for (int i=0;i<4;i++) { float differ =( (vet_posizione[1]) -mp->getY(controllo[i][0],controllo[i][2]) ); if (differ <= 0.45) tocca_mappa_inclinata=true; else tocca_mappa_inclinata=false; } //======================================================================================================= //==================================collision detection orizzontale====================================== if (vet_posizione[1] <= mp->getY(vet_posizione[0],vet_posizione[2])+0.5) //collision detection { vet_posizione[1]= mp->getY(vet_posizione[0],vet_posizione[2])+0.5 ; tocca_mappa_piana=true; } else tocca_mappa_piana=false; //======================================================================================================= //============================================================================================================== vet_compon_controllo.Zero(); vet_compon_vel_gravita.Zero(); triangolo.normale.Zero(); } else vet_posizione=old_vet_pos; }