00001 00002 00003 #include "SingleTexturedMesh.h" 00004 00005 #include "AABB.h" 00006 #include "Camera.h" 00007 #include "CoreEngine.h" 00008 #include "Renderer.h" 00009 #include "LightShader.h" 00010 #include "Sphere.h" 00011 #include "Texture.h" 00012 #include "TextureDatabase.h" 00013 #include "VBO.h" 00014 #include "World.h" 00015 00016 00017 namespace pge { 00018 00019 //**************************************************************************** 00020 // 00021 // 00022 // 00023 //**************************************************************************** 00024 SingleTexturedMesh::SingleTexturedMesh(bool disableLightShader) : Mesh() { 00025 m_texture = TextureDatabase::getInstance()->getDefaultTexture(); 00026 m_renderMode = Mesh::VertexBufferObject; 00027 m_vbo = NULL; 00028 m_vertexNum = 0; 00029 m_disableLightShader = disableLightShader; 00030 00031 if(!m_disableLightShader) { 00032 m_lightShader = new LightShader(CoreEngine::getInstance()->getCurrentWorld()->getLightProgram()); 00033 } else { 00034 m_lightShader = NULL; 00035 } 00036 00037 } 00038 00039 00040 //**************************************************************************** 00041 // 00042 // 00043 // 00044 //**************************************************************************** 00045 SingleTexturedMesh::~SingleTexturedMesh(void) { 00046 if(m_vbo != NULL) { 00047 delete m_vbo; 00048 m_vbo = NULL; 00049 } 00050 if(m_lightShader != NULL) { 00051 delete m_lightShader; 00052 m_lightShader = NULL; 00053 } 00054 } 00055 00056 00057 //**************************************************************************** 00058 // 00059 // 00060 // 00061 //**************************************************************************** 00062 bool SingleTexturedMesh::init(void) { 00063 Mesh::init(); 00064 buildVBO(); 00065 00066 if(!m_disableLightShader && m_lightShader != NULL) { 00067 getSurroundingLights(); 00068 } 00069 00070 return true; 00071 } 00072 00073 00074 //**************************************************************************** 00075 // 00076 // 00077 // 00078 //**************************************************************************** 00079 void SingleTexturedMesh::render(void) { 00080 // Calculate alpha value based on distance to the camera. 00081 Camera *camera = CoreEngine::getInstance()->getCurrentWorld()->getCamera(); 00082 float sqrDist = 0.0f; 00083 float dist = 0.0f; 00084 float maxDistance = 200.0f; 00085 float minDistance = 180.0f; 00086 00087 // If the camera is inside of the mesh's sphere, then render without alpha. 00088 if(m_boundingSphere->isIntersecting(*camera->getBoundingSphere())) { 00089 m_alphaColor = 1.0f; 00090 } else { 00091 // Calculate distance to camera. 00092 sqrDist = camera->getPosition().sqrDistance(m_boundingSphere->m_center); 00093 if(sqrDist >= minDistance * minDistance) { 00094 if(sqrDist <= maxDistance * maxDistance) { 00095 // Calculate blend factor. 00096 dist = camera->getPosition().distance(m_boundingSphere->m_center) - minDistance; 00097 m_alphaColor = 1.0f - (dist / (maxDistance - minDistance)); 00098 } else { 00099 m_alphaColor = 0.0f; 00100 } 00101 } else { 00102 m_alphaColor = 1.0f; 00103 } 00104 } 00105 if(m_alphaColor > 0.0f) { 00106 renderVBO(); 00107 } 00108 } 00109 00110 00111 //**************************************************************************** 00112 // 00113 // 00114 // 00115 //**************************************************************************** 00116 void SingleTexturedMesh::setTexture(Texture *texture) { 00117 if(texture != NULL) { 00118 m_texture = texture; 00119 } 00120 } 00121 00122 00123 //**************************************************************************** 00124 // 00125 // 00126 // 00127 //**************************************************************************** 00128 void SingleTexturedMesh::buildVBO(void) { 00129 std::vector<Triangle*>::iterator it; 00130 00131 00132 m_vertexNum = getVertexNum(); 00133 m_vbo = new VBO(m_vertexNum); 00134 00135 // Go through all triangles. 00136 for(it = m_triangles->begin(); it != m_triangles->end(); it++) { 00137 Triangle *triangle = *it; 00138 00139 m_vbo->addTriangle(triangle); 00140 } 00141 00142 m_vbo->buildVBO(); 00143 } 00144 00145 00146 //**************************************************************************** 00147 // 00148 // 00149 // 00150 //**************************************************************************** 00151 void SingleTexturedMesh::renderVBO(void) { 00152 if(m_texture != NULL) { 00153 // Enable alpha blending if the texture is set to it. 00154 if(m_texture->hasAlphaBlending()) { 00155 renderer::setTextureAlphaBlendEnabled(true); 00156 00157 } else if(m_alphaColor < 1.0f) { 00158 renderer::setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00159 renderer::setBlendingEnabled(true); 00160 } 00161 renderer::setTexture(m_texture, GL_MODULATE); 00162 renderer::color4f(1.0f, 1.0f, 1.0f, m_alphaColor); 00163 00164 } else { 00165 glDisable(GL_TEXTURE_2D); 00166 } 00167 00168 // Light shader. 00169 if(!m_disableLightShader && m_lightShader != NULL) { 00170 m_lightShader->preRender(); 00171 } 00172 00173 // Render. 00174 m_vbo->renderVBO(0, m_vertexNum); 00175 00176 // Light shader. 00177 if(!m_disableLightShader && m_lightShader != NULL) { 00178 m_lightShader->postRender(); 00179 } 00180 00181 if(m_texture != NULL) { 00182 // Disable alpha blending. 00183 if(m_texture->hasAlphaBlending()) { 00184 renderer::setTextureAlphaBlendEnabled(false); 00185 } 00186 } 00187 if(m_alphaColor < 1.0f) { 00188 renderer::setBlendingEnabled(false); 00189 // Reset alpha color. 00190 renderer::color4f(1.0f, 1.0f, 1.0f, 1.0f); 00191 } 00192 } 00193 00194 00195 //**************************************************************************** 00196 // 00197 // 00198 // 00199 //**************************************************************************** 00200 void SingleTexturedMesh::renderImmediate(void) { 00201 } 00202 00203 00204 //**************************************************************************** 00205 // 00206 // TODO: What to do if there are less than 3 lights in the world?! 00207 // 00208 //**************************************************************************** 00209 void SingleTexturedMesh::getSurroundingLights(void) { 00210 int i; 00211 World *world; 00212 Light *light; 00213 float distance; 00214 float minDistance; 00215 float tmpDistance; 00216 Light *minLight1; 00217 Light *minLight2; 00218 Light *minLight3; 00219 00220 00221 world = CoreEngine::getInstance()->getCurrentWorld(); 00222 00223 // TODO: infinity for this map! 00224 minDistance = 10000000.0f; 00225 00226 /*// Find the minimal distance light. 00227 for(i = 0; i < world->getLightNum(); i++) { 00228 light = world->getLightAt(i); 00229 distance = Vector3f(light->m_position).distance(m_boundingBox->getCenter()); 00230 if(distance < minDistance) { 00231 minLight1 = light; 00232 minDistance = distance; 00233 } 00234 } 00235 00236 // TODO: infinity for this map! 00237 tmpDistance = 10000000.0f; 00238 00239 // Find the second smallest distance light. 00240 for(i = 0; i < world->getLightNum(); i++) { 00241 light = world->getLightAt(i); 00242 distance = Vector3f(light->m_position).distance(m_boundingBox->getCenter()); 00243 00244 if(distance >= minDistance && distance < tmpDistance && light != minLight1) { 00245 minLight2 = light; 00246 tmpDistance = distance; 00247 } 00248 } 00249 00250 minDistance = tmpDistance; 00251 00252 // Find the third smallest distance light. 00253 for(i = 0; i < world->getLightNum(); i++) { 00254 light = world->getLightAt(i); 00255 distance = Vector3f(light->m_position).distance(m_boundingBox->getCenter()); 00256 00257 if(distance >= minDistance && distance < tmpDistance && light != minLight1 && light != minLight2) { 00258 minLight3 = light; 00259 tmpDistance = distance; 00260 } 00261 }*/ 00262 00263 00264 minLight1 = world->getLightAt(0); 00265 minLight2 = world->getLightAt(1); 00266 minLight3 = world->getLightAt(2); 00267 00268 m_lightShader->addActiveLight(minLight1); 00269 m_lightShader->addActiveLight(minLight2); 00270 m_lightShader->addActiveLight(minLight3); 00271 } 00272 };