bool CRenderManager::update() { glColor3f(1.0f,1.0f,1.0f); // get camera CCamera *camera = CV_GAME_MANAGER->getControlManager()->getCamera(); // transform view camera->transformView(); // Draw the map and items that fall into view frustum. // 1. extract approximate logical location of camera in the level map. vector2i center = CConversions::realToLogical(camera->getPosition()); GLint centerX = center[0]; GLint centerY = center[1]; bool isFPS = CV_GAME_MANAGER->getControlManager()->isFPS(); if (isFPS) { // fog only in FPS mode glEnable(GL_FOG); } /* In FPS mode we can't use height to determine visible offset. We have to use some extent read from config (CV_CAMERA_FPS_EXTENT). */ GLint diff = (GLint)(isFPS?cameraFPSExtent:camera->getPosition()[1]*10.0f); // 2. create a bounding square making its center logical position calculate above. GLint minX = (centerX-diff>=0?centerX-diff:0); GLint minY = (centerY-diff>=0?centerY-diff:0); GLint maxX = (centerX+diff<(GLint)CV_LEVEL_MAP_SIZE?centerX+diff:CV_LEVEL_MAP_SIZE-1); GLint maxY = (centerY+diff<(GLint)CV_LEVEL_MAP_SIZE?centerY+diff:CV_LEVEL_MAP_SIZE-1); // 3. go through all block that fall into this bounding square and check if they fall // int out view frustum. If not then just exclude them. CBlock *block; GLint blockVisible = 0, allVerticesCount = 0, creaturesVisible = 0, maxVertInput = 0, maxTexInput = 0; tmpVboVertexBufferSize = 0; tmpVboTexCoordBufferSize = 0; vector3f vertA, vertB, vertC; GLfloat **verts, *texCoords; CLevelManager *lManager = CV_GAME_MANAGER->getLevelManager(); CAnimatedTerrainManager *atManager = CV_GAME_MANAGER->getAnimatedTerrainManager(); CFrustum *frustum = CV_GAME_MANAGER->getControlManager()->getViewFrustum(); bool lavaWater = false; GLfloat delta = CV_GAME_MANAGER->getDeltaTime(); renderedBlocks.clear(); for (GLint y=minY; y<=maxY; y++) { for (GLint x=minX; x<=maxX; x++) { block = lManager->getBlock(x,y); if (block) { //block->getBoundingBox()->draw(); // just for testing if (frustum->containsBBOX(block->getBoundingBox())) { blockVisible++; block->updateTexture(delta); lavaWater = (block->isLava() || block->isWater()); if (lavaWater) { atManager->updateBlock(block); } renderedBlocks.push_back(block); // draw block objects if (block->getBlockObjects()->size()>0) { for (std::vector<CBlockObject*>::iterator rmIter = block->getBlockObjects()->begin(); rmIter != block->getBlockObjects()->end(); rmIter++) { CBlockObject *bObj = *rmIter; bObj->moveTo(); glRotatef(bObj->getRotateY(),0.0f,1.0f,0.0f); bObj->drawModel(delta); glRotatef(-bObj->getRotateY(),0.0f,1.0f,0.0f); bObj->moveBack(); } } bool isRoom = block->isRoom(); if (isRoom) { std::vector<GLuint> *dls = block->getDisplayLists(); if (dls->size()!=0) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,textureAtlasColor); glBegin(GL_QUADS); { for (std::vector<GLuint>::iterator dlIter = dls->begin(); dlIter != dls->end(); dlIter++) { glCallList(*dlIter); } } glEnd(); glDisable(GL_TEXTURE_2D); } } for (GLint f=CBlock::BFS_FRONT; f<=CBlock::BFS_CEILING; f++) { if ((!isFPS && f==CBlock::BFS_CEILING) || (isFPS && f==CBlock::BFS_TOP) || (isRoom && f!=CBlock::BFS_CEILING)) { continue; } if (block->isFaceVisible((CBlock::BLOCK_FACE_SELECTOR)f)) { verts = block->getVertices(); texCoords = block->getTextureCoordinates((CBlock::BLOCK_FACE_SELECTOR)f); if (lavaWater && f<=CBlock::BFS_RIGHT) { /* Lava and water have only lowers row of wall sections drawn. If they are drawn at all. */ maxVertInput = CV_FBLR_W_L_FACE_VERT_FLOATS; maxTexInput = CV_FBLR_W_L_FACE_TEX_FLOATS; } else { maxVertInput = f>=CBlock::BFS_TOP?CV_TBWLC_FACE_VERT_FLOATS:CV_FBLR_FACE_VERT_FLOATS; maxTexInput = f>=CBlock::BFS_TOP?CV_TBWLC_FACE_TEX_FLOATS:CV_FBLR_FACE_TEX_FLOATS; } if (tmpVboVertexBufferSize+maxVertInput>CV_MAX_VERTEX_BUFFER*3) { vbo->setElementsCount(CVBO::IDT_vertex,tmpVboVertexBufferSize/3); vbo->setElementsCount(CVBO::IDT_texture0,tmpVboTexCoordBufferSize/2); vbo->setElementsCount(CVBO::IDT_texture1,tmpVboTexCoordBufferSize/2); vbo->draw(); allVerticesCount+=tmpVboVertexBufferSize; tmpVboVertexBufferSize=0; tmpVboTexCoordBufferSize=0; } memcpy(tmpVboVertexBuffer+tmpVboVertexBufferSize, verts[f], sizeof(GLfloat)*maxVertInput); tmpVboVertexBufferSize+=maxVertInput; memcpy(tmpVboTexCoordBuffer+tmpVboTexCoordBufferSize, texCoords, sizeof(GLfloat)*maxTexInput); tmpVboTexCoordBufferSize+=maxTexInput; } } } } } } if (tmpVboVertexBufferSize>0) { vbo->setElementsCount(CVBO::IDT_vertex,tmpVboVertexBufferSize/3); vbo->setElementsCount(CVBO::IDT_texture0,tmpVboTexCoordBufferSize/2); vbo->setElementsCount(CVBO::IDT_texture1,tmpVboTexCoordBufferSize/2); vbo->draw(); allVerticesCount+=tmpVboVertexBufferSize; } // draw creatures CCreatureManager *cManager = CV_GAME_MANAGER->getCreatureManager(); GLint cCount = cManager->getCreatureVector()->size(); if (cCount>0) { CCreature *creature = NULL; for (std::vector<CCreature*>::iterator cIter = cManager->getCreatureVector()->begin(); cIter != cManager->getCreatureVector()->end(); cIter++) { creature = (*cIter); if (creature) { sBoundingBox *cBBOX = creature->getModel()->getBoundingBox(); cBBOX->translate(creature->getPosition()); if (frustum->containsBBOX(cBBOX)) { creature->draw(delta); creaturesVisible++; } cBBOX->translate(-creature->getPosition()); } } } // draw transparent block objects for (std::vector<CBlock*>::iterator vbIter = renderedBlocks.begin(); vbIter != renderedBlocks.end(); vbIter++) { block = *vbIter; if (block->getBlockObjects()->size()>0) { for (std::vector<CBlockObject*>::iterator rmIter = block->getBlockObjects()->begin(); rmIter != block->getBlockObjects()->end(); rmIter++) { CBlockObject *bObj = *rmIter; bObj->moveTo(); glRotatef(bObj->getRotateY(),0.0f,1.0f,0.0f); bObj->drawEffect(); glRotatef(-bObj->getRotateY(),0.0f,1.0f,0.0f); bObj->moveBack(); } } } glDisable(GL_FOG); if (!isFPS) { handlePickedObjects(); } CV_GAME_MANAGER->getTextPrinter()->print((GLfloat)0,(GLfloat)(CV_SETTINGS_WINDOW_HEIGHT-15*3),"Visible blocks: %d",blockVisible); CV_GAME_MANAGER->getTextPrinter()->print((GLfloat)0,(GLfloat)(CV_SETTINGS_WINDOW_HEIGHT-15*2),"Visible creatures: %d",creaturesVisible); CV_GAME_MANAGER->getTextPrinter()->print((GLfloat)0,(GLfloat)(CV_SETTINGS_WINDOW_HEIGHT-15),"Triangles drawn: %d",(allVerticesCount/4)*2); // render the lights representations. usefull for debugging CV_GAME_MANAGER->getLightingManager()->drawLightSources(frustum); return true; }
GLvoid CRenderManager::handlePickedObjects() { // if we are ower the menu we do not have to proccess things under the cursor if (CV_GAME_MANAGER->getGUIManager()->getPlayGUI()->is_mouse_over_gui()) { return; } // if we are not selling or buying we don't have to process blocks (just objects TODO) ACTION_EVENT *ae = CV_GAME_MANAGER->getGUIManager()->getLastActionEvent(); // get the block we have our cousor on CBlock *pickedBlock = CV_GAME_MANAGER->getPickingManager()->getLastPickedBlock(); if (pickedBlock) { GLint type = pickedBlock->getType(); /*if (!pickedBlock->isSellable()) { return; }*/ sBoundingBox *bbox = pickedBlock->getBoundingBox(); vector3f a(bbox->A); vector3f b(bbox->B); vector3f c(bbox->C); vector3f d(bbox->D); vector3f e(bbox->E); vector3f f(bbox->F); vector3f g(bbox->G); vector3f h(bbox->H); a[1]=b[1]=c[1]=d[1]=CV_BLOCK_HEIGHT+CV_BLOCK_HEIGHT/4.0f+CV_BLOCK_HEIGHT/32.0f; e[1]=f[1]=g[1]=h[1]=CV_BLOCK_HEIGHT/4.0f+CV_BLOCK_HEIGHT/32.0f; glLineWidth(4.0f); if (pickedBlock->isLow()) { if (!(ae->message_group==AEMG_BUILD_ROOMS || ae->message_group==AEMG_BUILD_DOORS || ae->message_group==AEMG_BUILD_TRAPS)) { return; } // draw the selection box if (pickedBlock->isSellable(CV_CURRENT_PLAYER_ID) && ae->message == AEM_SELL) { glColor3f(0.0f,1.0f,0.0f); } else if (pickedBlock->isBuildable(CV_CURRENT_PLAYER_ID) && ae->message != AEM_SELL) { glColor3f(0.0f,1.0f,0.0f); } else { glColor3f(1.0f,0.0f,0.0f); } glBegin(GL_LINES); { /*glVertex3fv(&a[0]); glVertex3fv(&b[0]); glVertex3fv(&b[0]); glVertex3fv(&c[0]); glVertex3fv(&c[0]); glVertex3fv(&d[0]); glVertex3fv(&d[0]); glVertex3fv(&a[0]);*/ glVertex3fv(&e[0]); glVertex3fv(&f[0]); glVertex3fv(&f[0]); glVertex3fv(&g[0]); glVertex3fv(&g[0]); glVertex3fv(&h[0]); glVertex3fv(&h[0]); glVertex3fv(&e[0]); /*glVertex3fv(&a[0]); glVertex3fv(&e[0]); glVertex3fv(&b[0]); glVertex3fv(&f[0]); glVertex3fv(&c[0]); glVertex3fv(&g[0]); glVertex3fv(&d[0]); glVertex3fv(&h[0]);*/ } glEnd(); } else { if (!(ae->message_group==AEMG_BUILD_ROOMS || ae->message_group==AEMG_BUILD_DOORS || ae->message_group==AEMG_BUILD_TRAPS)) glColor3f(type==CV_BLOCK_TYPE_ROCK_ID?1.0f:0.0f,type==CV_BLOCK_TYPE_ROCK_ID?0.0f:1.0f,0.0f); else glColor3f(1.0f,0.0f,0.0f); glBegin(GL_LINES); { glVertex3fv(&a[0]); glVertex3fv(&b[0]); glVertex3fv(&b[0]); glVertex3fv(&c[0]); glVertex3fv(&c[0]); glVertex3fv(&d[0]); glVertex3fv(&d[0]); glVertex3fv(&a[0]); glVertex3fv(&e[0]); glVertex3fv(&f[0]); glVertex3fv(&f[0]); glVertex3fv(&g[0]); glVertex3fv(&g[0]); glVertex3fv(&h[0]); glVertex3fv(&h[0]); glVertex3fv(&e[0]); glVertex3fv(&a[0]); glVertex3fv(&e[0]); glVertex3fv(&b[0]); glVertex3fv(&f[0]); glVertex3fv(&c[0]); glVertex3fv(&g[0]); glVertex3fv(&d[0]); glVertex3fv(&h[0]); } glEnd(); } glLineWidth(1.0f); } }