/*************************************************************************** File: Renderer.cpp Created: 03/01/2001 Author: Maxim Garber Computer Science Department University of North Carolina - Chapel Hill garber@cs.unc.edu Description: ----------------------------------------------------------------------------. Copyright 2001 Maxim Garber UNC Motion Planning Research Group *****************************************************************************/ #include "Renderer.hpp" #include "Renderer_constants.hpp" #include Renderer:: Renderer() { _mode = TEXTURE_MODE_FLAT; SetDefaultLightingState(); SetDefaultMaterialState(); } void Renderer:: Initialize(const char* renderFile){ ifstream rsrc; rsrc.open( renderFile ); rsrc >> _numRenderStates; for(int i = 0; i < _numRenderStates; i++){ // initialize triangle bucket TriBucket TB; _triangles.push_back(TB); // initialize render state RenderState* state = new RenderState; _pRenderStates.push_back(state); // load render state texture char textureFile[FILE_NAME_LENGTH]; float textureScale; rsrc >> textureFile; rsrc >> textureScale; AddTexture(textureFile, textureScale, i); // set some default parameters SetParameter(GL_TEXTURE_WRAP_S, GL_REPEAT, i); SetParameter(GL_TEXTURE_WRAP_T, GL_REPEAT, i); SetParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST, i); SetParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST, i); } CompileRenderStates(); } void Renderer:: AddTexture(GLubyte* texture, GLuint Width, GLuint Height, GLuint Channels, float textureScale, int renderState) { _pRenderStates[renderState]->_texture = texture; _pRenderStates[renderState]->_texWidth = Width; _pRenderStates[renderState]->_texHeight = Height; _pRenderStates[renderState]->_texChannels = Channels; _pRenderStates[renderState]->_texScaleFactor = textureScale; } void Renderer:: AddTexture(const char* textureFile, float textureScale, int renderState) { _pRenderStates[renderState]->_texture = NULL; LoadTGA(textureFile, _pRenderStates[renderState]->_texture, _pRenderStates[renderState]->_texWidth, _pRenderStates[renderState]->_texHeight, _pRenderStates[renderState]->_texChannels); _pRenderStates[renderState]->_texScaleFactor = textureScale; } void Renderer:: SetParameter(GLenum paramName, GLuint paramValue, int renderState) { _pRenderStates[renderState]->_paramNames.push_back(paramName); _pRenderStates[renderState]->_paramValues.push_back(paramValue); } void Renderer:: CompileRenderStates() { // initialize GLstate glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_FLAT); glEnable (GL_DEPTH_TEST); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for(int i = 0; i < _numRenderStates; i++) { // generate name; static GLuint texName; glGenTextures(1, &texName); // bind the texture glBindTexture(GL_TEXTURE_2D, texName); _pRenderStates[i]->_texName = texName; // set texture state parameters for(int j = 0; j < _pRenderStates[i]->_paramNames.size(); j++) { glTexParameteri(GL_TEXTURE_2D, _pRenderStates[i]->_paramNames[j], _pRenderStates[i]->_paramValues[j]); } // load texture image glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _pRenderStates[i]->_texWidth, _pRenderStates[i]->_texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, _pRenderStates[i]->_texture); } //delete(texNames); } void Renderer:: SetRenderState(int renderState) { glBindTexture(GL_TEXTURE_2D, _pRenderStates[renderState]->_texName); } /*--------------------------------------------------------------------------- Lights and Camera ----------------------------------------------------------------------------*/ void Renderer::SetEnableState(int i, int value) { switch(i) { case LIGHT0: case LIGHT1: case LIGHT2: case LIGHT3: case LIGHT4: case LIGHT5: case LIGHT6: case LIGHT7: Lights[i].IsEnabled=value; break; case COLOR_MATERIAL: ColorMaterialEnabled=value; break; default: printf("Renderer error: Enable/Disable: unsupported state!\n"); break; }; } void Renderer:: SetCameraPosition(float cameraPosition[3]) { for(int i = 0; i < 3; i++) _cameraPosition[i] = cameraPosition[i]; } /*--------------------------------------------------------------------------- Rendering ----------------------------------------------------------------------------*/ void Renderer:: Begin() { for(int i = 0; i < _numRenderStates; i++) _triangles[i].clear(); } void Renderer:: RenderTriangle(Tri tri) { int renderState = _SelectRenderState(tri); _triangles[renderState].push_back(tri); } void Renderer:: End() { if(_mode == TEXTURE_MODE_STANDARD) { glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); for(int i = 0; i < _numRenderStates; i++) { SetRenderState(i); glBegin(GL_TRIANGLES); int k = _triangles[i].size(); for(int t = 0; t < _triangles[i].size(); t++) { float texCoords[2]; _CalcTextureCoords(_triangles[i][t].A, _pRenderStates[i], texCoords); glTexCoord2fv(texCoords); glVertex3fv(_triangles[i][t].A); _CalcTextureCoords(_triangles[i][t].B, _pRenderStates[i], texCoords); glTexCoord2fv(texCoords); glVertex3fv(_triangles[i][t].B); _CalcTextureCoords(_triangles[i][t].C, _pRenderStates[i], texCoords); glTexCoord2fv(texCoords); glVertex3fv(_triangles[i][t].C); } glEnd(); } glDisable(GL_TEXTURE_2D); } else if(_mode == TEXTURE_MODE_FLAT) { //glClear(GL_DEPTH_BUFFER_BIT); for(int i = 0; i < _numRenderStates; i++) { float textureCoordsX = _screenWidth / (_pRenderStates[i]->_texWidth * _pRenderStates[i]->_texScaleFactor); float textureCoordsY = _screenHeight / (_pRenderStates[i]->_texHeight * _pRenderStates[i]->_texScaleFactor); glEnable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glClear(GL_STENCIL_BUFFER_BIT); glStencilFunc (GL_ALWAYS, 0x1, 0x1); glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); glBegin(GL_TRIANGLES); int k = _triangles[i].size(); for(int t = 0; t < _triangles[i].size(); t++) { glColor3f(1,0,0); glVertex3fv(_triangles[i][t].A); glVertex3fv(_triangles[i][t].B); glVertex3fv(_triangles[i][t].C); } glEnd(); glDrawBuffer(GL_BACK); // texture state glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); SetRenderState(i); // stencil state glDisable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_EQUAL, 0x1, 0x1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 0.99); glTexCoord2f(textureCoordsX, 0.0); glVertex3f( 1.0, -1.0, 0.99); glTexCoord2f(textureCoordsX, textureCoordsY ); glVertex3f( 1.0, 1.0, 0.99); glTexCoord2f(0.0, textureCoordsY ); glVertex3f(-1.0, 1.0, 0.99); glEnd(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glDisable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); } } else if(_mode == COMPUTED_COLOR_MODE) { glEnable(GL_COLOR_MATERIAL); for(int i = 0; i < _numRenderStates; i++) { glBegin(GL_TRIANGLES); int k = _triangles[i].size(); for(int t = 0; t < _triangles[i].size(); t++) { float color[3]; if (ColorMaterialEnabled) // UPDATE CURRENTLY SPECIFIED COLOR MATERIAL { float C[] = {_triangles[i][t].Color[0] / 255.0, _triangles[i][t].Color[1] / 255.0, _triangles[i][t].Color[2] / 255.0, 1.0 }; Materialfv(ColorMaterialFace,ColorMaterialMode,C); } _CalcLighting(color, _triangles[i][t].A, _triangles[i][t].N, ColorMaterials, 0); glColor3fv(color); glVertex3fv(_triangles[i][t].A); glColor3fv(color); glVertex3fv(_triangles[i][t].B); glColor3fv(color); glVertex3fv(_triangles[i][t].C); } glEnd(); } //glDisable(GL_COLOR_MATERIAL); } } int Renderer:: _SelectRenderState(Tri Tri) { float lightingColor[3]; if (ColorMaterialEnabled) // UPDATE CURRENTLY SPECIFIED COLOR MATERIAL { float C[] = {Tri.Color[0] / 255.0, Tri.Color[1] / 255.0, Tri.Color[2] / 255.0, 1.0 }; Materialfv(ColorMaterialFace,ColorMaterialMode,C); } _CalcLighting(lightingColor, Tri.A, Tri.N, ColorMaterials, 0); float intensity = (lightingColor[0] + lightingColor[1] + lightingColor[2]); int result = intensity*(_numRenderStates-1); if(result > _numRenderStates-1) result = _numRenderStates-1; return result; }