Game Development Community

TGEA 1.8.1 and RTS kit integration

by Morrie · in General Discussion · 09/05/2009 (8:00 pm) · 7 replies

I was wondering if any has been able to complete the integration between the RTS kit and the TGEA 1.8.1. I’ve looked through the forums, it seems like a lot of people tries but there are no responses if they have succeeded. Also does anyone know if it will be updated for T3D? If so it would be a great asset.

Any help would be greatly appreciated. I would like to use TGEA 1.8.1.

#1
09/09/2009 (6:42 am)
my game needed some rts features, so i decided this week to port what i could of the rts kit. its not pretty, i am willing to share. much help will be appreciated in cleaning up.

the only part i have not been able to port is the guiMapHudGen.cc, well, i have ported it, but its not generating my texture, if i use a precreated texture, guiMapHudRenderer.cc pulls it through fine.

my focus is ai, so when dealing with graphics i have done some bad things like moving core code private variables to public to make some of the rts code work, other than that, most of the ported code has been taking from the guru's on these forums, specially thanks to arcane-fx. yet my graphics knowledge is still too poor for me to complete the port.

guiMapHud.h:
#ifndef _GUIMAPHUD_H_
#define _GUIMAPHUD_H_

#define GFX_GRAPHICS_LAYER

#include "app/game.h"
#include "terrain/terrRender.h"
#include "T3D/gameConnection.h"
#include "T3D/missionArea.h"
#include "gui/3d/guiTSControl.h"

/// This is a somewhat-simple minimap.  It renders an ortho-projection image of the
/// relevant mission area, and copies it into a texture.  Note that this method requires
/// the area of the window that it will render into not to be covered up while it's doing
/// this.  An alternate method of render-to-texture would be advisable, but is beyond
/// the scope of this pack.
///
/// In addition to rendering units, the viewable area, and terrain, the map can also
/// render "pings".  Pings are alerts that appear on the map that can signify different
/// things.  They might be used so that teammates can easily point out important areas
/// of the map, or to signify that something is under attack and needs your attention.
class GuiMapHud : public GuiTSCtrl
{
   private:
      typedef GuiTSCtrl Parent;

      /// Some constants that control the rendering of map pings
      enum
      {
         pingCycleMS = 500,
         pingLifetimeMS = 2000,
         pingMagnitude = 10,
         pingRadius = 5
      };

      /// Stores all the information relating to a Ping on the minimap.
      struct PingLocationEvent
      {
         Point2F screenPos;
         ColorF color;
         U32 t;
         PingLocationEvent* next;
         PingLocationEvent* prev;

         PingLocationEvent()
         {
            t = 0;
            next = NULL;
            prev = NULL;
         }
         PingLocationEvent(Point2F in_screenPos, ColorF in_color)
         {
            t = 0;
            next = NULL;
            prev = NULL;
            screenPos = in_screenPos;
            color = in_color;
         }
      };

      /// Keep a linked list of the active pings.
      PingLocationEvent* mPingHead;
      U32 mLastRenderTime;

      bool mLeftMouseDown;

      U32 mTerrainSize;
      U32 mTextureSize;

      SimObjectPtr<GameConnection> mConnection;

      TerrainBlock* mTerrainBlock;
      GBitmap* mRenderBitmap;
#if defined(GFX_GRAPHICS_LAYER)
      GFXTexHandle mRenderTexture;
#else
      TextureHandle mRenderTexture;
#endif

      // Visibility variables
      F32 mGameVisDistance;
      F32 mGameFogDistance;
      F32 mVisDistanceMod;

      F32 mMinHeight;
      F32 mMaxHeight;

      StringTableEntry mPingTextureName;
#if defined(GFX_GRAPHICS_LAYER)
      GFXTexHandle mPingTexture;
#else
      TextureHandle mPingTexture;
#endif

      //Takes a point in world space and turns it into screen space
      bool projectPoint(Point2F pt, Point2F* screenPos);
      bool projectPoint(Point3F pt, Point2F* screenPos);
      //Takes a point in screen space and turns it into world space
      bool unprojectPoint(Point2I pt, Point3F* worldPos, bool needZ = false);

      void setupRender();
      void cleanupRender();

      bool processCameraQuery(CameraQuery * query);

      void updatePings(U32 ms);

   public:
      // Constructor and Destructor
      GuiMapHud();
      ~GuiMapHud();

      void createPingEvent(Point2F pt, ColorF color);

      void renderWorld(const RectI &updateRect);
      bool rebuildMap(bool force = false);
      bool rebuildMapOld();

      // Public GUI Methods
      bool onWake();
      void onSleep();
      bool onAdd();
      void onRemove();
      void inspectPostApply();
      static void initPersistFields();

      void onMouseDown(const GuiEvent &event);
      void onMouseUp(const GuiEvent &event);
      void onRightMouseDown(const GuiEvent &event);
      void onMouseDragged(const GuiEvent &event);

      // Rendering Methods
      void onRender(Point2I offset, const RectI &updateRect);

      DECLARE_CONOBJECT(GuiMapHud);
};

