📄 ball.c
字号:
actind+=array->prim_size[i]; } } DPRINTF("create_ball_icosa_array: volume=%f\n",volume);#endif scale_ratio=pow((4.0/3.0*r*r*r*M_PI)/fabs(volume),1.0/3.0); DPRINTF("create_ball_icosa_array: scale_ratioe=%f\n",scale_ratio); for(i=0;i<array->vnr*3;i++){ array->vert[i] = array->vert[i]*scale_ratio; } DPRINTF("create_ball_icosa_array: compiling list\n"); glNewList(id, GL_COMPILE); glPushMatrix(); /* call array */ glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glVertexPointer( 3, GL_FLOAT, 0, array->vert ); glNormalPointer( GL_FLOAT, 0, array->norm ); glTexCoordPointer( 2, GL_FLOAT, 0, array->tex ); DPRINTF("indnr=%d\n",array->indnr); DPRINTF("vnr=%d\n",array->vnr);#ifndef USE_TRISTRIPS glDrawElements( GL_TRIANGLES, array->indnr, GL_UNSIGNED_INT, array->index );#else { int actind=0; int i; for(i=0;i<array->num_prim;i++){ glDrawElements( GL_TRIANGLE_STRIP, array->prim_size[i], GL_UNSIGNED_INT, &(array->index[actind]) ); actind+=array->prim_size[i]; } }#endif// glEnd(); glPopMatrix(); glEndList();#endif // fprintf(stderr,"array compiled %d, NE=%d, %d\n",glGetError(),GL_NO_ERROR, array); return array;}#endifvoid calc_reftex( BallType * ball, myvec cam_pos, GLfloat * vp, GLfloat * np, GLfloat * tex, int nr ){ int i; double phi,th,v_abs,v_xy; myvec v_ref,v_in,n,norm; for(i=0;i<nr;i++){ n.x=np[i*3+0]; n.y=np[i*3+1]; n.z=np[i*3+2]; norm = vec_xyz(0,0,0); norm = vec_add( norm, vec_scale(ball->b[0],n.x) ); norm = vec_add( norm, vec_scale(ball->b[1],n.y) ); norm = vec_add( norm, vec_scale(ball->b[2],n.z) ); v_in = vec_diff( ball->r, cam_pos ); v_ref = vec_diff( v_in, vec_scale(vec_proj(v_in,norm),2.0) ); v_abs = vec_abs(v_ref); v_xy = sqrt(v_ref.x*v_ref.x+v_ref.y*v_ref.y); th = acos(v_ref.z/v_abs); phi = atan2(v_ref.y,v_ref.x); tex[i*2+0] = 0.5*(1.0+phi/M_PI); tex[i*2+1] = 0.5*th/M_PI; }}VMvect cutphi0( VMvect p1, VMvect p2 ){ return vec_scale( vec_add(vec_scale(p1,fabs(p2.y)),vec_scale(p2,fabs(p1.y))), 1.0/fabs(p2.y-p1.y) );}void myDrawElements( BallType * ball, ElemArray * array, myvec cam_pos ){ int i,j,k,l,m,n,tchanged; VMvect t[3], p[3]; int cutnr; int cutnr1[3]; int cutnr2[3]; double phi,th,v_abs,v_xy; myvec v_ref[3],v_in; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBegin(GL_TRIANGLES); for(i=0;i<array->indnr;i+=3){ j=array->index[i]; k=array->index[i+1]; l=array->index[i+2]; t[0].x=array->reftex[j*2]; t[0].y=array->reftex[j*2+1]; t[0].z=0.0; t[1].x=array->reftex[k*2]; t[1].y=array->reftex[k*2+1]; t[1].z=0.0; t[2].x=array->reftex[l*2]; t[2].y=array->reftex[l*2+1]; t[2].z=0.0; p[0]=vec_xyz(0,0,0); p[0]=vec_add(p[0],vec_scale(ball->b[0],array->norm[j*3])); p[0]=vec_add(p[0],vec_scale(ball->b[1],array->norm[j*3+1])); p[0]=vec_add(p[0],vec_scale(ball->b[2],array->norm[j*3+2])); p[1]=vec_xyz(0,0,0); p[1]=vec_add(p[1],vec_scale(ball->b[0],array->norm[k*3])); p[1]=vec_add(p[1],vec_scale(ball->b[1],array->norm[k*3+1])); p[1]=vec_add(p[1],vec_scale(ball->b[2],array->norm[k*3+2])); p[2]=vec_xyz(0,0,0); p[2]=vec_add(p[2],vec_scale(ball->b[0],array->norm[l*3])); p[2]=vec_add(p[2],vec_scale(ball->b[1],array->norm[l*3+1])); p[2]=vec_add(p[2],vec_scale(ball->b[2],array->norm[l*3+2])); for(m=0;m<3;m++){ v_in = vec_diff( ball->r, cam_pos );// v_ref[m] = vec_unit(vec_diff( v_in, vec_scale(vec_proj(v_in,p[m]),2.0) )); v_ref[m] = vec_unit(p[m]); v_abs = vec_abs(v_ref[m]); v_xy = sqrt(v_ref[m].x*v_ref[m].x+v_ref[m].y*v_ref[m].y); th = acos(v_ref[m].z/v_abs); phi = atan2(v_ref[m].y,v_ref[m].x); t[m].x = 0.5*(1.0+phi/M_PI); t[m].y = 0.5*th/M_PI;// fprintf(stderr,"tex%d=%f,%f,%f\n",m,p[m].x,p[m].y,p[m].z); }/* if( tri_area_xy( t1,t2,t3 ) < 0.0 ){ if( 1.0-t1.x > t1.x ) t1.x+=1.0; if( 1.0-t2.x > t2.x ) t2.x+=1.0; if( 1.0-t3.x > t3.x ) t3.x+=1.0; }*/ tchanged=0; cutnr=0; for(m=0;m<3;m++){ /* lines 1-2 2-3 3-1 */ n=(m+1)%3; if ( v_ref[m].y>0.0 && v_ref[n].y<0.0 ){ if( cutphi0(v_ref[m],v_ref[n]).x < 0.0 ){// if( v_ref[m].x < 0.0 ){ cutnr1[cutnr]=m; cutnr2[cutnr]=n; /* der kleinere zuerst */ cutnr++; } } else if ( v_ref[m].y<0.0 && v_ref[n].y>0.0 ){ if( cutphi0(v_ref[m],v_ref[n]).x < 0.0 ){// if( v_ref[m].x < 0.0 ){ cutnr1[cutnr]=n; cutnr2[cutnr]=m; cutnr++; } } }// fprintf(stderr,"cutnr=%d\n",cutnr); if(cutnr==2){ /* 2 schnitte mit phi=0 ebene */// fprintf(stderr," cutnr2[0]=%d\n",cutnr2[0]);// fprintf(stderr," cutnr2[1]=%d\n",cutnr2[1]); t[cutnr1[0]].x-=1.0; if(cutnr1[1]!=cutnr1[0]) t[cutnr1[1]].x-=1.0; tchanged=1; } else if(cutnr==1){#if 1 int other;// if( t[0].y<0.25 && t[1].y<0.25 && t[2].y<0.25 ){ if( t[0].y<0.25 ){ t[cutnr1[0]].x-=1.0; other = ((cutnr1[0]+1)^(cutnr2[0]+1))-1;// fprintf(stderr,"other=%d\n",other); t[other].x-=0.5; t[other].y=-t[other].y; tchanged=1; }else{ t[cutnr1[0]].x-=1.0; other = ((cutnr1[0]+1)^(cutnr2[0]+1))-1;// fprintf(stderr,"other=%d\n",other); t[other].x-=0.5; t[other].y=1.0-t[other].y; tchanged=1; }#endif } if(cutnr!=1){ glTexCoord2f( t[0].x,t[0].y ); glNormal3f ( array->norm[j*3],array->norm[j*3+1],array->norm[j*3+2] ); glVertex3f ( array->vert[j*3],array->vert[j*3+1],array->vert[j*3+2] ); glTexCoord2f( t[1].x,t[1].y ); glNormal3f ( array->norm[k*3],array->norm[k*3+1],array->norm[k*3+2] ); glVertex3f ( array->vert[k*3],array->vert[k*3+1],array->vert[k*3+2] ); glTexCoord2f( t[2].x,t[2].y ); glNormal3f ( array->norm[l*3],array->norm[l*3+1],array->norm[l*3+2] ); glVertex3f ( array->vert[l*3],array->vert[l*3+1],array->vert[l*3+2] ); } } glEnd();}void free_elem_array( ElemArray * array ){ free( array->vert ); free( array->norm ); free( array->tex ); free( array->reftex ); free( array->index );}void draw_ball( BallType * ball, myvec cam_pos, GLfloat cam_FOV, int win_width, int reflect )/* expects to be on table center */{ float cnear, cfar, geomfact; static int glballlist[]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; static float ballmatr[]={ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; int i,detail; static int maxdetail=-1; static ElemArray * array[11]; if( maxdetail != options_max_ball_detail ){ for(i=0;i<=maxdetail;i++){ if(glballlist[i]!=-1) glDeleteLists(glballlist[i],1); glballlist[i]=-1;#ifdef USE_VERTEX_ARRAYS for(i=0;i<=maxdetail;i++){ free_elem_array( array[i] ); array[i]=(ElemArray *)0; }#endif } maxdetail = options_max_ball_detail; } if( glballlist[0]==-1 ){ for(i=0;i<=maxdetail;i++){ glballlist[i] = glGenLists(1);#ifdef USE_VERTEX_ARRAYS array[i] = create_ball_icosa_array( BALL_D/2.0, i, glballlist[i] );#else create_ball_icosa( BALL_D/2.0, i, glballlist[i] );#endif } } glPushMatrix(); glTranslatef( ball->r.x, ball->r.y, ball->r.z ); ballmatr[ 0]=ball->b[0].x; ballmatr[ 1]=ball->b[0].y; ballmatr[ 2]=ball->b[0].z; ballmatr[ 4]=ball->b[1].x; ballmatr[ 5]=ball->b[1].y; ballmatr[ 6]=ball->b[1].z; ballmatr[ 8]=ball->b[2].x; ballmatr[ 9]=ball->b[2].y; ballmatr[10]=ball->b[2].z; ballmatr[15]=1.0; glMultMatrixf( ballmatr );/* if(showReflections){ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); }*/// glEnable(GL_TEXTURE_2D); geomfact=40.0/cam_FOV*(double)win_width/800; cnear = options_ball_detail_nearmax*geomfact; cfar = options_ball_detail_farmin*geomfact; // detail=(int)((double)maxdetail-(vec_abs(vec_diff(cam_pos,ball->r))-cnear)/(cfar-cnear)*(double)maxdetail); /* this would lead to a constant face (triangle) size */// detail=maxdetail-2.0*log(vec_abs(vec_diff(cam_pos,ball->r))/options_ball_detail_nearmax)/log(2.0); /* 1.0 instead of 2.0 because angles get smaller when smaller detail */ detail=maxdetail-1.0*log(vec_abs(vec_diff(cam_pos,ball->r))/cnear)/log(2.0); if( detail>maxdetail ) detail=maxdetail; if( detail<0 ) detail=0; #ifdef USE_VERTEX_ARRAYS #if 0 glPushMatrix(); glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glVertexPointer( 3, GL_FLOAT, 0, array[detail]->vert ); glNormalPointer( GL_FLOAT, 0, array[detail]->norm ); if( !reflect ){ glTexCoordPointer( 2, GL_FLOAT, 0, array[detail]->tex ); } else { if(options_calc_ball_reflections){/* calc_reftex( ball, cam_pos, array[detail]->vert, array[detail]->norm, array[detail]->reftex, array[detail]->vnr); glTexCoordPointer( 2, GL_FLOAT, 0, array[detail]->reftex );*/ } else { glTexCoordPointer( 2, GL_FLOAT, 0, array[detail]->tex ); } } if(options_calc_ball_reflections && reflect){// myDrawElements( ball, array[detail], cam_pos ); glDrawElements( GL_TRIANGLES, array[detail]->indnr, GL_UNSIGNED_INT, array[detail]->index ); } else { glDrawElements( GL_TRIANGLES, array[detail]->indnr, GL_UNSIGNED_INT, array[detail]->index ); } glPopMatrix(); #endif glCallList(glballlist[detail]); #else glCallList(glballlist[detail]); #endif glColor3f(1.0, 1.0, 1.0); glPopMatrix(); /* ang mom vec *//* glPushMatrix(); glTranslatef( ball->r.x, ball->r.y, ball->r.z ); wabs=vec_abs(ball->w); vabs=vec_abs(ball->v); if( wabs ){ glBegin(GL_LINES); glVertex3f( 0.0, 0.0, 0.0 ); glVertex3f( ball->w.x/wabs*0.1, ball->w.y/wabs*0.1, ball->w.z/wabs*0.1 ); glVertex3f( 0.0, 0.0, 0.0 ); glVertex3f( ball->v.x/vabs*0.1, ball->v.y/vabs*0.1, ball->v.z/vabs*0.1 ); glEnd(); } glPopMatrix();*/}void my_copy_area_1_3( char * src, int w1, int h1, int wc, int hc, int x0, int y0, char * dst , int w, int h ){ int x,y,i; for(y=0;y<hc;y++){ for(x=0;x<wc;x++){ for(i=0;i<3;i++){ if( src[y*w1+x]!=(char)0xFF ) dst[((y+y0)*w+x+x0)*3+i]=src[y*w1+x];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -