📄 queue.c
字号:
/* queue.c**** create the billard-queue display lists** Copyright (C) 2001 Florian Berger** Email: harpin_floh@yahoo.de, florian.berger@jk.uni-linz.ac.at**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License Version 2 as** published by the Free Software Foundation;**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***/#include <math.h>#include <stdlib.h>#include <stdio.h>#include <math.h>#include <GL/glu.h>#include <GL/gl.h>#include "billard.h"#include "queue.h"#include "png_loader.h"#include "options.h"static GLfloat col_shad [4] = {0.1, 0.1, 0.1, 1.0};static double cue_shad_w = 0.07;static double cue_shad_w2 = 0.014;static int queuetexbind;double rfunc(double x){ return(cos(x*M_PI));}int create_queue(double (*rfunc)(double)){ int queue_obj, i,j; int sidenr=16; GLfloat dl1=0.004; GLfloat dl2=0.001; double ph; VMvect v1,v2,n1,n2; int segnr=5; /* number of segments along the cue */ double r1,r2,dr1,dr2; queue_obj = glGenLists(1); glNewList(queue_obj, GL_COMPILE); for(j=0;j<segnr;j++){ glBegin(GL_QUAD_STRIP); r1=0.5*(QUEUE_D1-(QUEUE_D1-QUEUE_D2)*(rfunc((double)j/segnr)-rfunc(0))/(rfunc(1)-rfunc(0))); r2=0.5*(QUEUE_D1-(QUEUE_D1-QUEUE_D2)*(rfunc((double)(j+1)/segnr)-rfunc(0))/(rfunc(1)-rfunc(0))); dr1=0.5*(QUEUE_D1-(QUEUE_D1-QUEUE_D2)*(rfunc((double)j/segnr+0.001)-rfunc(0))/(rfunc(1)-rfunc(0))); dr1=(dr1-r1)/0.001; dr2=0.5*(QUEUE_D1-(QUEUE_D1-QUEUE_D2)*(rfunc((double)(j+1)/segnr+0.001)-rfunc(0))/(rfunc(1)-rfunc(0))); dr2=(dr2-r2)/0.001; for(i=0;i<sidenr+1;i++){ ph=2.0*M_PI/(double)sidenr*i;/* v1.x = QUEUE_D1/2.0*cos(ph); v1.y = QUEUE_D1/2.0*sin(ph); v1.z = QUEUE_L-dl1; v2.x = QUEUE_D2/2.0*cos(ph); v2.y = QUEUE_D2/2.0*sin(ph); v2.z = dl2; n.x = (QUEUE_L-dl1-dl2)*cos(ph); n.y = (QUEUE_L-dl1-dl2)*sin(ph); n.z = -(QUEUE_D1-QUEUE_D2)/2.0;*/ v1.x = r1*cos(ph); v1.y = r1*sin(ph); v1.z = (QUEUE_L-dl1)-(QUEUE_L-dl1-dl2)/segnr*j; v2.x = r2*cos(ph); v2.y = r2*sin(ph); v2.z = (QUEUE_L-dl1)-(QUEUE_L-dl1-dl2)/segnr*(j+1); n1.x = cos(ph); n1.y = sin(ph); n1.z = -dr1; n1=vec_unit(n1); n2.x = cos(ph); n2.y = sin(ph); n2.z = -dr2; n2=vec_unit(n2); glNormal3f( n2.x, n2.y, n2.z ); glTexCoord2f( 1.0-v2.z/QUEUE_L, (v2.x+QUEUE_D1/2.0)/QUEUE_D1 ); glVertex3f( v2.x, v2.y, v2.z ); glNormal3f( n1.x, n1.y, n1.z ); glTexCoord2f( 1.0-v1.z/QUEUE_L, (v1.x+QUEUE_D1/2.0)/QUEUE_D1 ); glVertex3f( v1.x, v1.y, v1.z ); } glEnd(); } glBegin(GL_TRIANGLE_FAN); glNormal3f( 0.0, 0.0, -1.0 ); glVertex3f( 0.0, 0.0, 0.0 ); for(i=0;i<sidenr+1;i++){ ph=2.0*M_PI/(double)sidenr*i; v2.x = QUEUE_D2/2.0*cos(ph); v2.y = QUEUE_D2/2.0*sin(ph); v2.z = dl2; glTexCoord2f( 1.0-v2.z/QUEUE_L, (v2.x+QUEUE_D1/2.0)/QUEUE_D1 ); glVertex3f( v2.x, v2.y, v2.z ); } glEnd(); glBegin(GL_TRIANGLE_FAN); glNormal3f( 0.0, 0.0, 1.0 ); glVertex3f( 0.0, 0.0, QUEUE_L ); for(i=0;i<sidenr+1;i++){ ph=2.0*M_PI-2.0*M_PI/(double)sidenr*i; v1.x = QUEUE_D1/2.0*cos(ph); v1.y = QUEUE_D1/2.0*sin(ph); v1.z = QUEUE_L-dl1; glTexCoord2f( 1.0-v1.z/QUEUE_L, (v1.x+QUEUE_D1/2.0)/QUEUE_D1 ); glVertex3f( v1.x, v1.y, v1.z ); } glEnd(); glEndList(); return queue_obj;}void delete_queue_texbind( void ){ glDeleteTextures(1,&queuetexbind);}void create_queue_texbind( void ){ int queuetexw,queuetexh, depth; char * queuetexdata; glGenTextures(1,&queuetexbind); load_png("queue.png",&queuetexw,&queuetexh,&depth,&queuetexdata); glBindTexture(GL_TEXTURE_2D,queuetexbind); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, queuetexw, queuetexh, GL_RGB, GL_UNSIGNED_BYTE, queuetexdata); free(queuetexdata);}void draw_queue( VMvect pos0, GLfloat Xrot, GLfloat Zrot, GLfloat zoffs, GLfloat xoffs, GLfloat yoffs, int spheretexbind, VMvect * lightpos, int lightnr ){ static int init=0; static int queue_obj; static int queueshadowbind; static int queuetexw,queuetexh; static char * queuetexdata; GLfloat queue_col_spec[4] = {0.0, 0.0, 0.0, 1.0}; GLfloat queue_col_diff[4] = {0.8, 0.8, 0.8, 1.0}; GLfloat queue_col_refl[4] = {1.0, 1.0, 1.0, 0.2}; GLfloat queue_col_amb [4]; int i,depth; VMvect dir,nx,ny,hitpoint,pos; dir = vec_xyz(sin(Zrot*M_PI/180.0)*sin(Xrot*M_PI/180.0), cos(Zrot*M_PI/180.0)*sin(Xrot*M_PI/180.0), cos(Xrot*M_PI/180.0)); nx = vec_unit(vec_cross(vec_ez(),dir)); /* parallel to table */ ny = vec_unit(vec_cross(nx,dir)); /* orthogonal to dir and nx */ hitpoint = vec_add(vec_scale(nx,xoffs),vec_scale(ny,yoffs)); pos = vec_add(pos0,hitpoint); pos = vec_add(pos,vec_scale(dir,zoffs)); for(i=0;i<3;i++) queue_col_amb[i]=queue_col_diff[i]*0.5; if(!init){ if( options_queue_tex ){ create_queue_texbind();/* glGenTextures(1,&queuetexbind); load_png("queue.png",&queuetexw,&queuetexh,&depth,&queuetexdata); glBindTexture(GL_TEXTURE_2D,queuetexbind); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, queuetexw, queuetexh, GL_RGB, GL_UNSIGNED_BYTE, queuetexdata); free(queuetexdata);*/ glGenTextures(1,&queueshadowbind); load_png("queue_shadow.png",&queuetexw,&queuetexh,&depth,&queuetexdata); glBindTexture(GL_TEXTURE_2D,queueshadowbind); gluBuild2DMipmaps(GL_TEXTURE_2D, 1, queuetexw, queuetexh, GL_LUMINANCE, GL_UNSIGNED_BYTE, queuetexdata); free(queuetexdata); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter); } else { queuetexbind=0; } queue_obj=create_queue(rfunc); init=1; } glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glMaterialfv(GL_FRONT, GL_DIFFUSE, queue_col_diff); glMaterialfv(GL_FRONT, GL_AMBIENT, queue_col_amb); glMaterialfv(GL_FRONT, GL_SPECULAR, queue_col_spec); glMaterialf (GL_FRONT, GL_SHININESS, 0.0 ); glPushMatrix(); glTranslatef( pos.x, pos.y, pos.z ); glRotatef( -Zrot, 0.0, 0.0, 1.0 ); glRotatef( -Xrot, 1.0, 0.0, 0.0 );// glTranslatef( 0.0, 0.0, zoffs ); glBindTexture(GL_TEXTURE_2D,queuetexbind); glCallList( queue_obj ); /* draw queue-reflections */ if( options_queue_reflect ){ glPolygonOffset( 0.0, -1.0 ); glEnable( GL_POLYGON_OFFSET_FILL ); glDepthMask (GL_FALSE); glEnable(GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE); glMaterialfv(GL_FRONT, GL_DIFFUSE, queue_col_refl); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBindTexture(GL_TEXTURE_2D,spheretexbind); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glCallList( queue_obj ); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_BLEND); glDepthMask (GL_TRUE); glDisable( GL_POLYGON_OFFSET_FILL ); } glPopMatrix(); /* draw queue-shadow */ if( options_queue_shadows ){ if( options_simple_queue_shadows ){ glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glMaterialfv(GL_FRONT, GL_DIFFUSE, col_shad); glDepthMask (GL_FALSE); glEnable(GL_BLEND);// glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);// glBlendFunc (GL_ZERO, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTranslatef( pos.x, pos.y, -BALL_D/2.02 ); glRotatef( -Zrot, 0.0, 0.0, 1.0 );// glTranslatef( 0.0, -zoffs, 0.0 ); glBindTexture(GL_TEXTURE_2D,queueshadowbind); glBegin(GL_QUADS); glNormal3f(0.0,0.0,1.0); glTexCoord2f(0.0,0.0); glVertex3f(-cue_shad_w,0.0,0.0); glNormal3f(0.0,0.0,1.0); glTexCoord2f(1.0,0.0); glVertex3f(+cue_shad_w,0.0,0.0); glNormal3f(0.0,0.0,1.0); glTexCoord2f(1.0,1.0); glVertex3f(+cue_shad_w,-4.0*cue_shad_w,0.0); glNormal3f(0.0,0.0,1.0); glTexCoord2f(0.0,1.0); glVertex3f(-cue_shad_w,-4.0*cue_shad_w,0.0); glEnd(); glDisable(GL_BLEND); glDepthMask (GL_TRUE); } if( !options_simple_queue_shadows ){ VMvect p1,p2,vn; GLfloat col_spec [4] = {0.0, 0.0, 0.0, 1.0}; /* dont need any specular because of reflections */ GLfloat col_amb [4] = {0.2, 0.2, 0.2, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT, col_amb ); glMaterialfv(GL_FRONT, GL_SPECULAR, col_spec); glMaterialf (GL_FRONT, GL_SHININESS, 0.0 ); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDepthMask (GL_FALSE); glEnable(GL_BLEND);// glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);// glBlendFunc (GL_ZERO, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); for(i=0;i<lightnr;i++){ /* cue tip projected on table */ p1 = vec_surf_proj(lightpos[i], /* proj point */ pos, /* point to proj */ vec_xyz(0,0,1), /* surface normal */ vec_xyz(0,0,-BALL_D/2.02) /* surface pos */ ); /* cue tail (somewhat) projected on table */ p2 = vec_surf_proj(lightpos[i], /* proj point */ vec_add(pos,vec_scale(dir,0.3)), /* point to proj */ vec_xyz(0,0,1), /* surface normal */ vec_xyz(0,0,-BALL_D/2.02) /* surface pos */ );/* p1= vec_xyz(0.2,0.5,-0.028292); p2= vec_xyz(-0.2,-0.5,-0.028292);*/// fprintf(stderr,"i=%d, p1=<%f,%f,%f>, p2=<%f,%f,%f>\n",i,p1.x,p1.y,p1.z,p2.x,p2.y,p2.z); vn = vec_diff(p2,p1); vn = vec_unit(vec_xyz(-vn.y,vn.x,0.0)); col_shad[0]=0.7-0.4*vec_abs(vec_diff(lightpos[i],p1)); col_shad[1]=col_shad[0]; col_shad[2]=col_shad[0]; col_shad[3]=1.0; glMaterialfv(GL_FRONT, GL_DIFFUSE, col_shad); glPushMatrix(); glBindTexture(GL_TEXTURE_2D,queueshadowbind); glBegin(GL_QUADS); glNormal3f(0.0,0.0,1.0); glTexCoord2f(0.0,0.0); glVertex3f(p1.x-vn.x*cue_shad_w2,p1.y-vn.y*cue_shad_w2,p1.z); glNormal3f(0.0,0.0,1.0); glTexCoord2f(1.0,0.0); glVertex3f(p1.x+vn.x*cue_shad_w2,p1.y+vn.y*cue_shad_w2,p1.z); glNormal3f(0.0,0.0,1.0); glTexCoord2f(1.0,1.0); glVertex3f(p2.x+vn.x*cue_shad_w2,p2.y+vn.y*cue_shad_w2,p2.z); glNormal3f(0.0,0.0,1.0); glTexCoord2f(0.0,1.0); glVertex3f(p2.x-vn.x*cue_shad_w2,p2.y-vn.y*cue_shad_w2,p2.z); glEnd(); glPopMatrix(); } glDisable(GL_BLEND); glDepthMask (GL_TRUE); } } if( options_avatar_on ){ #define upperarm_l 0.30 #define forearm_l 0.35 #define shoulder_l 0.35 #define shoulder1_h 0.50 VMvect shoulder1, shoulder2, shoulder_dir, hand1, hand2, elbow1, elbow2, xdir, ydir; double x1,x; hand2 = vec_add(pos0,hitpoint); hand2 = vec_add(hand2,vec_scale(dir,0.3)); shoulder1 = vec_add(pos0,hitpoint); shoulder1 = vec_add(shoulder1,vec_scale(dir,1.25)); shoulder1.z = shoulder1_h; shoulder_dir = vec_unit(vec_add(vec_add(vec_scale(nx,-0.4),vec_scale(ny,0.4)),vec_scale(dir,-0.7))); shoulder2 = vec_add(shoulder1,vec_scale(shoulder_dir,shoulder_l)); hand1 = vec_add(pos,vec_scale(dir,1.2)); xdir = vec_unit(vec_diff(shoulder1,hand1)); ydir = vec_unit(vec_cross(nx,xdir)); x = vec_abs(vec_diff(shoulder1,hand1)); x1 = x/2.0 + (upperarm_l*upperarm_l - forearm_l*forearm_l)/x; elbow1 = vec_add(vec_scale(xdir,-x1),vec_scale(ydir,sqrt(upperarm_l*upperarm_l-x1*x1))); elbow1 = vec_add(elbow1,shoulder1); xdir = vec_unit(vec_diff(shoulder2,hand2)); ydir = vec_unit(vec_cross(nx,xdir)); x = vec_abs(vec_diff(shoulder2,hand2)); x1 = x/2.0 + (upperarm_l*upperarm_l - forearm_l*forearm_l)/x; elbow2 = vec_add(vec_scale(xdir,-x1),vec_scale(ydir,sqrt(upperarm_l*upperarm_l-x1*x1))); elbow2 = vec_add(elbow2,shoulder2);// elbow2 = vec_add(vec_scale(xdir,x2),vec_scale(ydir,sqrt(forearm_l*forearm_l-x2*x2))); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glColor3f(1.0,1.0,1.0); glBegin(GL_LINE_STRIP); glVertex3f( hand1.x, hand1.y, hand1.z ); glVertex3f( elbow1.x, elbow1.y, elbow1.z ); glVertex3f( shoulder1.x, shoulder1.y, shoulder1.z ); glVertex3f( shoulder2.x, shoulder2.y, shoulder2.z );// glVertex3f( elbow2.x, elbow2.y, elbow2.z ); glVertex3f( hand2.x, hand2.y, hand2.z ); glEnd(); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -