1
0
forked from 0ad/0ad
0ad/source/graphics/UnitManager.cpp
Matei 0ed2815c8b Added initial version of LOS, and updated minimap to show both LOS and water.
LOS issues still outstanding:
- LOS looks ugly because of quad tesselation into 2 triangles
- Quad tesselation is unspecified by OpenGL (in fact using GL_QUADS on
LOS quads seemed to give different tesselations than it did for the
underlying terrain quads, but terrain rendering also used GL_QUADS).
This should be fixed once we decide on the quad tesselation issue.
- Units with traits.vision.permanent set are visible through FOW even if
you havent seen them before; this should only be true when you have seen
them before. But it gets even more complicated - if a permanent unit
seen through FOW dies or gets upgraded or something, perhaps you should
remember the old version. I'm not completely sure how to do this
(probably involves cloning its actor somehow).

This was SVN commit r2876.
2005-10-09 03:43:03 +00:00

130 lines
3.4 KiB
C++
Executable File

///////////////////////////////////////////////////////////////////////////////
//
// Name: UnitManager.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#include "precompiled.h"
#include "lib/res/res.h"
#include "Model.h"
#include "UnitManager.h"
#include "Unit.h"
#include "CConsole.h"
#include "ObjectManager.h"
#include "ObjectEntry.h"
#include "LOSManager.h"
extern CConsole* g_Console;
#include <algorithm>
///////////////////////////////////////////////////////////////////////////////
// CUnitManager constructor
CUnitManager::CUnitManager()
{
}
///////////////////////////////////////////////////////////////////////////////
// CUnitManager destructor
CUnitManager::~CUnitManager()
{
DeleteAll();
}
///////////////////////////////////////////////////////////////////////////////
// AddUnit: add given unit to world
void CUnitManager::AddUnit(CUnit* unit)
{
m_Units.push_back(unit);
}
///////////////////////////////////////////////////////////////////////////////
// RemoveUnit: remove given unit from world, but don't delete it
void CUnitManager::RemoveUnit(CUnit* unit)
{
// find entry in list
typedef std::vector<CUnit*>::iterator Iter;
Iter i=std::find(m_Units.begin(),m_Units.end(),unit);
if (i!=m_Units.end()) {
m_Units.erase(i);
}
}
///////////////////////////////////////////////////////////////////////////////
// DeleteUnit: remove given unit from world and delete it
void CUnitManager::DeleteUnit(CUnit* unit)
{
RemoveUnit(unit);
delete unit;
}
///////////////////////////////////////////////////////////////////////////////
// DeleteAll: remove and delete all units
void CUnitManager::DeleteAll()
{
uint i;
for (i=0;i<m_Units.size();i++) {
delete m_Units[i];
}
m_Units.clear();
}
///////////////////////////////////////////////////////////////////////////////
// PickUnit: iterate through units testing given ray against bounds of each
// unit; return the closest unit, or null if everything missed
CUnit* CUnitManager::PickUnit(const CVector3D& origin,const CVector3D& dir) const
{
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
// closest object found so far
CUnit* hit = 0;
// distance to closest object found so far
float dist = 1.0e30f;
// closest approach offset (easier to pick small stuff in forests than standard ScEd style selection)
float minrel = 1.0e30f;
for (uint i=0;i<m_Units.size();i++) {
CUnit* unit=m_Units[i];
float tmin,tmax;
if (unit->GetModel()->GetBounds().RayIntersect(origin,dir,tmin,tmax)
&& losMgr->GetUnitStatus(unit, g_Game->GetLocalPlayer()) != UNIT_HIDDEN)
{
// Point of closest approach
CVector3D obj;
unit->GetModel()->GetBounds().GetCentre( obj );
CVector3D delta = obj - origin;
float distance = delta.Dot( dir );
CVector3D closest = origin + dir * distance;
CVector3D offset = obj - closest;
float rel = offset.GetLength();
if (!hit || rel < minrel ) {
hit=unit;
dist=tmin;
minrel = rel;
}
}
}
return hit;
}
///////////////////////////////////////////////////////////////////////////////
// CreateUnit: create a new unit and add it to the world
CUnit* CUnitManager::CreateUnit(CStr& actorName, CEntity* entity)
{
CObjectEntry* obj = g_ObjMan.FindObject(actorName);
if (! obj)
return NULL;
CUnit* unit = new CUnit(obj, obj->m_Model->Clone(), entity);
AddUnit(unit);
return unit;
}