#endif
#2
09/09/2009 (6:44 am)
guiMapHudGen.cc(part1)
#include "T3D/RTS/guiMapHud.h"
#include "sceneGraph/sceneGraph.h"
#include "interior/interiorInstance.h"
#include "T3D/missionArea.h"
#include "gui/core/guiCanvas.h"

static Point2F sCurrRenderPos;
static F32 sHalfRenderWidth;

//rebuild map using the backbuffer for a framebuffer
bool GuiMapHud::rebuildMapOld()
{
   //GLint drawBuffer = 0, readBuffer = 0;
   //glGetIntegerv(GL_DRAW_BUFFER, &drawBuffer);
   //glGetIntegerv(GL_READ_BUFFER, &readBuffer);
   //glDrawBuffer(GL_BACK);
   //glReadBuffer(GL_BACK);

   RectI oldBounds = mBounds;
   
   //make sure there is enough screen space
   U32 windowWidth = getRoot()->getPlatformWindow()->getBounds().extent.y;
   Con::printf("Window width for mini map %.3f", windowWidth);

   U32 maxSize = windowWidth;
   if (!isPow2(maxSize))
      maxSize = getNextPow2(maxSize) / 2;
   //need to do at least 4 pieces
   if (maxSize > mTextureSize / 2)
      maxSize = mTextureSize / 2;
   U32 subDivs = mTextureSize / maxSize;

   const RectI missionArea = MissionArea::smMissionArea;
   S32 biggerExtent = getMax(missionArea.extent.x, missionArea.extent.y);

   //setup some constants
   S32 texelSquareSize = maxSize;
   S32 renderSquareSize = biggerExtent / subDivs;
   sHalfRenderWidth = renderSquareSize / 2;

   Point2I center = (missionArea.extent / 2) + missionArea.point;
   Point2I start;
   if (missionArea.extent.x < missionArea.extent.y)
   {
      start.y = missionArea.point.y + sHalfRenderWidth;
      start.x = center.x + (missionArea.point.y - center.y) + sHalfRenderWidth;
   }
   else if (missionArea.extent.y < missionArea.extent.x)
   {
      start.x = missionArea.point.x + sHalfRenderWidth;
      start.y = center.y + (missionArea.point.x - center.x) + sHalfRenderWidth;
   }
   else
   {
      start = missionArea.point + Point2I(sHalfRenderWidth, sHalfRenderWidth);
   }

   mBounds.extent = Point2I(texelSquareSize, texelSquareSize);
   mBounds.point = Point2I(0,windowWidth - texelSquareSize);

   //ok, we're good now...
   //glColor3f(1.0,1.0,1.0);
   Con::printf("Map generation beginning...");
   U32 startTime = Platform::getRealMilliseconds();
   GFX->pushActiveRenderTarget();  
   GFXStateBlockRef sbr;
   GFXStateBlockDesc desc;
#3
09/09/2009 (6:45 am)
guiMapHudGen.cc(part2)
desc.setZEnable(true);
    sbr = GFX->createStateBlock(desc);

  GFX->setStateBlock(sbr);

   GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI( 255, 0, 0 ), 1.0f, 0 );
   for (S32 v = 0; v < subDivs; v++)
   {
      sCurrRenderPos.y = start.y + v * renderSquareSize;
      for (S32 u = 0; u < subDivs; u++)
      {
         sCurrRenderPos.x = start.x + u * renderSquareSize;

         U32 start = Platform::getRealMilliseconds();
         //glClear(GL_DEPTH_BUFFER_BIT);
		             GFX->clear(GFXClearZBuffer | GFXClearStencil, ColorI( 255, 0, 0 ), 1.0f, 0);
         Parent::onRender(mBounds.point, mBounds);
         Con::printf("Section rendered in %.3f seconds", (Platform::getRealMilliseconds() - start) / 1000.0);

         start = Platform::getRealMilliseconds();
		 GFX->getDrawUtil()->drawBitmapSR(mRenderTexture, Point2I(texelSquareSize*u, texelSquareSize*v),  
                 RectI(0, 0, texelSquareSize, texelSquareSize));
         //glFinish();
         //glBindTexture(GL_TEXTURE_2D, mRenderTexture.getGLName));
		 //GFX->setTexture( GL_TEXTURE_2D, mRenderTexture );
         //glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
         //   texelSquareSize*u, texelSquareSize*v,
         //   0, 0,
         //   texelSquareSize, texelSquareSize);
         Con::printf("Section captured in %.3f seconds", (Platform::getRealMilliseconds() - start) / 1000.0);
      }
   }

   //restore data
   GFX->popActiveRenderTarget();
   mBounds = oldBounds;
   //glDrawBuffer(drawBuffer);
   //glReadBuffer(readBuffer);

   Con::printf("Map generation complete in %.3f seconds", (Platform::getRealMilliseconds() - startTime) / 1000.0);

   return true;
}

