diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index 8fb47a0b..57abc6bf 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -3177,6 +3177,10 @@ void Game::render3d(){ renderer.renderMouse3d(); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderMouse3d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis()); + renderer.renderUnitsToBuild(avgRenderFps); + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderUnitsToBuild]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start(); + renderer.setLastRenderFps(lastRenderFps); } diff --git a/source/glest_game/graphics/renderer.cpp b/source/glest_game/graphics/renderer.cpp index 13e0fbb0..d9dc6c7a 100644 --- a/source/glest_game/graphics/renderer.cpp +++ b/source/glest_game/graphics/renderer.cpp @@ -1736,14 +1736,13 @@ void Renderer::renderMouse3d() { throw megaglest_runtime_error(szBuf); } - GLUquadricObj *cilQuadric; - Vec4f color; - assertGl(); if((mouse3d->isEnabled() || gui->isPlacingBuilding()) && gui->isValidPosObjWorld()) { + const Vec2i &pos= gui->getPosObjWorld(); + glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + glPushAttrib(GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glDisable(GL_STENCIL_TEST); @@ -1751,43 +1750,23 @@ void Renderer::renderMouse3d() { glEnable(GL_COLOR_MATERIAL); glDepthMask(GL_FALSE); - const Vec2i &pos= gui->getPosObjWorld(); - - Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); - if(gui->isPlacingBuilding()) { - const UnitType *building= gui->getBuilding(); - - //selection building emplacement - float offset= building->getSize()/2.f-0.5f; - glTranslatef(pos3f.x+offset, pos3f.y, pos3f.z+offset); - - //choose color - if(map->isFreeCells(pos, building->getSize(), fLand)){ - color= Vec4f(1.f, 1.f, 1.f, 0.5f); - } - else { - color= Vec4f(1.f, 0.f, 0.f, 0.5f); - } modelRenderer->begin(true, true, false); - glColor4fv(color.ptr()); - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color.ptr()); - Model *buildingModel= building->getFirstStOfClass(scStop)->getAnimation(); - if(gui->getSelectedFacing() != CardinalDir::NORTH) { - float rotateAmount = gui->getSelectedFacing() * 90.f; - if(rotateAmount > 0) { - glRotatef(rotateAmount, 0.f, 1.f, 0.f); - } - } + const UnitType *building= gui->getBuilding(); + renderGhostModel(building, pos); - buildingModel->updateInterpolationData(0.f, false); - modelRenderer->render(buildingModel); - glDisable(GL_COLOR_MATERIAL); modelRenderer->end(); + + glDisable(GL_COLOR_MATERIAL); + glPopAttrib(); } else { + glPushMatrix(); + Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); + Vec4f color; + GLUquadricObj *cilQuadric; //standard mouse glDisable(GL_TEXTURE_2D); glDisable(GL_CULL_FACE); @@ -1808,9 +1787,9 @@ void Renderer::renderMouse3d() { gluCylinder(cilQuadric, 0.7f, 0.f, 0.f, 4, 1); gluDeleteQuadric(cilQuadric); + glPopAttrib(); + glPopMatrix(); } - glPopAttrib(); - glPopMatrix(); } } @@ -4614,7 +4593,56 @@ void Renderer::renderTeamColorPlane(){ } } +void Renderer::renderGhostModel(const UnitType *building, const Vec2i pos,Vec4f *forceColor) { + //const UnitType *building= gui->getBuilding(); + //const Vec2i &pos= gui->getPosObjWorld(); + const Gui *gui= game->getGui(); + //const Mouse3d *mouse3d= gui->getMouse3d(); + const Map *map= game->getWorld()->getMap(); + if(map == NULL) { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s] Line: %d map == NULL",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); + throw megaglest_runtime_error(szBuf); + } + + glPushMatrix(); + Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); + + //selection building placement + float offset= building->getSize()/2.f-0.5f; + glTranslatef(pos3f.x+offset, pos3f.y, pos3f.z+offset); + + //choose color + Vec4f color; + if(forceColor != NULL) { + color = *forceColor; + } + else { + if(map->isFreeCells(pos, building->getSize(), fLand)) { + color= Vec4f(1.f, 1.f, 1.f, 0.5f); + } + else { + color= Vec4f(1.f, 0.f, 0.f, 0.5f); + } + } + + glColor4fv(color.ptr()); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color.ptr()); + Model *buildingModel= building->getFirstStOfClass(scStop)->getAnimation(); + + if(gui->getSelectedFacing() != CardinalDir::NORTH) { + float rotateAmount = gui->getSelectedFacing() * 90.f; + if(rotateAmount > 0) { + glRotatef(rotateAmount, 0.f, 1.f, 0.f); + } + } + + buildingModel->updateInterpolationData(0.f, false); + modelRenderer->render(buildingModel); + + glPopMatrix(); +} void Renderer::renderUnits(const int renderFps) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { @@ -4734,6 +4762,47 @@ void Renderer::renderUnits(const int renderFps) { } +void Renderer::renderUnitsToBuild(const int renderFps) { + if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { + return; + } + + //assert + assertGl(); + + VisibleQuadContainerCache &qCache = getQuadCache(); + if(qCache.visibleQuadUnitBuildList.empty() == false) { + Vec4f modelColor= Vec4f(0.f, 1.f, 0.f, 0.5f); + + glMatrixMode(GL_MODELVIEW); + glPushAttrib(GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_BLEND); + glDisable(GL_STENCIL_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_COLOR_MATERIAL); + glDepthMask(GL_FALSE); + + modelRenderer->begin(true, true, false); + + for(int visibleUnitIndex = 0; + visibleUnitIndex < qCache.visibleQuadUnitBuildList.size(); ++visibleUnitIndex) { + std::pair &buildUnit = qCache.visibleQuadUnitBuildList[visibleUnitIndex]; + renderGhostModel(buildUnit.second, buildUnit.first,&modelColor); + + //printf("Rendering to build unit index = %d\n",visibleUnitIndex); + } + + modelRenderer->end(); + + glDisable(GL_COLOR_MATERIAL); + glPopAttrib(); + } + + //assert + assertGl(); + +} + void Renderer::renderTeamColorEffect(Vec3f &v, int heigth, int size, Vec3f color, const Texture2D *texture) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; @@ -7994,7 +8063,7 @@ VisibleQuadContainerCache & Renderer::getQuadCache( bool updateOnDirtyFrame, for(int j = 0; j < faction->getUnitCount(); ++j) { Unit *unit= faction->getUnit(j); - + bool unitCheckedForRender = false; if(VisibleQuadContainerCache::enableFrustumCalcs == true) { //bool insideQuad = PointInFrustum(quadCache.frustumData, unit->getCurrVector().x, unit->getCurrVector().y, unit->getCurrVector().z ); bool insideQuad = CubeInFrustum(quadCache.frustumData, unit->getCurrVector().x, unit->getCurrVector().y, unit->getCurrVector().z, unit->getType()->getSize()); @@ -8004,25 +8073,71 @@ VisibleQuadContainerCache & Renderer::getQuadCache( bool updateOnDirtyFrame, if(renderInMap == true) { quadCache.visibleUnitList.push_back(unit); } - continue; // no more need to check any further; + unitCheckedForRender = true; // no more need to check any further; // Currently don't need this list //quadCache.inVisibleUnitList.push_back(unit); } } + if(unitCheckedForRender == false) { + bool insideQuad = visibleQuad.isInside(unit->getPos()); + bool renderInMap = world->toRenderUnit(unit); + if(insideQuad == true && renderInMap == true) { + quadCache.visibleQuadUnitList.push_back(unit); + } + else { + unit->setVisible(false); + // Currently don't need this list + //quadCache.inVisibleUnitList.push_back(unit); + } - bool insideQuad = visibleQuad.isInside(unit->getPos()); - bool renderInMap = world->toRenderUnit(unit); - if(insideQuad == true && renderInMap == true) { - quadCache.visibleQuadUnitList.push_back(unit); - } - else { - unit->setVisible(false); - // Currently don't need this list - //quadCache.inVisibleUnitList.push_back(unit); + if(renderInMap == true) { + quadCache.visibleUnitList.push_back(unit); + } } - if(renderInMap == true) { - quadCache.visibleUnitList.push_back(unit); + bool unitBuildPending = unit->isBuildCommandPending(); + if(unitBuildPending == true) { + std::pair pendingUnit = unit->getBuildCommandPendingInfo(); + const Vec2i &pos = pendingUnit.first; + const Map *map= world->getMap(); + + bool unitBuildCheckedForRender = false; + + //printf("#1 Unit is about to build another unit\n"); + + if(VisibleQuadContainerCache::enableFrustumCalcs == true) { + Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); + //bool insideQuad = PointInFrustum(quadCache.frustumData, unit->getCurrVector().x, unit->getCurrVector().y, unit->getCurrVector().z ); + bool insideQuad = CubeInFrustum(quadCache.frustumData, pos3f.x, pos3f.y, pos3f.z, pendingUnit.second->getSize()); + bool renderInMap = world->toRenderUnit(unit,pendingUnit); + if(insideQuad == false || renderInMap == false) { + if(renderInMap == true) { + quadCache.visibleQuadUnitBuildList.push_back(pendingUnit); + } + unitBuildCheckedForRender = true; // no more need to check any further; + // Currently don't need this list + //quadCache.inVisibleUnitList.push_back(unit); + } + + //printf("#2 Unit build added? insideQuad = %d, renderInMap = %d\n",insideQuad,renderInMap); + } + + if(unitBuildCheckedForRender == false) { + bool insideQuad = visibleQuad.isInside(pos); + bool renderInMap = world->toRenderUnit(unit,pendingUnit); + if(insideQuad == true && renderInMap == true) { + quadCache.visibleQuadUnitBuildList.push_back(pendingUnit); + } + else { + //unit->setVisible(false); + // Currently don't need this list + //quadCache.inVisibleUnitList.push_back(unit); + } + + //printf("#3 Unit build added? insideQuad = %d, renderInMap = %d\n",insideQuad,renderInMap); + } + + //printf("#4 quadCache.visibleQuadUnitBuildList.size() = %d\n",quadCache.visibleQuadUnitBuildList.size()); } } } diff --git a/source/glest_game/graphics/renderer.h b/source/glest_game/graphics/renderer.h index 52f3bdbb..e21b78f7 100644 --- a/source/glest_game/graphics/renderer.h +++ b/source/glest_game/graphics/renderer.h @@ -102,6 +102,7 @@ protected: visibleObjectList = obj.visibleObjectList; visibleUnitList = obj.visibleUnitList; visibleQuadUnitList = obj.visibleQuadUnitList; + visibleQuadUnitBuildList = obj.visibleQuadUnitBuildList; visibleScaledCellList = obj.visibleScaledCellList; visibleScaledCellToScreenPosList = obj.visibleScaledCellToScreenPosList; lastVisibleQuad = obj.lastVisibleQuad; @@ -133,10 +134,12 @@ public: inline void clearVolatileCacheData() { visibleUnitList.clear(); visibleQuadUnitList.clear(); + visibleQuadUnitBuildList.clear(); //inVisibleUnitList.clear(); visibleUnitList.reserve(500); visibleQuadUnitList.reserve(500); + visibleQuadUnitBuildList.reserve(100); } inline void clearNonVolatileCacheData() { visibleObjectList.clear(); @@ -156,6 +159,7 @@ public: Quad2i lastVisibleQuad; std::vector visibleObjectList; std::vector visibleQuadUnitList; + std::vector > visibleQuadUnitBuildList; std::vector visibleUnitList; std::vector visibleScaledCellList; std::map visibleScaledCellToScreenPosList; @@ -463,6 +467,9 @@ public: //basic rendering void renderMouse2d(int mouseX, int mouseY, int anim, float fade= 0.f); void renderMouse3d(); + + void renderGhostModel(const UnitType *building, const Vec2i pos,Vec4f *forceColor=NULL); + void renderBackground(const Texture2D *texture); void renderTextureQuad(int x, int y, int w, int h, const Texture2D *texture, float alpha=1.f,const Vec3f *color=NULL); void renderConsole(const Console *console, const bool showAll=false, const bool showMenuConsole=false, int overrideMaxConsoleLines=-1); @@ -511,6 +518,7 @@ public: void renderWater(); void renderUnits(const int renderFps); + void renderUnitsToBuild(const int renderFps); void renderSelectionEffects(); void renderWaterEffects(); diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index 7ee14c54..e0e2d7e0 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -859,6 +859,38 @@ bool Unit::isBuilt() const{ return (isBeingBuilt() == false); } +bool Unit::isBuildCommandPending() const { + bool result = false; + + Command *command= this->getCurrCommand(); + if(command != NULL) { + const BuildCommandType *bct= dynamic_cast(command->getCommandType()); + if(bct != NULL) { + if(this->getCurrSkill()->getClass() != scBuild) { + result = true; + } + } + } + + return result; +} + +std::pair Unit::getBuildCommandPendingInfo() const { + std::pair result; + result.second = NULL; + + Command *command= this->getCurrCommand(); + if(command != NULL) { + const BuildCommandType *bct= dynamic_cast(command->getCommandType()); + if(bct != NULL) { + result.first = command->getOriginalPos(); + result.second = command->getUnitType(); + } + } + + return result; +} + bool Unit::isAlly(const Unit *unit) const { if(unit == NULL) { char szBuf[4096]=""; diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index d2e3274f..69bec62a 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -534,6 +534,9 @@ public: bool isOperative() const; bool isBeingBuilt() const; bool isBuilt() const; + bool isBuildCommandPending() const; + std::pair getBuildCommandPendingInfo() const; + bool isAnimProgressBound() const; bool isPutrefacting() const { return deadCount!=0; diff --git a/source/glest_game/world/world.cpp b/source/glest_game/world/world.cpp index 135c96da..c2826951 100644 --- a/source/glest_game/world/world.cpp +++ b/source/glest_game/world/world.cpp @@ -827,6 +827,23 @@ bool World::toRenderUnit(const Unit *unit) const { map.getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()))->isExplored(thisTeamIndex)); } +bool World::toRenderUnit(const Unit *unit, std::pair pendingUnit) const { + if(unit == NULL) { + throw megaglest_runtime_error("unit == NULL"); + } + + if(showWorldForPlayer(thisFactionIndex) == true) { + return true; + } + if(unit->getTeam() != thisTeamIndex) { + return false; + } + + return + (map.getSurfaceCell(Map::toSurfCoords(pendingUnit.first))->isVisible(thisTeamIndex) && + map.getSurfaceCell(Map::toSurfCoords(pendingUnit.first))->isExplored(thisTeamIndex) ); +} + void World::morphToUnit(int unitId,const string &morphName,bool ignoreRequirements) { if(SystemFlags::getSystemSettingType(SystemFlags::debugLUA).enabled) SystemFlags::OutputDebug(SystemFlags::debugLUA,"In [%s::%s Line: %d] unit [%d] morphName [%s] forceUpgradesIfRequired = %d\n",__FILE__,__FUNCTION__,__LINE__,unitId,morphName.c_str(),ignoreRequirements); Unit* unit= findUnitById(unitId); diff --git a/source/glest_game/world/world.h b/source/glest_game/world/world.h index 9b6bc439..b36b70da 100644 --- a/source/glest_game/world/world.h +++ b/source/glest_game/world/world.h @@ -216,8 +216,12 @@ public: const UnitType* findUnitTypeById(const FactionType* factionType, int id); bool placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spaciated= false); void moveUnitCells(Unit *unit); + bool toRenderUnit(const Unit *unit, const Quad2i &visibleQuad) const; bool toRenderUnit(const Unit *unit) const; + bool toRenderUnit(const Unit *unit, std::pair pendingUnit) const; + + Unit *nearestStore(const Vec2i &pos, int factionIndex, const ResourceType *rt); void addAttackEffects(const Unit *unit);