#include #include "tipi.h" #include "sin.h" /* Funzioni di uso comune */ # define NUM_OGETTI (26) //extern Tsin[4096];/* Richiamo alla tavola del seno */ extern GsCOORDINATE2 TELECAMERACORD;/*Richiamo alla globale TELECAMERACORD */ extern long pro ;/* Richiamo alla globale di proiezione */ extern GsRVIEW2 puntovista;/* Richiamo alla globale del punto di vista */ extern SFECOL collisione[NUM_OGETTI][6];/* Richiamo alla vettore globale di collisione Sferica */ extern BOX vetbox[NUM_OGETTI];/* Richiamo alla vettore globale di collisione Boxes */ extern GsCOORDINATE2 coordinate[NUM_OGETTI];/* Richiamo alla vettore globale di coordinate */ extern u_char radice[10000];/* Vettore delle radici */ extern SVECTOR rotazioni[NUM_OGETTI];/* Richiamo al Vettore delle anomalie di ogni ogetto */ void Ruota(SVECTOR anomalia,MATRIX * Matfin,char tipo)/* Ruota l'ogetto con vari tipi di combinazioni di assi */ { MATRIX MatrixX,MatrixY,MatrixZ;/* Matrici contenenti le singole rotazioni di assi X,Y,Z*/ SVECTOR ap;// Vettore di appoggio di anomalie ap.vx=anomalia.vx; ap.vy=0; ap.vz=0; //asse X RotMatrix(&ap,&MatrixX); ap.vx=0; ap.vy=anomalia.vy; ap.vz=0; //asseY RotMatrix(&ap,&MatrixY); ap.vx=0; ap.vy=0; ap.vz=anomalia.vz; //asseZ RotMatrix(&ap,&MatrixZ); switch(tipo)/* SWITCH */ { case 0:/* Tipo */ { MulMatrix0(&MatrixX,&MatrixY,Matfin); MulMatrix0(Matfin,&MatrixZ,Matfin); };tipo=-1;break; case 1:/* Tipo */ { MulMatrix0(&MatrixX,&MatrixZ,Matfin); MulMatrix0(Matfin,&MatrixY,Matfin); };tipo=-1;break; case 2:/* Tipo */ { MulMatrix0(&MatrixY,&MatrixX,Matfin); MulMatrix0(Matfin,&MatrixZ,Matfin); };tipo=-1;break; case 3:/* Tipo */ { MulMatrix0(&MatrixY,&MatrixZ,Matfin); MulMatrix0(Matfin,&MatrixX,Matfin); };tipo=-1;break; case 4:/* Tipo */ { MulMatrix0(&MatrixZ,&MatrixX,Matfin); MulMatrix0(Matfin,&MatrixY,Matfin); };tipo=-1;break; case 5:/* Tipo */ { MulMatrix0(&MatrixZ,&MatrixY,Matfin); MulMatrix0(Matfin,&MatrixX,Matfin); };tipo=-1;break; } } long Modulo(long a) { if(a<0) return a*(-1); else return a; } long SENO(long alfa) /* Mia funzione Seno dove 0-4095 0-2PGRECO*/ { if(alfa!=0) { if (alfa>0) { alfa=alfa%4096; return Tsin[(alfa)]; } else { alfa=-(alfa%4096); return ((-1)*rsin((-1)*(alfa))); } } else return 0; } long COSENO(long alfa) /* Mia funzione Coseno dove 0-4095 0-2PGRECO*/ { return SENO(alfa+1024); } void Partiziona(long F,long *fx,long *fy,long *fz,char in)// Partiziono la forza totale agente sull'ogetto in { // Ho side effects long Fp=0; *fy=-(F*SENO(rotazioni[in].vx))/ONE; Fp=(F*COSENO(rotazioni[in].vx))/ONE; *fz=(Fp*COSENO(rotazioni[in].vy))/ONE; *fx=(Fp*SENO(rotazioni[in].vy))/ONE; } ConvNumlo(long num)/* converte in stringa un numero di 32 bits con segno */ { int cont=0;/* Contatore divisore */ u_long div=1000000000;/* Valore di divisione */ if(num<0) {/* Valore negativo*/ FntPrint("-");/* Metto il segno alla stringa*/ num=num*(-1); } for(cont=0;cont<=9;cont++) { switch(num/div) { case 0: { if (cont==9) FntPrint("0"); }; break; case 1: { FntPrint("1"); }; break; case 2: { FntPrint("2"); }; break; case 3: { FntPrint("3"); }; break; case 4: { FntPrint("4"); }; break; case 5: { FntPrint("5"); }; break; case 6: { FntPrint("6"); }; break; case 7: { FntPrint("7"); }; break; case 8: { FntPrint("8"); }; break; case 9: { FntPrint("9"); }; break; } num=num%div;/*Assegno a num il resto della divisione per il divisore */ div=div/10; } } long Potenza(long x,long y) { long temp=x;/* Variabile temporanea */ int i1;/* Indice */ if(y==0) return 1; else if(y==1) return temp; else { for(i1=1;i1<=(y-1);i1++) temp=temp*x; return temp; } } void LocalScreen(GsCOORDINATE2 * cord,VECTOR * out)/* Funzione di conversione local screen di posizione di un ogetto gestito da cord */ { VECTOR in;/* Vettore che contiene le coordinate dell'ogetto */ MATRIX matr1lw,matr1ls;/* Matrici di appoggio */ long Xs,Ys,Zs,Xss,Yss;/* Variabili locali di uso per la conversione */ /* Calcolo coordinate di schermo di ogni ogetto */ /* Assegno le coordinate del figlio rispetto al padre */ in.vx=(*cord).coord.t[0]; in.vy=(*cord).coord.t[1]; in.vz=(*cord).coord.t[2]; if((*cord).super!=WORLD)/* L'ogetto non figlio del mondo */ { GsGetLws((*cord).super,&matr1lw,&matr1ls);/* Setto subito la LS e LW matrix del padre dell'ogetto */ /* ora che ho le matrici LS che mi servone posso calcolare le Xs,Ys,Zs*/ ApplyMatrixLV(&matr1ls,&in,out);/* Moltiplico la matrice LS per il vettore 3x1 delle coordinate locali del punto Xl,Yl,Zl e ottengo le coordinate di rotazione rispetto allo schermo Teoretico*/ /* Pongo la traslazione relativa alla Local---->Screen */ Xs=(*out).vx+matr1ls.t[0]; Ys=(*out).vy+matr1ls.t[1]; Zs=(*out).vz+matr1ls.t[2]; } else /* L'ogetto figlio del mondo */ { ApplyMatrixLV(&(GsWSMATRIX),&in,out);/* Moltiplico la matrice WS per le coordinate del mondo in VL 3x1 ed ottengo in VR le coordinate di rotazione rispetto allo schermo Teoretico */ /* Pongo la traslazione relativa alla World---->Screen */ Xs=(*out).vx+GsWSMATRIX.t[0]; Ys=(*out).vy+GsWSMATRIX.t[1]; Zs=(*out).vz+GsWSMATRIX.t[2]; } /* Calcolo posizioni sullo schermo teoretico */ Xss=(pro*Xs)/Zs; Yss=(pro*Ys)/Zs; /* Assegno le coordinate al vettore ZSORT */ (*out).vx=Xss; (*out).vy=Yss; (*out).vz=Zs; /* Calcolo coordinate di schermo di ogni ogetto */ } void LocalScreenPoint(GsCOORDINATE2 * cord,VECTOR * out)/* Funzione di conversione local screen di un punto di un ogetto gestito da cord */ { VECTOR in;/* Vettore che contiene le coordinate dell'ogetto */ MATRIX matr1lw,matr1ls;/* Matrici di appoggio */ long Xs,Ys,Zs,Xss,Yss;/* Variabili locali di uso per la conversione */ /* Calcolo coordinate di schermo di ogni ogetto */ /* Assegno le coordinate del figlio rispetto al padre */ in.vx=(*out).vx; in.vy=(*out).vy; in.vz=(*out).vz; GsGetLws(cord,&matr1lw,&matr1ls);/* Setto subito la LS e LW matrix dell'ogetto */ /* ora che ho le matrici LS che mi servone posso calcolare le Xs,Ys,Zs*/ ApplyMatrixLV(&matr1ls,&in,out);/* Moltiplico la matrice LS per il vettore 3x1 delle coordinate locali del punto Xl,Yl,Zl e ottengo le coordinate di rotazione rispetto allo schermo Teoretico*/ /* Pongo la traslazione relativa alla Local---->Screen */ Xs=(*out).vx+matr1ls.t[0]; Ys=(*out).vy+matr1ls.t[1]; Zs=(*out).vz+matr1ls.t[2]; /* Calcolo posizioni sullo schermo teoretico */ Xss=(pro*Xs)/Zs; Yss=(pro*Ys)/Zs; /* Assegno le coordinate al vettore ZSORT */ (*out).vx=Xss; (*out).vy=Yss; (*out).vz=Zs; /* Calcolo coordinate di schermo di ogni ogetto */ } void LocalWorld(GsCOORDINATE2 * cord,VECTOR * out)/* Funzione di conversione local world di posizione di un ogetto gestito da cord */ { VECTOR in;/* Vettore che contiene le coordinate dell'ogetto */ MATRIX matr1lw,matr1ls;/* Matrici di appoggio */ long Xw,Yw,Zw;/* Variabili locali di uso per la conversione */ /* Calcolo coordinate di Mondo di ogni ogetto */ /* Assegno le coordinate del figlio rispetto al padre */ in.vx=(*cord).coord.t[0]; in.vy=(*cord).coord.t[1]; in.vz=(*cord).coord.t[2]; if((*cord).super!=WORLD)/* L'ogetto non figlio del mondo */ { GsGetLws((*cord).super,&matr1lw,&matr1ls);/* Setto subito la LS e LW matrix del padre dell'ogetto */ /* ora che ho le matrici LS che mi servone posso calcolare le Xs,Ys,Zs*/ ApplyMatrixLV(&matr1lw,&in,out);/* Moltiplico la matrice LS per il vettore 3x1 delle coordinate locali del punto Xl,Yl,Zl e ottengo le coordinate di rotazione rispetto al Mondo*/ /* Pongo la traslazione relativa alla Local---->World */ Xw=(*out).vx+matr1lw.t[0]; Yw=(*out).vy+matr1lw.t[1]; Zw=(*out).vz+matr1lw.t[2]; } else /* L'ogetto figlio del mondo */ { /* Pongo la traslazione relativa alla Local---->World */ Xw=in.vx; Yw=in.vy; Zw=in.vz; } /* Assegno le coordinate al vettore out */ (*out).vx=Xw; (*out).vy=Yw; (*out).vz=Zw; /* Calcolo coordinate di Mondo di ogni ogetto */ } // ASSEGNARE AL PARAMETRO CORD IL PUNTATORE DEL CAMPO COORD2 DEL TIPO GsDOBJ2 nelle funzioni sopra create !!!!! O IL // GESTORE DELL'OGETTO IN QUESTIONE void LocalWorldPoint(GsCOORDINATE2 * cord,VECTOR * in,VECTOR * out)/* Funzione che calcola la posizione mondo di un punto in coordinate locali di un ogetto */ { MATRIX lw,ls;/* Matrici local-world e local-screen */ GsGetLws(cord,&lw,&ls);/* Setto subito la LS e LW matrix del padre dell'ogetto */ ApplyMatrixLV(&lw,in,out);/* Moltiplico la matrice LW per il vettore 3x1 delle coordinate locali del punto e ottengo le coordinate di rotazione rispetto al Mondo*/ /* Sommo il fattore di traslazione */ (*out).vx+=lw.t[0]; (*out).vy+=lw.t[1]; (*out).vz+=lw.t[2]; } void Local1Local2(VECTOR * p1/* Input Point */,VECTOR * p2/* Output Point */,GsCOORDINATE2 * l1,GsCOORDINATE2 * l2)/* converte le coordinate locali di un ogetto in coordinate locali di un altro ogetto */ { VECTOR p1w;/* Coordinate del punto rispetto al mondo */ LocalWorldPoint(l1,p1,&p1w);/* Converto Local---->World */ puntovista.super=l2;/* Assegno come padre del punto di vista il secondo ogetto */ GsSetRefView2(&puntovista);/* Setto la nuova GsWSMATRIX */ ApplyMatrixLV(&GsWSMATRIX,&p1w,p2);/* Applico il fattore di ROTAZIONE al punto in coordinate del mondo */ (*p2).vx+=GsWSMATRIX.t[0];// Traslazione X (*p2).vy+=GsWSMATRIX.t[1];// Traslazione Y (*p2).vz+=GsWSMATRIX.t[2];// Traslazione Z puntovista.super=&TELECAMERACORD; GsSetRefView2(&puntovista);/* Riassegno il punto di vista della telecamera */ } int ColBox(u_char h,u_char k) { int i1;/* Contatore */ int flag=0; for(i1=0;i1<=5;i1++) { VECTOR p,p1;/* Coordinate punto rispetto a local 2,punto rispetto a local 1*/ switch(i1)/* SWITCH */ { case 0:/* X positivo */ { p1.vx=(vetbox[h]).pos.vx; p1.vy=0; p1.vz=0; };break; case 1:/* X negativo*/ { p1.vx=(vetbox[h]).neg.vx; p1.vy=0; p1.vz=0; };break; case 2:/* Y positivo */ { p1.vx=0; p1.vy=(vetbox[h]).pos.vy; p1.vz=0; };break; case 3:/* Y negativo */ { p1.vx=0; p1.vy=(vetbox[h]).neg.vy; p1.vz=0; };break; case 4:/* Z positivo */ { p1.vx=0; p1.vy=0; p1.vz=(vetbox[h]).pos.vz; };break; case 5:/* Z negativo */ { p1.vx=0; p1.vy=0; p1.vz=(vetbox[h]).neg.vz; };break; } Local1Local2(&p1,&p,&(coordinate[h]),&(coordinate[k]));/* Pongo in p le coordinate di p1 rispetto a local 2 */ if(/* vedo se p rientra nel box di k */ (p.vx<=(vetbox[k].pos.vx))&& (p.vx>=(vetbox[k].neg.vx))&& (p.vy<=(vetbox[k].pos.vy))&& (p.vy>=(vetbox[k].neg.vy))&& (p.vz<=(vetbox[k].pos.vz))&& (p.vz>=(vetbox[k].neg.vz)) ) /* Allora*/ { i1=6;/* Esco dal ciclo*/ flag=1; } } return flag; } int DetectColBox(u_char h,u_char k)/* Detecta se il box h entra nel box k o viceversa */ { return ((ColBox(h,k))||(ColBox(k,h)));/* h entra in k o k entra in h*/ } int DetectCollision(u_short h,u_short k)/* Funzione che verifica se l'ogetto h in collisione con l'ogetto k*/ { int i1,i2,flag;/* Indici di scorrimento delle sfere dell'ogetto h-esimo e k-esimo e flag di collisione */ VECTOR p0,p1;/* Coordinate world de punti centrali delle 2 sfere */ long Xm,Ym,Zm,arg;/* Distanze assiali dei 2 ogetti e argomento */ flag=0; i1=1; if((collisione[h][0].ray==0)||(collisione[k][0].ray==0))/* Uno dei due non ha sfere di collisione */ { return 0; } else /* Entrambi hanno sfere di collisione */ { while((i1<=collisione[h][0].ray)&&(flag==0))/* Per ogni sfera di collisione del primo */ { i2=1; while((i2<=collisione[k][0].ray)&&(flag==0))/* Controllo tutte le sfere del secondo */ { LocalWorldPoint(&(coordinate[h]),&(collisione[h][i1].localpos),&p0);/* Calcolo la posizione della sfera i1-esima dell' h-esimo ogetto */ LocalWorldPoint(&(coordinate[k]),&(collisione[k][i2].localpos),&p1);/* Calcolo la posizione della sfera i2-esima del k-esimo ogetto */ /* Calcolo distanza */ /* Aggiustamento distanze assiali */ if(p0.vx>p1.vx) Xm=p0.vx-p1.vx; else Xm=p1.vx-p0.vx; if(p0.vy>p1.vy) Ym=p0.vy-p1.vy; else Ym=p1.vy-p0.vy; if(p0.vz>p1.vz) Zm=p0.vz-p1.vz; else Zm=p1.vz-p0.vz; arg=Potenza(Xm,2)+Potenza(Ym,2)+Potenza(Zm,2);/* arg la distanza al quadrato */ if (arg<=(Potenza(collisione[h][i1].ray+collisione[k][i2].ray,2)))/* vedo se la distanza^2 +piccola del^2 della somma dei raggi */ flag=1;/* Ho detectato la collisione !!! */ i2++; } i1++; } return flag;/* Ritorno flag 0 se non detectata 1 se detectata */ } }