void primSolidTexture3Fade(vector *p1, real32 size, color c, trhandle tex, real32 fade) { real32 halfsize = size / 2; real32 biasRed, biasGreen, biasBlue; texreg* reg; rndTextureEnable(TRUE); trMakeCurrent(tex); reg = trStructureGet(tex); if (bitTest(reg->flags, TRF_Alpha)) { glEnable(GL_BLEND); glDisable(GL_ALPHA_TEST); rndAdditiveBlends(TRUE); } biasRed = colReal32(colRed(c)); biasGreen = colReal32(colGreen(c)); biasBlue = colReal32(colBlue(c)); if (RGL) { glPixelTransferf(GL_RED_BIAS, biasRed); glPixelTransferf(GL_GREEN_BIAS, biasGreen); glPixelTransferf(GL_BLUE_BIAS, biasBlue); } glColor4f(biasRed, biasGreen, biasBlue, fade); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(p1->x-halfsize, p1->y-halfsize, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(p1->x+halfsize, p1->y-halfsize, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(p1->x+halfsize, p1->y+halfsize, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(p1->x-halfsize, p1->y+halfsize, 0.0f); glEnd(); if (RGL) { glPixelTransferf(GL_RED_BIAS, 0.0f); glPixelTransferf(GL_GREEN_BIAS, 0.0f); glPixelTransferf(GL_BLUE_BIAS, 0.0f); } glDisable(GL_BLEND); rndAdditiveBlends(FALSE); }
static void primSolidTexture3_multi(vector* p1, real32 size, color c, trhandle tex) { real32 halfsize; texreg* reg; extern udword gDevcaps; halfsize = 0.5f * size; rndTextureEnable(TRUE); trMakeCurrent(tex); reg = trStructureGet(tex); if (bitTest(reg->flags, TRF_Alpha)) { glEnable(GL_BLEND); glDisable(GL_ALPHA_TEST); rndAdditiveBlends(TRUE); } glBegin(GL_QUADS); glColor3ub(colRed(c), colGreen(c), colBlue(c)); glTexCoord2f(0.0f, 0.0f); glVertex3f(p1->x-halfsize, p1->y-halfsize, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(p1->x+halfsize, p1->y-halfsize, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(p1->x+halfsize, p1->y+halfsize, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(p1->x-halfsize, p1->y+halfsize, 0.0f); if (!bitTest(gDevcaps, DEVSTAT_NO_GETTEXIMAGE)) { glColor3ub(172, 172, 172); glTexCoord2f(0.0f, 0.0f); glVertex3f(p1->x-halfsize, p1->y-halfsize, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(p1->x+halfsize, p1->y-halfsize, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(p1->x+halfsize, p1->y+halfsize, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(p1->x-halfsize, p1->y+halfsize, 0.0f); } glEnd(); glDisable(GL_BLEND); rndAdditiveBlends(FALSE); }
/*----------------------------------------------------------------------------- Name : primBeginPointSize3Fade Description : begin drawing multiple 3D points Inputs : size - size of point (ie. 1.0f, 2.0f, ...) Outputs : Return : ----------------------------------------------------------------------------*/ void primBeginPointSize3Fade(real32 size) { if (glCapFeatureExists(GL_POINT_SIZE)) { glPointSize(size); } gFastBlends = glCapFastFeature(GL_BLEND); if (gFastBlends) { gWasBlending = glIsEnabled(GL_BLEND); if (!gWasBlending) { glEnable(GL_BLEND); } rndAdditiveBlends(FALSE); } glBegin(GL_POINTS); }
//don't mind if this is inefficient as it only //gets called once per image anyway void hrDrawFile(char* filename, sdword x, sdword y) { udword handle; rectangle rect; lifheader* lif = trLIFFileLoad(filename, Pyrophoric); rndTextureEnable(TRUE); rndAdditiveBlends(FALSE); glEnable(GL_BLEND); glGenTextures(1, &handle); trClearCurrent(); glBindTexture(GL_TEXTURE_2D, handle); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lif->width, lif->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, lif->data); // FIXME: there's no LiF scaling here, just translation of the image x = hrScaleMissionLoadingScreens ? feResRepositionScaledX(x) : feResRepositionCentredX(x); y = hrScaleMissionLoadingScreens ? feResRepositionScaledY(y) : feResRepositionCentredY(y); x -= lif->width >> 1; y -= lif->height >> 1; rect.x0 = x; rect.y0 = y; rect.x1 = x + lif->width; rect.y1 = y + lif->height; hrRectSolidTextured2(&rect); glDeleteTextures(1, &handle); memFree(lif); glDisable(GL_BLEND); }
/*----------------------------------------------------------------------------- Name : primLine3 Description : Draw a line in 3D using having a thickness of 1 pixel Inputs : p1, p2 - end points of line segment to draw c - color to draw it in. Outputs : Return : void ----------------------------------------------------------------------------*/ void primLine3(vector *p1, vector *p2, color c) { bool blendon; if (glCapFeatureExists(GL_LINE_SMOOTH)) { blendon = glIsEnabled(GL_BLEND); if (!blendon) glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); rndAdditiveBlends(FALSE); } glColor3ub(colRed(c), colGreen(c), colBlue(c)); glBegin(GL_LINES); glVertex3fv((const GLfloat *)p1); glVertex3fv((const GLfloat *)p2); glEnd(); if (glCapFeatureExists(GL_LINE_SMOOTH)) { if (!blendon) glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); } }
void primCircleSolid3Fade(vector *centre, real32 radius, sdword nSlices, color c, real32 fade) { sdword index; GLfloat v[3]; double theta; GLboolean blend = glIsEnabled(GL_BLEND); if (!blend) { glEnable(GL_BLEND); rndAdditiveBlends(FALSE); } glColor4ub(colRed(c), colGreen(c), colBlue(c), (ubyte)(fade * 255.0f)); v[0] = centre->x; v[1] = centre->y; v[2] = centre->z; glBegin(GL_TRIANGLE_FAN); glVertex3fv(v); //centre vertex for (index = 0, theta = 0.0; index < nSlices; index++) { v[0] = centre->x + (real32)(sin(theta)) * radius; v[1] = centre->y + (real32)(cos(theta)) * radius; theta += 2.0 * PI / (double)nSlices; glVertex3fv(v); //vertex on outer rim } v[0] = centre->x; v[1] = centre->y + radius; glVertex3fv(v); //final vertex on outer rim glEnd(); if (!blend) { glDisable(GL_BLEND); } }
/*----------------------------------------------------------------------------- Name : btgRender Description : renders the background. assumes modelview already set Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void btgRender() { udword nStar; sdword lightOn, index; GLboolean texOn, blendOn, depthOn; udword* dlast; udword* dnext; static sdword lastFade = 255; #if MR_KEYBOARD_CHEATS extern bool gMosaic; #endif if (btgHead == NULL) { #ifdef _WIN32 btgLoad("BTG\\default.btg"); #else btgLoad("BTG/default.btg"); #endif } #if MR_KEYBOARD_CHEATS glShadeModel(gMosaic ? GL_FLAT : GL_SMOOTH); #else glShadeModel(GL_SMOOTH); #endif glGetFloatv(GL_COLOR_CLEAR_VALUE, _bgColor); for (index = 0; index < 4; index++) { _bgByte[index] = (GLubyte)(_bgColor[index] * 255.0f); } dnext = (udword*)_bgByte; dlast = (udword*)lastbg; depthOn = glIsEnabled(GL_DEPTH_TEST); lightOn = rndLightingEnable(FALSE); texOn = glIsEnabled(GL_TEXTURE_2D); blendOn = glIsEnabled(GL_BLEND); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); rndAdditiveBlends(FALSE); if (useVBO) glBindBuffer(GL_ARRAY_BUFFER, vboTransVerts); //polys if (btgFade != lastFade || *dnext != *dlast) { if (btgFade < 0) { btgFade = 255; } #ifndef _WIN32_FIXME btgColorVertices(); #endif if (useVBO) glBufferData(GL_ARRAY_BUFFER, btgHead->numVerts * sizeof(btgTransVertex), btgTransVerts, GL_STATIC_DRAW); *dlast = *dnext; lastFade = btgFade; } //use DrawElements to render the bg polys glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); if (useVBO) { glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(btgTransVertex), 0); glVertexPointer(3, GL_FLOAT, sizeof(btgTransVertex), (GLvoid*)4); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndices); glDrawElements(GL_TRIANGLES, 3 * btgHead->numPolys, GL_UNSIGNED_SHORT, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } else { glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(btgTransVertex), (GLubyte*)btgTransVerts); glVertexPointer(3, GL_FLOAT, sizeof(btgTransVertex), ((GLubyte*)btgTransVerts) + 4); glDrawElements(GL_TRIANGLES, 3 * btgHead->numPolys, GL_UNSIGNED_SHORT, btgIndices); } glDisableClientState(GL_COLOR_ARRAY); //stars rndPerspectiveCorrection(FALSE); rndAdditiveBlends(TRUE); trClearCurrent(); glEnable(GL_TEXTURE_2D); rndTextureEnvironment(RTE_Modulate); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (useVBO) { glBindBuffer(GL_ARRAY_BUFFER, vboTransStars); glVertexPointer(3, GL_FLOAT, sizeof(GLfloat) * 5, 0); glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat) * 5, (GLubyte*)sizeof(vector)); glBindBuffer(GL_ARRAY_BUFFER, 0); } else { glVertexPointer(3, GL_FLOAT, sizeof(GLfloat) * 5, (GLubyte*)btgTransStars); glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat) * 5, ((GLubyte*)btgTransStars) + sizeof(vector)); } for (nStar = 0; nStar < btgHead->numStars; nStar++) { if (btgStars[nStar].glhandle) { glColor4ub((GLubyte)btgStars[nStar].red, (GLubyte)btgStars[nStar].green, (GLubyte)btgStars[nStar].blue, (GLubyte)btgStars[nStar].alpha); glBindTexture(GL_TEXTURE_2D, btgStars[nStar].glhandle); glDrawArrays(GL_TRIANGLE_STRIP, nStar * 4, 4); } } glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisable(GL_BLEND); rndAdditiveBlends(FALSE); rndLightingEnable(lightOn); if (texOn) glEnable(GL_TEXTURE_2D); if (blendOn) { glEnable(GL_BLEND); } else { glDisable(GL_BLEND); } glEnable(GL_CULL_FACE); if (depthOn) { glEnable(GL_DEPTH_TEST); } else { glDisable(GL_DEPTH_TEST); } }
/*----------------------------------------------------------------------------- Name : primSolidTexture3 Description : Draw a 3D point with size Inputs : p1 - location of point size - physical size of point c - color of point Outputs : Return : void ----------------------------------------------------------------------------*/ void primSolidTexture3(vector *p1, real32 size, color c, trhandle tex) { real32 halfsize; real32 biasRed, biasGreen, biasBlue; texreg* reg; if (!glCapFeatureExists(RGL_COLOROP_ADD)) { //multi-pass render to approximate a missing feature primSolidTexture3_multi(p1, size, c, tex); return; } halfsize = 0.5f * size; rndTextureEnable(TRUE); // glDepthMask(GL_FALSE); trMakeCurrent(tex); reg = trStructureGet(tex); if (bitTest(reg->flags, TRF_Alpha)) { glEnable(GL_BLEND); glDisable(GL_ALPHA_TEST); rndAdditiveBlends(TRUE); } biasRed = colReal32(colRed(c)); biasGreen = colReal32(colGreen(c)); biasBlue = colReal32(colBlue(c)); if (RGL) { glPixelTransferf(GL_RED_BIAS, biasRed); glPixelTransferf(GL_GREEN_BIAS, biasGreen); glPixelTransferf(GL_BLUE_BIAS, biasBlue); } glColor3f(biasRed, biasGreen, biasBlue); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(p1->x-halfsize, p1->y-halfsize, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(p1->x+halfsize, p1->y-halfsize, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(p1->x+halfsize, p1->y+halfsize, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(p1->x-halfsize, p1->y+halfsize, 0.0f); glEnd(); if (RGL) { glPixelTransferf(GL_RED_BIAS, 0.0f); glPixelTransferf(GL_GREEN_BIAS, 0.0f); glPixelTransferf(GL_BLUE_BIAS, 0.0f); } glDisable(GL_BLEND); // glDepthMask(GL_TRUE); rndAdditiveBlends(FALSE); }
/*----------------------------------------------------------------------------- Name : primCircleOutline3 Description : Draw a solid circle on the z = centre->z plane Inputs : centre - centre point (in 3D coords) of the circle radius - radius of circle (actually, distance from centre to vertices) nSlices - number of polygons to draw nSpokes - number of 'spokes' which actually get drawn. nSlices should integer divide by this with no remainder. color - color of circle axis - axis on which to draw the circle Outputs : .. Return : void ----------------------------------------------------------------------------*/ void primCircleOutline3(vector *centre, real32 radius, sdword nSlices, sdword nSpokes, color color, uword axis) { Node *node; vertice_array *vertices; register vector *vec_ptr; sdword index; GLfloat c[3], rim[3]; // find the vertice list containing the unit circle that has the same // number of slices and is aligned along the same axis as the circle to be drawn node = CircleList.head; while (node != NULL) { vertices = (vertice_array *)listGetStructOfNode(node); if ((vertices->num_vertices == (nSlices + 1)) && (vertices->axis == axis)) { //found the correct unit circle break; } node = node->next; } //if the unit circle isn't found, generate a new one if (node == NULL) { vertices = primCreateNewCircleVerticeArray(nSlices, axis); } if (nSpokes != 0) { nSpokes = nSlices / nSpokes; } glColor3ub(colRed(color), colGreen(color), colBlue(color)); c[0] = centre->x; //compute centre point c[1] = centre->y; c[2] = centre->z; glShadeModel(GL_SMOOTH); if (glCapFeatureExists(GL_LINE_SMOOTH)) { glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); rndAdditiveBlends(FALSE); } vec_ptr = &vertices->vertice[0]; switch (axis) { case X_AXIS: rim[0] = centre->x + vec_ptr->x * radius; //draw the circle glBegin(GL_LINE_LOOP); for (index = 0; index <= nSlices; index++, vec_ptr++) { rim[1] = centre->y + vec_ptr->y * radius; rim[2] = centre->z + vec_ptr->z * radius; glVertex3fv(rim); //vertex on rim } glEnd(); //now draw the spokes if (nSpokes) { vec_ptr = &vertices->vertice[0]; glBegin(GL_LINES); for (index = 0; index <= nSlices; index += nSpokes, vec_ptr += nSpokes) { rim[1] = centre->y + vec_ptr->y * radius; rim[2] = centre->z + vec_ptr->z * radius; glVertex3fv(c); glVertex3fv(rim); } glEnd(); } break; case Y_AXIS: rim[1] = centre->y + vec_ptr->y * radius; //draw the circle glBegin(GL_LINE_LOOP); for (index = 0; index <= nSlices; index++, vec_ptr++) { rim[0] = centre->x + vec_ptr->x * radius; rim[2] = centre->z + vec_ptr->z * radius; glVertex3fv(rim); //vertex on rim } glEnd(); //draw the spokes if (nSpokes) { vec_ptr = &vertices->vertice[0]; glBegin(GL_LINES); for (index = 0; index <= nSlices; index += nSpokes, vec_ptr += nSpokes) { rim[0] = centre->x + vec_ptr->x * radius; rim[2] = centre->z + vec_ptr->z * radius; glVertex3fv(c); glVertex3fv(rim); } glEnd(); } break; case Z_AXIS: rim[2] = centre->z + vec_ptr->z * radius; //draw the circle glBegin(GL_LINE_LOOP); for (index = 0; index <= nSlices; index++, vec_ptr++) { rim[0] = centre->x + vec_ptr->x * radius; rim[1] = centre->y + vec_ptr->y * radius; glVertex3fv(rim); //vertex on rim } glEnd(); //draw the spokes if (nSpokes) { vec_ptr = &vertices->vertice[0]; glBegin(GL_LINES); for (index = 0; index <= nSlices; index += nSpokes, vec_ptr += nSpokes) { rim[0] = centre->x + vec_ptr->x * radius; rim[1] = centre->y + vec_ptr->y * radius; glVertex3fv(c); glVertex3fv(rim); } glEnd(); } break; default: break; } if (glCapFeatureExists(GL_LINE_SMOOTH)) { glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); } }
/*----------------------------------------------------------------------------- Name : RenderNAVLights Description : TODO: render sorted by projected depth value so alpha sorts correctly Inputs : ship - the ship whose navlights we are to render Outputs : Return : ----------------------------------------------------------------------------*/ void RenderNAVLights(Ship *ship) { sdword i; NAVLight *navLight; NAVLightInfo *navLightInfo; ShipStaticInfo *shipStaticInfo; NAVLightStatic *navLightStatic; vector origin = {0.0f, 0.0f, 0.0f}; NAVLightStaticInfo *navLightStaticInfo; real32 fade; bool lightOn; extern bool bFade; extern real32 meshFadeAlpha; fade = bFade ? meshFadeAlpha : 1.0f; shipStaticInfo = (ShipStaticInfo *)ship->staticinfo; navLightInfo = ship->navLightInfo; if(shipStaticInfo->navlightStaticInfo && navLightInfo != NULL) { glDepthMask(GL_FALSE); rndAdditiveBlends(TRUE); lightOn = rndLightingEnable(FALSE); navLightStaticInfo = shipStaticInfo->navlightStaticInfo; navLightStatic = navLightStaticInfo->navlightstatics; navLight = navLightInfo->navLights; for( i=0 ; i<navLightStaticInfo->numNAVLights ; i++, navLight ++, navLightStatic ++) { // Account for the startdelay. if(navLight->lastTimeFlashed == navLightStatic->startdelay) { navLight->lastTimeFlashed = universe.totaltimeelapsed + navLightStatic->startdelay; } if(universe.totaltimeelapsed > navLight->lastTimeFlashed) { if(navLight->lightstate == 1) { navLight->lastTimeFlashed = universe.totaltimeelapsed + navLightStatic->flashrateoff; } else { navLight->lastTimeFlashed = universe.totaltimeelapsed + navLightStatic->flashrateon; } navLight->lightstate = 1 - navLight->lightstate; } if(navLight->lightstate) { if (ship->currentLOD <= (sdword)navLightStatic->minLOD) { navLightBillboardEnable(ship, navLightStatic); if(navLightStatic->texturehandle == TR_InvalidHandle) { primCircleSolid3Fade(&origin, navLightStatic->size, 10, navLightStatic->color, fade); } else { primSolidTexture3Fade(&origin, navLightStatic->size, navLightStatic->color, navLightStatic->texturehandle, fade); } navLightBillboardDisable(); } else { color tempColor; tempColor = colRGB(colRed(navLightStatic->color) * 2 / 3, colGreen(navLightStatic->color) * 2 / 3, colBlue(navLightStatic->color) * 2 / 3); rndTextureEnable(FALSE); if (RGL) { if (glCapFastFeature(GL_BLEND)) { rndAdditiveBlends(TRUE); primPointSize3(&navLightStatic->position, 2.0f, tempColor); } else { primPointSize3(&navLightStatic->position, 1.0f, tempColor); } } else { rndAdditiveBlends(TRUE); glEnable(GL_POINT_SMOOTH); primPointSize3Fade(&navLightStatic->position, 2.0f, tempColor, fade); glDisable(GL_POINT_SMOOTH); } } } } rndLightingEnable(lightOn); rndAdditiveBlends(FALSE); glDepthMask(GL_TRUE); } }