bool GuiMapHud::rebuildMap(bool force)
{
   // get game server connection
   mConnection = GameConnection::getConnectionToServer();
   if(!mConnection)
      return false;

   Con::printf("Proceeding with mini-map generation...");

   TerrainBlock* newTerrain = gClientSceneGraph->getCurrentTerrain();
   AssertWarn(newTerrain, "No terrain block!");
   if (!newTerrain)
      return false;

   //ok, we've got everything we need - now do some calculations
   mTerrainBlock = newTerrain;
   mTerrainSize = TerrainBlock::BlockSize * newTerrain->getSquareSize();

   //make sure we're just above the highest object
   mMaxHeight = 0;
   mMinHeight = 1000;
   for (U32 v = 0; v < TerrainBlock::BlockSize; v++)
   {
      for (U32 u = 0; u < TerrainBlock::BlockSize; u++)
      {
         GridSquare* gs = newTerrain->findSquare(TerrainBlock::BlockShift, u, v);
         if (gs->maxHeight * 0.03125f > mMaxHeight)
            mMaxHeight = gs->maxHeight * 0.03125f;
         if (gs->minHeight * 0.03125f < mMinHeight)
            mMinHeight = gs->minHeight * 0.03125f;
      }
   }

   mMaxHeight += 1;

   //allocate bitmap, and backup old data
   //DON'T NEED TO DELETE BITMAP! TEXTURE MANAGER DOES THIS
   mRenderBitmap = new GBitmap(mTextureSize, mTextureSize);
   mRenderTexture = GFXTexHandle(mRenderBitmap, &GFXDefaultGUIProfile, false, avar("%s() - Cooldown Texture (line %d)", __FUNCTION__, __LINE__));

   rebuildMapOld();
   return true;
}
#4
09/09/2009 (6:48 am)
guiMapHudGen.cc(part3)
//set up a section to be rendered
void GuiMapHud::setupRender()
{
   //glEnable(GL_DEPTH_TEST);
   //glDepthFunc(GL_LEQUAL);
   //glClear(GL_DEPTH_BUFFER_BIT); //don't clear the depth buffer
   //glDisable(GL_CULL_FACE);
   //glMatrixMode(GL_MODELVIEW);
   //dglSetCanonicalState();
   //TerrainRender::mRenderingCommander = true;

	GFX->clear(GFXClearZBuffer | GFXClearStencil, ColorI( 255, 0, 0 ), 1.0f, 0);

	GFXStateBlockRef sbr;
    GFXStateBlockDesc desc;

    desc.cullDefined = true;
    desc.cullMode = GFXCullNone;

    sbr = GFX->createStateBlock(desc);

    GFX->setStateBlock(sbr);
   // set new and old visibility data
   mGameVisDistance = gClientSceneGraph->getVisibleDistance();
   mGameFogDistance = gClientSceneGraph->getFogDistance();
   mVisDistanceMod = gClientSceneGraph->getVisibleDistanceMod();
   F32 x = pow(mMaxHeight - mMinHeight + 2, 2);
   F32 y = pow(sHalfRenderWidth * mSqrt(2.0), 2);
   F32 dist = mSqrt(x + y) + 200;
   gClientSceneGraph->setVisibleDistance(dist);
   gClientSceneGraph->setFogDistance(dist + 50);
   gClientSceneGraph->smVisibleDistanceMod = 1.0;
}

//render a section
void GuiMapHud::renderWorld(const RectI &updateRect)
{
   setupRender();

   gClientSceneGraph->renderScene(TerrainObjectType | WaterObjectType);

   cleanupRender();
}

//cleanup that render
void GuiMapHud::cleanupRender()
{
   //TerrainRender::mRenderingCommander = false;
   gClientSceneGraph->setVisibleDistance(mGameVisDistance);
   gClientSceneGraph->setFogDistance(mGameFogDistance);
   gClientSceneGraph->smVisibleDistanceMod = mVisDistanceMod;
}

//GuiTSControl::onRender calls this for camera info before rendering
bool GuiMapHud::processCameraQuery(CameraQuery * query)
{
   // Get our camera matrix
   if(!mConnection->getControlCameraTransform(0.0f, &query->cameraMatrix))
      return false;

   // Set the rotation angle
   Point3F rotation(mDegToRad(90.0f), 0.0f, 0.0f);

   // Set near/far planes
   query->nearPlane = 0.1f;
   query->farPlane = mMaxHeight - mMinHeight + 2;

   //query->leftRight = sHalfRenderWidth;
   //query->topBottom = sHalfRenderWidth;
   query->ortho = true;

   if(!query->cameraMatrix.isIdentity())
      query->cameraMatrix.identity();

   Point3F pos(sCurrRenderPos.x, sCurrRenderPos.y, mMaxHeight);
   query->cameraMatrix.setPosition(pos);
   query->cameraMatrix.mul(MatrixF(rotation));

   // Return OK.
   return(true);
}

any help in making this do its job will be greatly appreciated, then my rts port to 1.8.1 will be complete and i can share a final product...
#5
03/05/2010 (10:46 pm)
@Greg

you could still help guide the rest of us with your other code changes so we can get a mostly complete port done :)
#6
03/11/2010 (2:16 pm)
@Scooby, if you can give me an upload location I will gladly post the rts c++ source.
#7
04/20/2010 (9:05 pm)
I can create a spot on my site - PM me if you're interested. It wouldn't be a real code repository or anything, but hey....