//-------------------------------------------------------------------- void RglBilinearPatch (float p[2][2][3], int detail) { float norm[3]; int i; int j; float ***subdiv; double uInc; double vInc; double u; double v; int uDetail; int vDetail; if (detail < 1) detail = 1; // uDetail = vDetail = detail; //-- figure out a nice subdivision... float tmpA; float tmpB; float tmpC; float uDist; float vDist; tmpA = p[0][0][0]-p[0][1][0]; tmpB = p[0][0][1]-p[0][1][1]; tmpC = p[0][0][2]-p[0][1][2]; uDist = fabs(tmpA) + fabs(tmpB) + fabs(tmpC); tmpA = p[1][0][0]-p[1][1][0]; tmpB = p[1][0][1]-p[1][1][1]; tmpC = p[1][0][2]-p[1][1][2]; uDist += fabs(tmpA) + fabs(tmpB) + fabs(tmpC); tmpA = p[0][0][0]-p[1][0][0]; tmpB = p[0][0][1]-p[1][0][1]; tmpC = p[0][0][2]-p[1][0][2]; vDist = fabs(tmpA) + fabs(tmpB) + fabs(tmpC); tmpA = p[0][1][0]-p[1][1][0]; tmpB = p[0][1][1]-p[1][1][1]; tmpC = p[0][1][2]-p[1][1][2]; vDist += fabs(tmpA) + fabs(tmpB) + fabs(tmpC); if(uDist < vDist) { uDetail = detail; vDetail = (int)((float)detail*(uDist/vDist)); } else { uDetail = (int)((float)detail*(vDist/uDist)); vDetail = detail; } //-- sanity checks... if(vDetail < 1) vDetail = 1; if(uDetail < 1) uDetail = 1; if(vDetail > 100) vDetail = 100; if(uDetail > 100) uDetail = 100; //-- allocate memory subdiv = new float**[vDetail+1]; for (i = 0; i < vDetail+1; i++) { subdiv[i] = new float*[uDetail+1]; for (j = 0; j < uDetail+1; j++) subdiv[i][j] = new float[3]; } //-- calculate vertices uInc = 1.0/(double)uDetail; vInc = 1.0/(double)vDetail; v = 0.0; for (i = 0; i < vDetail+1; i++) { u = 0.0; for (j = 0; j < uDetail+1; j++) { subdiv[i][j][0] = (1.0-u)*(1.0-v)*p[0][0][0] + u*(1.0-v)*p[1][0][0] + (1.0-u)*v*p[0][1][0] + u*v*p[1][1][0]; subdiv[i][j][1] = (1.0-u)*(1.0-v)*p[0][0][1] + u*(1.0-v)*p[1][0][1] + (1.0-u)*v*p[0][1][1] + u*v*p[1][1][1]; subdiv[i][j][2] = (1.0-u)*(1.0-v)*p[0][0][2] + u*(1.0-v)*p[1][0][2] + (1.0-u)*v*p[0][1][2] + u*v*p[1][1][2]; // flip Z for gl/RIB compatibility subdiv[i][j][2] = -subdiv[i][j][2]; u += uInc; } v += vInc; } float s1, s2, t1, t2, ud, vd; ud = uDetail; vd = vDetail; //-- draw vertices for (i = 0; i < vDetail; i++) { //ooops - u,v are backwards... s1 = i/vd; s2 = (i+1)/vd; t1 = 0.0; t2 = 0.0; glBegin(GL_TRIANGLE_STRIP); calcNormal (norm, subdiv[i][1], subdiv[i+1][1], subdiv[i][0]); glNormal3fv (norm); glTexCoord2f_M0(s2, t1); glTexCoord2f_M1(s2, t1); glVertex3fv(subdiv[i+1][0]); glTexCoord2f_M0(s1, t1); glTexCoord2f_M1(s1, t1); glVertex3fv(subdiv[i ][0]); for (j = 0; j < uDetail; j++) { t1 = j/ud; t2 = (j+1)/ud; calcNormal (norm, subdiv[i][j+1], subdiv[i+1][j+1], subdiv[i][j]); glNormal3fv (norm); glTexCoord2f_M0(s2, t2); glTexCoord2f_M1(s2, t2); glVertex3fv(subdiv[i+1][j+1]); glTexCoord2f_M0(s1, t2); glTexCoord2f_M1(s1, t2); glVertex3fv(subdiv[i ][j+1]); } glEnd(); } // Cleanup... for (i = 0; i < vDetail+1; i++) { for (j = 0; j < uDetail+1; j++) delete [] subdiv[i][j]; delete [] subdiv[i]; } delete [] subdiv; }
//-------------------------------------------------------------------- void RglSphereN (float radius, float zmin, float zmax, float thetamax, int detail, MVertex &nscale) { int ixy; int iz; int zDensity; int xyDensity; float x,y,z; float xySize; float rad; float zrad; float zradStep; float radStep; float zminRad; float zmaxRad; //-- do some quick error checking if (!radius || !thetamax || zmin == zmax ) return; if (thetamax > 360.0f) thetamax = 360.0f; if (thetamax < -360.0f) thetamax = -360.0f; if (zmin < -radius) zmin = -radius; if (zmin > radius) zmin = radius; if (zmax < -radius) zmax = -radius; if (zmax > radius) zmax = radius; //-- set number of y polygons to half that of detail, & account for partial spheres zDensity = abs((int)( ((zmax-zmin)/radius)*(float)detail )/3); if (zDensity < 2) zDensity = 2; xyDensity = abs((int)( (D2RAD(thetamax)/(2.0*M_PI))*(float)detail )); if (xyDensity < 4) xyDensity = 4; //-- make space for vertices RglPoint **verts = new RglPoint*[zDensity+1]; RglPoint **norms = new RglPoint*[zDensity+1]; for (iz = 0; iz < (zDensity+1); iz++) { norms[iz] = new RglPoint[xyDensity+1]; verts[iz] = new RglPoint[xyDensity+1]; } zmaxRad = -acos(zmax/radius); zminRad = -acos(zmin/radius); zradStep = (zmaxRad-zminRad)/(float)(zDensity); radStep = D2RAD(thetamax)/(float)xyDensity; zrad = zmaxRad; for (iz = 0; iz < zDensity+1; iz++) { z = cos(zrad) * radius; rad = -M_PI/2.0; xySize = sin(zrad) * radius; for(ixy = 0; ixy < (xyDensity+1); ixy++) { x = sin (rad)*xySize; y = cos (rad)*xySize; verts[iz][ixy][0] = norms[iz][ixy][0] = x; verts[iz][ixy][1] = norms[iz][ixy][1] = y; verts[iz][ixy][2] = norms[iz][ixy][2] = z; normalizeVec(norms[iz][ixy]); rad += radStep; } zrad -= zradStep; } MVertex N1, N2, T; float s1, t1, t2, zd, xyd; zd = zDensity-1.0; xyd = xyDensity-1.0; for (iz = 0; iz < zDensity; iz++) { t1 = 1.0 - (zd-iz)/zd; t2 = 1.0 - (zd-iz-1.0)/zd; glBegin(GL_QUAD_STRIP); if(zmin < zmax) //-- if we want to flip the normals, swap zmin and zmax for(ixy = 0; ixy <= xyDensity; ixy++) { s1 = ixy/xyd; T = norms[iz+1][ixy]; N1 = nscale.scale(T); T = norms[iz][ixy]; N2 = nscale.scale(T); glTexCoord2f_M0(s1, t2); glTexCoord2f_M1(s1, t2); glNormal3fv( N1.xyz() ); glVertex3fv(verts[iz+1][ixy]); glTexCoord2f_M0(s1, t1); glTexCoord2f_M1(s1, t1); glNormal3fv( N2.xyz() ); glVertex3fv(verts[iz][ixy]); } else for(ixy = 0; ixy <= xyDensity; ixy++) { s1 = ixy/xyd; glTexCoord2f_M0(s1, t2); glTexCoord2f_M1(s1, t2); glNormal3f( -norms[iz+1][ixy][0], -norms[iz+1][ixy][1], -norms[iz+1][ixy][2]); glVertex3fv(verts[iz+1][ixy]); glTexCoord2f_M0(s1, t1); glTexCoord2f_M1(s1, t1); glNormal3f( -norms[iz][ixy][0], -norms[iz][ixy][1], -norms[iz][ixy][2]); glVertex3fv(verts[iz][ixy]); } glEnd(); } //-- cleanup for (iz = 0; iz < (zDensity+1); iz++) { delete []verts[iz]; delete []norms[iz]; } delete []verts; delete []norms; }
//-------------------------------------------------------------------- void RglDisk (float height, float radius, float thetamax, int detail, bool dcomp) { int zDensity; int xyDensity; int ixy; int iz; float x,y; float rad; float radStep; float norm[3]; //-- do some kludgy error checking if ( radius == 0.0f || thetamax == 0.0f ) return; if (thetamax > 360.0f) thetamax = 360.0f; if (thetamax < -360.0f) thetamax = -360.0f; //-- calculate tesselation xyDensity = abs((int)( (D2RAD(thetamax)/(2.0*M_PI))*(float)detail )); if(dcomp) zDensity = abs((int)((float)detail/4.0f)); else zDensity = 2; if (xyDensity < 4) xyDensity = 4; else if (xyDensity > 100) xyDensity = 100; if (zDensity < 2) zDensity = 2; else if(zDensity > 100) zDensity = 100; //-- make space for vertices RglPoint **verts = new RglPoint*[zDensity+1]; RglPoint **norms = new RglPoint*[zDensity+1]; for (iz = 0; iz < (zDensity+1); iz++) { norms[iz] = new RglPoint[xyDensity+1]; verts[iz] = new RglPoint[xyDensity+1]; for(ixy = 0; ixy < xyDensity+1; ixy++) { norms[iz][ixy][0] = 0.0f; norms[iz][ixy][1] = 0.0f; norms[iz][ixy][2] = 0.0f; } } //-- Calculate tip and base radStep = (D2RAD(thetamax))/( (float)xyDensity ); rad = M_PI/2.0; for (ixy = 0; ixy < xyDensity+1; ixy++) { //-- verts for tip verts[0][ixy][0] = verts[0][ixy][1] = 0.0f; verts[0][ixy][2] = height; //-- verts for base x = sin (rad)*radius; y = cos (rad)*radius; verts[zDensity-1][ixy][0] = x; verts[zDensity-1][ixy][1] = y; verts[zDensity-1][ixy][2] = height; if (ixy > 0) { if(thetamax < 0.0f) calcNormal (norm, verts[0][ixy-1], verts[zDensity-1][ixy-1], verts[zDensity-1][ixy]); else calcNormal (norm, verts[0][ixy-1], verts[zDensity-1][ixy], verts[zDensity-1][ixy-1]); norms[0][ixy][0] += norm[0]; norms[0][ixy][1] += norm[1]; norms[0][ixy][2] += norm[2]; norms[0][ixy-1][0] += norm[0]; norms[0][ixy-1][1] += norm[1]; norms[0][ixy-1][2] += norm[2]; } rad += radStep; } norms[0][0][0] += norms[0][xyDensity][0]; norms[0][0][1] += norms[0][xyDensity][1]; norms[0][0][2] += norms[0][xyDensity][2]; norms[0][xyDensity][0] += norms[0][0][0]; norms[0][xyDensity][1] += norms[0][0][1]; norms[0][xyDensity][2] += norms[0][0][2]; for(ixy = 0; ixy < xyDensity+1; ixy++) { normalizeVec(norms[0][ixy]); norms[zDensity-1][ixy][0] = norms[0][ixy][0] ; norms[zDensity-1][ixy][1] = norms[0][ixy][1] ; norms[zDensity-1][ixy][2] = norms[0][ixy][2] ; } //-- Interpolate tesselation float zDf = (float)zDensity-1; float izf; for(iz = 1; iz < zDensity-1; iz++) { izf = (float)iz; for (ixy = 0; ixy < xyDensity+1; ixy++) { verts[iz][ixy][0] = verts[0][ixy][0]*((zDf-izf)/zDf) + verts[zDensity-1][ixy][0]*(izf/zDf); verts[iz][ixy][1] = verts[0][ixy][1]*((zDf-izf)/zDf) + verts[zDensity-1][ixy][1]*(izf/zDf); verts[iz][ixy][2] = verts[0][ixy][2]*((zDf-izf)/zDf) + verts[zDensity-1][ixy][2]*(izf/zDf); norms[iz][ixy][0] = norms[0][ixy][0]; norms[iz][ixy][1] = norms[0][ixy][1]; norms[iz][ixy][2] = norms[0][ixy][2]; } } //-- Draw tip float s1, t1, t2, zd, xyd; zd = zDensity-1.0; xyd = xyDensity-1.0; s1 = 0.0; t1 = 1.0; glBegin(GL_TRIANGLE_FAN); glTexCoord2f_M0(s1, t1); glTexCoord2f_M1(s1, t1); glNormal3fv(norms[0][0]); glVertex3fv(verts[0][0]); for (ixy = xyDensity; ixy >= 0; ixy--) { s1 = ixy/xyd; glTexCoord2f_M0(s1, t1); glTexCoord2f_M1(s1, t1); glVertex3fv(verts[1][ixy]); } glEnd(); //-- Draw the rest for(iz = 1; iz < zDensity-1; iz++) { t1 = (zd-iz)/zd; t2 = (zd-iz-1.0)/zd; glBegin(GL_QUAD_STRIP); izf = (float)iz; for (ixy = 0; ixy < xyDensity+1; ixy++) { s1 = ixy/xyd; glTexCoord2f_M0(s1, t2); glTexCoord2f_M1(s1, t2); glVertex3fv(verts[iz+1][ixy]); glTexCoord2f_M0(s1, t1); glTexCoord2f_M1(s1, t1); glVertex3fv(verts[iz][ixy]); } glEnd(); } //-- cleanup for (iz = 0; iz < (zDensity+1); iz++) { delete []verts[iz]; delete []norms[iz]; } delete []verts; delete []norms; }
//-------------------------------------------------------------------- void RglCylinder (float radius, float zmin, float zmax, float thetamax, int detail, bool dcomp) { int zDensity; int xyDensity; int ixy; int iz; float x; float y; float rad; float radStep; //-- do some quick error checking if (!radius || !thetamax) return; if (thetamax > 360.0f) thetamax = 360.0f; if (thetamax < -360.0f) thetamax = -360.0f; //-- calculate tesselation xyDensity = abs((int)( (D2RAD(thetamax)/(2.0*M_PI))*(float)detail )); if(dcomp) zDensity = abs((int)(((zmax-zmin)/radius)*((float)detail/10.0f))); else zDensity = 3; if (xyDensity < 4) xyDensity = 4; else if (xyDensity > 100) xyDensity = 100; if (zDensity < 2) zDensity = 2; else if(zDensity > 100) zDensity = 100; //-- make space for vertices RglPoint **verts = new RglPoint*[zDensity+1]; RglPoint **norms = new RglPoint*[zDensity+1]; for (iz = 0; iz < (zDensity+1); iz++) { norms[iz] = new RglPoint[xyDensity+1]; verts[iz] = new RglPoint[xyDensity+1]; for(ixy = 0; ixy < xyDensity+1; ixy++) { norms[iz][ixy][0] = 0.0f; norms[iz][ixy][1] = 0.0f; norms[iz][ixy][2] = 0.0f; } } //-- calculate min and max radStep = (D2RAD(thetamax))/( (float)xyDensity ); rad = M_PI/2.0; for (ixy = 0; ixy < xyDensity+1; ixy++) { x = sin (rad)*radius; y = cos (rad)*radius; verts[0][ixy][0] = verts[zDensity-1][ixy][0] = x; verts[0][ixy][1] = verts[zDensity-1][ixy][1] = y; verts[0][ixy][2] = zmin; verts[zDensity-1][ixy][2] = zmax; norms[0][ixy][0] = norms[zDensity-1][ixy][0] = x; norms[0][ixy][1] = norms[zDensity-1][ixy][1] = y; norms[0][ixy][2] = norms[zDensity-1][ixy][2] = 0.0; normalizeVec(norms[0][ixy]); normalizeVec(norms[zDensity-1][ixy]); rad += radStep; } //-- interpolate tesselation float izf; float zDf = (float)zDensity-1; for(iz = 1; iz < zDensity-1; iz++) { izf = (float)iz; for (ixy = 0; ixy < xyDensity+1; ixy++) { verts[iz][ixy][0] = verts[0][ixy][0]*((zDf-izf)/zDf) + verts[zDensity-1][ixy][0]*(izf/zDf); verts[iz][ixy][1] = verts[0][ixy][1]*((zDf-izf)/zDf) + verts[zDensity-1][ixy][1]*(izf/zDf); verts[iz][ixy][2] = verts[0][ixy][2]*((zDf-izf)/zDf) + verts[zDensity-1][ixy][2]*(izf/zDf); norms[iz][ixy][0] = norms[0][ixy][0]; norms[iz][ixy][1] = norms[0][ixy][1]; norms[iz][ixy][2] = norms[0][ixy][2]; } } //-- Draw cylinder float s1, t1, t2, zd, xyd; zd = zDensity-1.0; xyd = xyDensity-1.0; for(iz = 0; iz < zDensity-1; iz++) { t1 = (zd-iz)/zd; t2 = (zd-iz-1.0)/zd; izf = (float)iz; glBegin(GL_TRIANGLE_STRIP); for (ixy = 0; ixy < xyDensity+1; ixy++) { s1 = ixy/xyd; glTexCoord2f_M0(s1, t1); glTexCoord2f_M1(s1, t1); glNormal3fv(norms[iz][ixy]); glVertex3fv(verts[iz][ixy]); glTexCoord2f_M0(s1, t2); glTexCoord2f_M1(s1, t2); glNormal3fv(norms[iz+1][ixy]); glVertex3fv(verts[iz+1][ixy]); } glEnd(); } //-- Cleanup for (iz = 0; iz < (zDensity+1); iz++) { delete []verts[iz]; delete []norms[iz]; } delete []verts; delete []norms; }
//-------------------------------------------------------------------- void GroundMetalSegment::drawMultiTex(float rep, float S, float tilt, bool blipMirrorT, float *c0_clr, float *c1_clr, float *r0_clr, float *r1_clr, float *r2_clr) { float repA = 0.0; float repB = rep; glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture(GL_TEXTURE_2D, parent->tex[Ground::Blip]); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D, parent->tex[Ground::Base]); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glEnable(GL_TEXTURE_2D); // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBegin(GL_TRIANGLES); //-- use triangles to prevent color popping on Utah glTexCoord2f_M0( rep, repA+S+tilt); glColor4fv(c1_clr); glTexCoord2f_M1( 1.0, 0.0); glVertex3f( pos[0], pos[1], pos[2]); glTexCoord2f_M0( 0.0, repA+S); glColor4fv(r2_clr); glTexCoord2f_M1( 0.0, 0.0); glVertex3f(-size[0]+pos[0], pos[1], pos[2]); glTexCoord2f_M0( 0.0, repB+S); glColor4fv(r0_clr); glTexCoord2f_M1( 0.0, 1.0); glVertex3f(-size[0]+pos[0], -size[1]+pos[1], pos[2]); glTexCoord2f_M0( rep, repA+S+tilt); glColor4fv(c1_clr); glTexCoord2f_M1( 1.0, 0.0); glVertex3f( pos[0], pos[1], pos[2]); glTexCoord2f_M0( 0.0, repB+S); glColor4fv(r0_clr); glTexCoord2f_M1( 0.0, 1.0); glVertex3f(-size[0]+pos[0], -size[1]+pos[1], pos[2]); glTexCoord2f_M0( rep, repB+S+tilt); glColor4fv(c0_clr); glTexCoord2f_M1( 1.0, 1.0); glVertex3f( pos[0], -size[1]+pos[1], pos[2]); glTexCoord2f_M0( 0.0, repA+S); glColor4fv(r0_clr); glTexCoord2f_M1( 0.0, 0.0); glVertex3f( size[0]+pos[0], pos[1], pos[2]); glTexCoord2f_M0( rep, repA+S+tilt); glColor4fv(c1_clr); glTexCoord2f_M1( 1.0, 0.0); glVertex3f( pos[0], pos[1], pos[2]); glTexCoord2f_M0( rep, repB+S+tilt); glColor4fv(c0_clr); glTexCoord2f_M1( 1.0, 1.0); glVertex3f( pos[0], -size[1]+pos[1], pos[2]); glTexCoord2f_M0( 0.0, repA+S); glColor4fv(r0_clr); glTexCoord2f_M1( 0.0, 0.0); glVertex3f( size[0]+pos[0], pos[1], pos[2]); glTexCoord2f_M0( rep, repB+S+tilt); glColor4fv(c0_clr); glTexCoord2f_M1( 1.0, 1.0); glVertex3f( pos[0], -size[1]+pos[1], pos[2]); glTexCoord2f_M0( 0.0, repB+S); glColor4fv(r1_clr); glTexCoord2f_M1( 0.0, 1.0); glVertex3f( size[0]+pos[0], -size[1]+pos[1], pos[2]); if(blipMirrorT) { repA = rep; repB = 0.0; } glTexCoord2f_M0( 0.0, repA+S); glColor4fv(r1_clr); glTexCoord2f_M1( 0.0, 1.0); glVertex3f( size[0]+pos[0], size[1]+pos[1], pos[2]); glTexCoord2f_M0( rep, repA+S+tilt); glColor4fv(c0_clr); glTexCoord2f_M1( 1.0, 1.0); glVertex3f( pos[0], size[1]+pos[1], pos[2]); glTexCoord2f_M0( rep, repB+S+tilt); glColor4fv(c1_clr); glTexCoord2f_M1( 1.0, 0.0); glVertex3f( pos[0], pos[1], pos[2]); glTexCoord2f_M0( 0.0, repA+S); glColor4fv(r1_clr); glTexCoord2f_M1( 0.0, 1.0); glVertex3f( size[0]+pos[0], size[1]+pos[1], pos[2]); glTexCoord2f_M0( rep, repB+S+tilt); glColor4fv(c1_clr); glTexCoord2f_M1( 1.0, 0.0); glVertex3f( pos[0], pos[1], pos[2]); glTexCoord2f_M0( 0.0, repB+S); glColor4fv(r0_clr); glTexCoord2f_M1( 0.0, 0.0); glVertex3f( size[0]+pos[0], pos[1], pos[2]); //-- glTexCoord2f_M0( rep, repA+S+tilt); glColor4fv(c0_clr); glTexCoord2f_M1( 1.0, 1.0); glVertex3f( pos[0], size[1]+pos[1], pos[2]); glTexCoord2f_M0( 0.0, repA+S); glColor4fv(r0_clr); glTexCoord2f_M1( 0.0, 1.0); glVertex3f(-size[0]+pos[0], size[1]+pos[1], pos[2]); glTexCoord2f_M0( 0.0, repB+S); glColor4fv(r2_clr); glTexCoord2f_M1( 0.0, 0.0); glVertex3f(-size[0]+pos[0], pos[1], pos[2]); glTexCoord2f_M0( rep, repA+S+tilt); glColor4fv(c0_clr); glTexCoord2f_M1( 1.0, 1.0); glVertex3f( pos[0], size[1]+pos[1], pos[2]); glTexCoord2f_M0( 0.0, repB+S); glColor4fv(r2_clr); glTexCoord2f_M1( 0.0, 0.0); glVertex3f(-size[0]+pos[0], pos[1], pos[2]); glTexCoord2f_M0( rep, repB+S+tilt); glColor4fv(c1_clr); glTexCoord2f_M1( 1.0, 0.0); glVertex3f( pos[0], pos[1], pos[2]); glEnd(); glDisable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE0_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); }