/*========================================================================== * (C) 2006 Universitat Jaume I *========================================================================== * PROYECT: GAME TOOLS *========================================================================== * CONTENT: * * * @file GeoLodManager.cpp *===========================================================================*/ #include "GeoLodManager.h" #include "GeoLodObject.h" namespace Geometry { class lodobj_idpos_node_t { public: lodobj_idpos_node_t(LodObject *o):lodobj(o),must_recalculate_distance(true),dist2cam(0.0f){} LodObject *lodobj; float dist2cam; // used to index the lodobj in the other map bool must_recalculate_distance; bool operator < (const lodobj_idpos_node_t &o) const { return (lodobj->GetUniqueID()GetUniqueID()); } }; } using namespace Geometry; LodManager::LodManager(float near, float far, const Geometry::Vector3 &campos) :targetFPS(30),camera_changed(true),camera_pos(campos), near_range(near),far_range(far) { } void Geometry::LodManager::AddLodObj(LodObject * o, const Geometry::Vector3 &p) { float dist = CalculateDistToCamera(p); lodobj_dists[dist] = lodobj_dist_node_t(o); UpdateLODObjectPos(o,p); } void Geometry::LodManager::UpdateLOD(void) { // recalculate distances if have to if (camera_changed) { // if the camera has changed, recalculate all lodobject distances to it lodobj_dists.clear(); for (std::map::iterator it = lodobj_pos.begin(); it != lodobj_pos.end(); it++) { const lodobj_idpos_node_t & posnode = it->first; const Vector3 & pos = it->second; float newdist = CalculateDistToCamera(pos); lodobj_dists[newdist] = lodobj_dist_node_t(posnode.lodobj); } camera_changed=false; } else { // if any of the objects changed its position, the distance must be recalculated for (std::map::iterator it = lodobj_pos.begin(); it != lodobj_pos.end(); it++) { const lodobj_idpos_node_t & posnode = it->first; if (posnode.must_recalculate_distance) { const Vector3 & pos = it->second; float newdist = CalculateDistToCamera(pos); lodobj_dists[newdist] = lodobj_dist_node_t(posnode.lodobj); /* lodobj_dists.erase(it);*/ } } } // select a tree to change its LOD float random_dist = SelectRandomDistance(); std::map::iterator nearest = lodobj_dists.upper_bound(random_dist); } void Geometry::LodManager::UpdateCamera(const Geometry::Vector3 &p) { camera_pos = p; camera_changed = true; } void Geometry::LodManager::UpdateLODObjectPos(LodObject *o, const Geometry::Vector3 &p) { lodobj_pos[lodobj_idpos_node_t(o)] = p; } float Geometry::LodManager::CalculateDistToCamera(const Geometry::Vector3 &p) const { return camera_pos.dotProduct(p); } float Geometry::LodManager::SelectRandomDistance(void) const { float linear_01 = (float)rand()/(float)RAND_MAX; float exp_01 = linear_01*linear_01; float real_dist = exp_01*near_range + (1.0f-exp_01)*far_range; return real_dist; }