1
1
forked from 0ad/0ad

g_YMinOffset declared in gameview.h instead of extern elsewhere

terrain: made const-correct
lib: Add round_up_to_pow2
minimap: cleanup. split user input and DrawViewRect out of Draw; add
m_Camera; made pointers const; user local x,x2 variables instead of
writing out m_CachedActualSize

This was SVN commit r2970.
This commit is contained in:
janwas 2005-10-19 17:16:34 +00:00
parent a953a8ef57
commit 364e36128e
7 changed files with 186 additions and 168 deletions

View File

@ -1,6 +1,11 @@
#ifndef _GameView_H
#define _GameView_H
// needed by minimap
extern float g_MaxZoomHeight; //note: Max terrain height is this minus YMinOffset
extern float g_YMinOffset;
#include "Camera.h"
#include "Vector3D.h"

View File

@ -72,7 +72,7 @@ bool CTerrain::Initialize(u32 size,const u16* data)
///////////////////////////////////////////////////////////////////////////////
// CalcPosition: calculate the world space position of the vertex at (i,j)
void CTerrain::CalcPosition(i32 i, i32 j, CVector3D& pos)
void CTerrain::CalcPosition(i32 i, i32 j, CVector3D& pos) const
{
u16 height;
if ((u32)i < m_MapSize && (u32)j < m_MapSize) // will reject negative coordinates
@ -87,7 +87,7 @@ void CTerrain::CalcPosition(i32 i, i32 j, CVector3D& pos)
///////////////////////////////////////////////////////////////////////////////
// CalcFromPosition: calculate the vertex underneath the world space position
void CTerrain::CalcFromPosition(const CVector3D& pos, i32& i, i32& j)
void CTerrain::CalcFromPosition(const CVector3D& pos, i32& i, i32& j) const
{
i = pos.X / CELL_SIZE;
j = pos.Z / CELL_SIZE;
@ -96,7 +96,7 @@ void CTerrain::CalcFromPosition(const CVector3D& pos, i32& i, i32& j)
///////////////////////////////////////////////////////////////////////////////
// CalcNormal: calculate the world space normal of the vertex at (i,j)
void CTerrain::CalcNormal(u32 i, u32 j, CVector3D& normal)
void CTerrain::CalcNormal(u32 i, u32 j, CVector3D& normal) const
{
CVector3D left, right, up, down;
@ -144,7 +144,7 @@ void CTerrain::CalcNormal(u32 i, u32 j, CVector3D& normal)
///////////////////////////////////////////////////////////////////////////////
// GetPatch: return the patch at (x,z) in patch space, or null if the patch is
// out of bounds
CPatch* CTerrain::GetPatch(i32 x, i32 z)
CPatch* CTerrain::GetPatch(i32 x, i32 z) const
{
if (x<0 || x>=i32(m_MapSizePatches)) return 0;
if (z<0 || z>=i32(m_MapSizePatches)) return 0;
@ -155,7 +155,7 @@ CPatch* CTerrain::GetPatch(i32 x, i32 z)
///////////////////////////////////////////////////////////////////////////////
// GetPatch: return the tile at (x,z) in tile space, or null if the tile is out
// of bounds
CMiniPatch* CTerrain::GetTile(i32 x, i32 z)
CMiniPatch* CTerrain::GetTile(i32 x, i32 z) const
{
if (x<0 || x>=i32(m_MapSize)-1) return 0;
if (z<0 || z>=i32(m_MapSize)-1) return 0;

View File

@ -26,9 +26,9 @@ public:
bool Initialize(u32 size,const u16* ptr);
// return number of vertices along edge of the terrain
u32 GetVerticesPerSide() { return m_MapSize; }
u32 GetVerticesPerSide() const { return m_MapSize; }
// return number of patches along edge of the terrain
u32 GetPatchesPerSide() { return m_MapSizePatches; }
u32 GetPatchesPerSide() const { return m_MapSizePatches; }
inline bool isOnMap( float x, float y ) const
{
@ -52,17 +52,17 @@ public:
// get patch at given coordinates, expressed in patch-space; return 0 if
// coordinates represent patch off the edge of the map
CPatch* GetPatch(i32 x, i32 z);
CPatch* GetPatch(i32 x, i32 z) const;
// get tile at given coordinates, expressed in tile-space; return 0 if
// coordinates represent tile off the edge of the map
CMiniPatch* GetTile(i32 x, i32 z);
CMiniPatch* GetTile(i32 x, i32 z) const;
// calculate the position of a given vertex
void CalcPosition(i32 i, i32 j, CVector3D& pos);
void CalcPosition(i32 i, i32 j, CVector3D& pos) const;
// calculate the vertex under a given position (rounding down coordinates)
void CalcFromPosition(const CVector3D& pos, i32& i, i32& j);
void CalcFromPosition(const CVector3D& pos, i32& i, i32& j) const;
// calculate the normal at a given vertex
void CalcNormal(u32 i, u32 j, CVector3D& normal);
void CalcNormal(u32 i, u32 j, CVector3D& normal) const;
// flatten out an area of terrain (specified in world space coords); return
// the average height of the flattened area

View File

@ -17,12 +17,9 @@
#include "Profile.h"
#include "LOSManager.h"
#include "ps/Globals.h"
#include "graphics/GameView.h"
extern float g_MaxZoomHeight, g_YMinOffset;
bool HasClicked=false;
bool g_TerrainModified = false;
static unsigned int ScaleColor(unsigned int color, float x)
@ -33,16 +30,6 @@ static unsigned int ScaleColor(unsigned int color, float x)
return (0xff000000 | r | g<<8 | b<<16);
}
static int RoundUpToPowerOf2(int x)
{
if ((x & (x-1))==0) return x;
int d=x;
while (d & (d-1)) {
d&=(d-1);
}
return d<<1;
}
CMiniMap::CMiniMap()
: m_TerrainTexture(0), m_TerrainData(0), m_MapSize(0), m_Terrain(0),
m_LOSTexture(0), m_LOSData(0), m_UnitManager(0)
@ -57,20 +44,129 @@ CMiniMap::~CMiniMap()
Destroy();
}
void CMiniMap::ProcessUserInput()
{
//================================================================
//INTERACTIVE MINIMAP STARTS
//Have questions on ^. Send email to ajdecker1022@msn.com
static bool HasClicked=false; // HACK
//Check for a click
if(g_mouse_buttons[SDL_BUTTON_LEFT]==true)
{
HasClicked=true;
}
//Check to see if left button is false (meaning it's been lifted)
if (g_mouse_buttons[SDL_BUTTON_LEFT]==false && HasClicked==true)
{
//Is cursor inside Minimap boundaries?
if(g_mouse_x > m_CachedActualSize.left && g_mouse_x < m_CachedActualSize.right
&& g_mouse_y > m_CachedActualSize.top && g_mouse_y < m_CachedActualSize.bottom)
{
CTerrain *MMTerrain=g_Game->GetWorld()->GetTerrain();
CVector3D CamOrient=m_Camera->m_Orientation.GetTranslation();
//get center point of screen
int x = (int)g_Renderer.GetWidth()/2.f, y = (int)g_Renderer.GetHeight()/2.f;
CVector3D ScreenMiddle=m_Camera->GetWorldCoordinates(x,y);
//Get Vector required to go from camera position to ScreenMiddle
CVector3D TransVector;
TransVector.X=CamOrient.X-ScreenMiddle.X;
TransVector.Z=CamOrient.Z-ScreenMiddle.Z;
//world position of where mouse clicked
CVector3D Destination;
//X and Z according to proportion of mouse position and minimap
Destination.X=(CELL_SIZE*m_MapSize)*
((g_mouse_x-m_CachedActualSize.left)/m_CachedActualSize.GetWidth());
Destination.Z=(CELL_SIZE*m_MapSize)*((m_CachedActualSize.bottom-g_mouse_y)
/m_CachedActualSize.GetHeight());
m_Camera->m_Orientation._14=Destination.X;
m_Camera->m_Orientation._34=Destination.Z;
m_Camera->m_Orientation._14+=TransVector.X;
m_Camera->m_Orientation._34+=TransVector.Z;
//Lock Y coord. No risk of zoom exceeding limit-Y does not increase
float Height=MMTerrain->getExactGroundLevel(
m_Camera->m_Orientation._14, m_Camera->m_Orientation._34) + g_YMinOffset;
if (m_Camera->m_Orientation._24 < Height)
{
m_Camera->m_Orientation._24=Height;
}
m_Camera->UpdateFrustum();
}
HasClicked=false;
}
//END OF INTERACTIVE MINIMAP
//====================================================================
}
// render view rect : John M. Mena
// This sets up and draws the rectangle on the mini-map
// which represents the view of the camera in the world.
void CMiniMap::DrawViewRect()
{
// Get correct world coordinates based off corner of screen start
// at Bottom Left and going CW
CVector3D hitPt[4];
hitPt[0]=m_Camera->GetWorldCoordinates(0,g_Renderer.GetHeight());
hitPt[1]=m_Camera->GetWorldCoordinates(g_Renderer.GetWidth(),g_Renderer.GetHeight());
hitPt[2]=m_Camera->GetWorldCoordinates(g_Renderer.GetWidth(),0);
hitPt[3]=m_Camera->GetWorldCoordinates(0,0);
float ViewRect[4][2];
for (int i=0;i<4;i++) {
// convert to minimap space
float px=hitPt[i].X;
float pz=hitPt[i].Z;
ViewRect[i][0]=(m_CachedActualSize.GetWidth()*px/float(CELL_SIZE*m_MapSize));
ViewRect[i][1]=(m_CachedActualSize.GetHeight()*pz/float(CELL_SIZE*m_MapSize));
}
// Enable Scissoring as to restrict the rectangle
// to only the mini-map below by retrieving the mini-maps
// screen coords.
glScissor((int)m_CachedActualSize.left, 0, (int)m_CachedActualSize.right, (int)m_CachedActualSize.GetHeight());
glEnable(GL_SCISSOR_TEST);
glEnable(GL_LINE_SMOOTH);
glLineWidth(2);
glColor3f(1.0f, 0.3f, 0.3f);
// Draw the viewing rectangle with the ScEd's conversion algorithm
const float x = m_CachedActualSize.left, y = m_CachedActualSize.bottom;
glBegin(GL_LINE_LOOP);
glVertex2f(x+ViewRect[0][0], y-ViewRect[0][1]);
glVertex2f(x+ViewRect[1][0], y-ViewRect[1][1]);
glVertex2f(x+ViewRect[2][0], y-ViewRect[2][1]);
glVertex2f(x+ViewRect[3][0], y-ViewRect[3][1]);
glEnd();
// restore state
glDisable(GL_SCISSOR_TEST);
glDisable(GL_POINT_SMOOTH);
glLineWidth(1.0f);
}
void CMiniMap::Draw()
{
// The terrain isn't actually initialized until the map is loaded, which
// happens when the game is started
// happens when the game is started, so abort until then.
if(!(GetGUI() && g_Game && g_Game->IsGameStarted()))
return;
// Set our globals in case they hadn't been set before
m_Terrain = g_Game->GetWorld()->GetTerrain();
m_Camera = g_Game->GetView()->GetCamera();
m_Terrain = g_Game->GetWorld()->GetTerrain();
m_UnitManager = g_Game->GetWorld()->GetUnitManager();
m_Width = (u32)(m_CachedActualSize.right - m_CachedActualSize.left);
m_Width = (u32)(m_CachedActualSize.right - m_CachedActualSize.left);
m_Height = (u32)(m_CachedActualSize.bottom - m_CachedActualSize.top);
m_MapSize = m_Terrain->GetVerticesPerSide();
m_TextureSize = RoundUpToPowerOf2(m_MapSize);
m_TextureSize = round_up_to_pow2(m_MapSize);
if(!m_TerrainTexture)
CreateTextures();
@ -80,28 +176,28 @@ void CMiniMap::Draw()
RebuildLOSTexture();
float texCoordMax = ((float)m_MapSize - 1) / ((float)m_TextureSize);
float z = GetBufferedZ();
const float texCoordMax = ((float)m_MapSize - 1) / ((float)m_TextureSize);
const float x = m_CachedActualSize.left, y = m_CachedActualSize.bottom;
const float x2 = m_CachedActualSize.right, y2 = m_CachedActualSize.top;
const float z = GetBufferedZ();
// Draw the main textured quad
g_Renderer.BindTexture(0, m_TerrainTexture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(m_CachedActualSize.left, m_CachedActualSize.bottom, z);
glVertex3f(x, y, z);
glTexCoord2f(texCoordMax, 0.0f);
glVertex3f(m_CachedActualSize.right, m_CachedActualSize.bottom, z);
glVertex3f(x2, y, z);
glTexCoord2f(texCoordMax, texCoordMax);
glVertex3f(m_CachedActualSize.right, m_CachedActualSize.top, z);
glVertex3f(x2, y2, z);
glTexCoord2f(0.0f, texCoordMax);
glVertex3f(m_CachedActualSize.left, m_CachedActualSize.top, z);
glVertex3f(x, y2, z);
glEnd();
// Draw the LOS quad in black, using alpha values from the LOS texture
g_Renderer.BindTexture(0, m_LOSTexture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
@ -117,27 +213,22 @@ void CMiniMap::Draw()
glBegin(GL_QUADS);
glColor3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(m_CachedActualSize.left, m_CachedActualSize.bottom, z);
glVertex3f(x, y, z);
glTexCoord2f(texCoordMax, 0.0f);
glVertex3f(m_CachedActualSize.right, m_CachedActualSize.bottom, z);
glVertex3f(x2, y, z);
glTexCoord2f(texCoordMax, texCoordMax);
glVertex3f(m_CachedActualSize.right, m_CachedActualSize.top, z);
glVertex3f(x2, y2, z);
glTexCoord2f(0.0f, texCoordMax);
glVertex3f(m_CachedActualSize.left, m_CachedActualSize.top, z);
glVertex3f(x, y2, z);
glEnd();
glDisable(GL_BLEND);
// Draw unit points
float x = m_CachedActualSize.left;
float y = m_CachedActualSize.bottom;
const std::vector<CUnit *> &units = m_UnitManager->GetUnits();
std::vector<CUnit *>::const_iterator iter = units.begin();
CUnit *unit = 0;
CVector2D pos;
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
glDisable(GL_DEPTH_TEST);
glEnable(GL_POINT_SMOOTH);
glDisable(GL_TEXTURE_2D);
@ -167,130 +258,18 @@ void CMiniMap::Draw()
glVertex3f(x + pos.x, y - pos.y, z);
}
}
glEnd();
//================================================================
//INTERACTIVE MINIMAP STARTS
//Have questions on ^. Send email to ajdecker1022@msn.com
// JW: this really doesn't belong here.. tying us to the real GUI
// input mechanism is pending.
ProcessUserInput();
//Get Camera handle
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
DrawViewRect();
//Check for a click
if(g_mouse_buttons[SDL_BUTTON_LEFT]==true)
{
HasClicked=true;
}
//Check to see if left button is false (meaning it's been lifted)
if (g_mouse_buttons[SDL_BUTTON_LEFT]==false && HasClicked==true)
{
//Is cursor inside Minimap boundaries?
if(g_mouse_x > m_CachedActualSize.left && g_mouse_x < m_CachedActualSize.right
&& g_mouse_y > m_CachedActualSize.top && g_mouse_y < m_CachedActualSize.bottom)
{
CTerrain *MMTerrain=g_Game->GetWorld()->GetTerrain();
CVector3D CamOrient=g_Camera.m_Orientation.GetTranslation();
//get center point of screen
CVector3D ScreenMiddle=g_Camera.GetWorldCoordinates(
g_Renderer.GetWidth()/2,g_Renderer.GetHeight()/2);
//Get Vector required to go from camera position to ScreenMiddle
CVector3D TransVector;
TransVector.X=CamOrient.X-ScreenMiddle.X;
TransVector.Z=CamOrient.Z-ScreenMiddle.Z;
//world position of where mouse clicked
CVector3D Destination;
//X and Z according to proportion of mouse position and minimap
Destination.X=(CELL_SIZE*m_MapSize)*
((g_mouse_x-m_CachedActualSize.left)/m_CachedActualSize.GetWidth());
Destination.Z=(CELL_SIZE*m_MapSize)*((m_CachedActualSize.bottom-g_mouse_y)
/m_CachedActualSize.GetHeight());
g_Camera.m_Orientation._14=Destination.X;
g_Camera.m_Orientation._34=Destination.Z;
g_Camera.m_Orientation._14+=TransVector.X;
g_Camera.m_Orientation._34+=TransVector.Z;
//Lock Y coord. No risk of zoom exceeding limit-Y does not increase
float Height=MMTerrain->getExactGroundLevel(
g_Camera.m_Orientation._14, g_Camera.m_Orientation._34) + g_YMinOffset;
if (g_Camera.m_Orientation._24 < Height)
{
g_Camera.m_Orientation._24=Height;
}
g_Camera.UpdateFrustum();
}
HasClicked=false;
}
//END OF INTERACTIVE MINIMAP
//====================================================================
// render view rect : John M. Mena
// This sets up and draws the rectangle on the mini-map
// which represents the view of the camera in the world.
// Get a handle to the camera
//Get correct world coordinates based off corner of screen start
//at Bottom Left and going CW
CVector3D hitPt[4];
hitPt[0]=g_Camera.GetWorldCoordinates(0,g_Renderer.GetHeight());
hitPt[1]=g_Camera.GetWorldCoordinates(g_Renderer.GetWidth(),g_Renderer.GetHeight());
hitPt[2]=g_Camera.GetWorldCoordinates(g_Renderer.GetWidth(),0);
hitPt[3]=g_Camera.GetWorldCoordinates(0,0);
float ViewRect[4][2];
for (int i=0;i<4;i++) {
// convert to minimap space
float px=hitPt[i].X;
float pz=hitPt[i].Z;
ViewRect[i][0]=(m_CachedActualSize.GetWidth()*px/float(CELL_SIZE*m_MapSize));
ViewRect[i][1]=(m_CachedActualSize.GetHeight()*pz/float(CELL_SIZE*m_MapSize));
}
// Enable Scissoring as to restrict the rectangle
// to only the mini-map below by retrieving the mini-maps
// screen coords.
glScissor((int)m_CachedActualSize.left, 0, (int)m_CachedActualSize.right, (int)m_CachedActualSize.GetHeight());
glEnable(GL_SCISSOR_TEST);
glEnable(GL_LINE_SMOOTH);
glLineWidth(2);
glColor3f(1.0f, 0.3f, 0.3f);
// Draw the viewing rectangle with the ScEd's conversion algorithm
glBegin(GL_LINE_LOOP);
glVertex2f(x+ViewRect[0][0], y-ViewRect[0][1]);
glVertex2f(x+ViewRect[1][0], y-ViewRect[1][1]);
glVertex2f(x+ViewRect[2][0], y-ViewRect[2][1]);
glVertex2f(x+ViewRect[3][0], y-ViewRect[3][1]);
glEnd();
glDisable(GL_SCISSOR_TEST);
// Reset everything back to normal
glPointSize(1.0f);
glDisable(GL_LINE_SMOOTH);
glLineWidth(1.0f);
glEnable(GL_TEXTURE_2D);
glDisable(GL_POINT_SMOOTH);
glEnable(GL_DEPTH_TEST);
}
@ -323,9 +302,12 @@ void CMiniMap::CreateTextures()
RebuildLOSTexture();
}
TIMER_ADD_CLIENT(tc_minimap_rebuildterrain);
void CMiniMap::RebuildTerrainTexture()
{
PROFILE_START("rebuild minimap: terrain");
TIMER_ACCRUE(tc_minimap_rebuildterrain);
u32 x = 0;
u32 y = 0;
@ -377,9 +359,12 @@ void CMiniMap::RebuildTerrainTexture()
PROFILE_END("rebuild minimap: terrain");
}
TIMER_ADD_CLIENT(tc_minimap_rebuildlos);
void CMiniMap::RebuildLOSTexture()
{
PROFILE_START("rebuild minimap: los");
TIMER_ACCRUE(tc_minimap_rebuildlos);
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
CPlayer* player = g_Game->GetLocalPlayer();
@ -437,6 +422,8 @@ void CMiniMap::Destroy()
}
}
TIMER_ADD_CLIENT(tc_minimap_getmapspacecoords);
/*
* Calefaction
* TODO: Speed this up. There has to be some mathematical way to make
@ -444,6 +431,8 @@ void CMiniMap::Destroy()
*/
CVector2D CMiniMap::GetMapSpaceCoords(CVector3D worldPos)
{
TIMER_ACCRUE(tc_minimap_getmapspacecoords);
u32 x = (u32)(worldPos.X / CELL_SIZE);
// Entity's Z coordinate is really its longitudinal coordinate on the terrain
u32 y = (u32)(worldPos.Z / CELL_SIZE);

View File

@ -1,9 +1,10 @@
#ifndef __H_MINIMAP_H__
#define __H_MINIMAP_H__
#include "GUI.h"
#include "Vector2D.h"
#include "Vector3D.h"
#include "gui/GUI.h"
#include "ps/Vector2D.h"
#include "maths/Vector3D.h"
#include "graphics/Camera.h"
class CTerrain;
class CUnitManager;
@ -36,11 +37,14 @@ protected:
CVector2D GetMapSpaceCoords(CVector3D worldPos);
// the terrain we are mini-mapping
CTerrain *m_Terrain;
const CTerrain* m_Terrain;
// the unit manager with unit positions
CUnitManager *m_UnitManager;
const CUnitManager* m_UnitManager;
// not const: camera is moved by clicking on minimap
CCamera* m_Camera;
// minimap texture handles
u32 m_TerrainTexture;
u32 m_LOSTexture;
@ -60,6 +64,9 @@ protected:
// texture size
u32 m_TextureSize;
void DrawViewRect(); // split out of Draw
void ProcessUserInput();
};
#endif

View File

@ -204,6 +204,21 @@ uint log2(uint x)
}
cassert(sizeof(int)*CHAR_BIT == 32); // otherwise change round_up_to_pow2
uint round_up_to_pow2(uint x)
{
// fold upper bit into lower bits; leaves same MSB set but
// everything below it 1. adding 1 yields next POT.
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x+1;
}
int ilog2(const float x)
{
const u32 i = *(u32*)&x;

View File

@ -426,6 +426,8 @@ extern int ilog2(uint n);
// return log base 2, rounded up.
extern uint log2(uint x);
extern uint round_up_to_pow2(uint x);
// multiple must be a power of two.
extern uintptr_t round_up(uintptr_t val, uintptr_t multiple);