[1069] | 1 | /*==========================================================================
|
---|
| 2 | * (C) 2006 Universitat Jaume I
|
---|
| 3 | *==========================================================================
|
---|
| 4 | * PROYECT: GAME TOOLS
|
---|
| 5 | *==========================================================================
|
---|
| 6 | * CONTENT:
|
---|
| 7 | *
|
---|
| 8 | *
|
---|
| 9 | * @file GeoLodManager.cpp
|
---|
| 10 | *===========================================================================*/
|
---|
| 11 |
|
---|
| 12 | #include "GeoLodManager.h"
|
---|
| 13 | #include "GeoLodObject.h"
|
---|
| 14 |
|
---|
| 15 | namespace Geometry
|
---|
| 16 | {
|
---|
| 17 | class lodobj_idpos_node_t
|
---|
| 18 | {
|
---|
| 19 | public:
|
---|
[1071] | 20 | lodobj_idpos_node_t(LodObject *o):lodobj(o),must_recalculate_distance(true),dist2cam(0.0f){}
|
---|
[1069] | 21 | LodObject *lodobj;
|
---|
[1071] | 22 | float dist2cam; // used to index the lodobj in the other map
|
---|
| 23 | bool must_recalculate_distance;
|
---|
[1069] | 24 | bool operator < (const lodobj_idpos_node_t &o) const { return (lodobj->GetUniqueID()<o.lodobj->GetUniqueID()); }
|
---|
| 25 | };
|
---|
| 26 | }
|
---|
| 27 |
|
---|
| 28 | using namespace Geometry;
|
---|
| 29 |
|
---|
| 30 | LodManager::LodManager(float near, float far, const Geometry::Vector3 &campos)
|
---|
| 31 | :targetFPS(30),camera_changed(true),camera_pos(campos),
|
---|
| 32 | near_range(near),far_range(far)
|
---|
| 33 | {
|
---|
| 34 | }
|
---|
| 35 |
|
---|
| 36 | void Geometry::LodManager::AddLodObj(LodObject * o, const Geometry::Vector3 &p)
|
---|
| 37 | {
|
---|
| 38 | float dist = CalculateDistToCamera(p);
|
---|
| 39 | lodobj_dists[dist] = lodobj_dist_node_t(o);
|
---|
| 40 | UpdateLODObjectPos(o,p);
|
---|
| 41 | }
|
---|
| 42 |
|
---|
| 43 |
|
---|
| 44 | void Geometry::LodManager::UpdateLOD(void)
|
---|
| 45 | {
|
---|
| 46 | // recalculate distances if have to
|
---|
| 47 | if (camera_changed)
|
---|
| 48 | {
|
---|
[1071] | 49 | // if the camera has changed, recalculate all lodobject distances to it
|
---|
| 50 | lodobj_dists.clear();
|
---|
| 51 | for (std::map<Geometry::lodobj_idpos_node_t,Geometry::Vector3>::iterator it = lodobj_pos.begin(); it != lodobj_pos.end(); it++)
|
---|
| 52 | {
|
---|
| 53 | const lodobj_idpos_node_t & posnode = it->first;
|
---|
| 54 | const Vector3 & pos = it->second;
|
---|
| 55 | float newdist = CalculateDistToCamera(pos);
|
---|
| 56 | lodobj_dists[newdist] = lodobj_dist_node_t(posnode.lodobj);
|
---|
| 57 | }
|
---|
[1069] | 58 | camera_changed=false;
|
---|
| 59 | }
|
---|
[1071] | 60 | else
|
---|
| 61 | {
|
---|
| 62 | // if any of the objects changed its position, the distance must be recalculated
|
---|
| 63 | for (std::map<Geometry::lodobj_idpos_node_t,Geometry::Vector3>::iterator it = lodobj_pos.begin(); it != lodobj_pos.end(); it++)
|
---|
| 64 | {
|
---|
| 65 | const lodobj_idpos_node_t & posnode = it->first;
|
---|
| 66 | if (posnode.must_recalculate_distance)
|
---|
| 67 | {
|
---|
| 68 | const Vector3 & pos = it->second;
|
---|
| 69 | float newdist = CalculateDistToCamera(pos);
|
---|
| 70 | lodobj_dists[newdist] = lodobj_dist_node_t(posnode.lodobj);
|
---|
| 71 | /* lodobj_dists.erase(it);*/
|
---|
| 72 | }
|
---|
| 73 | }
|
---|
| 74 | }
|
---|
| 75 |
|
---|
| 76 | // select a tree to change its LOD
|
---|
| 77 | float random_dist = SelectRandomDistance();
|
---|
| 78 | std::map<float,Geometry::lodobj_dist_node_t>::iterator nearest = lodobj_dists.upper_bound(random_dist);
|
---|
[1069] | 79 | }
|
---|
| 80 |
|
---|
| 81 | void Geometry::LodManager::UpdateCamera(const Geometry::Vector3 &p)
|
---|
| 82 | {
|
---|
| 83 | camera_pos = p;
|
---|
| 84 | camera_changed = true;
|
---|
| 85 | }
|
---|
| 86 |
|
---|
| 87 | void Geometry::LodManager::UpdateLODObjectPos(LodObject *o, const Geometry::Vector3 &p)
|
---|
| 88 | {
|
---|
| 89 | lodobj_pos[lodobj_idpos_node_t(o)] = p;
|
---|
| 90 | }
|
---|
| 91 |
|
---|
| 92 |
|
---|
| 93 | float Geometry::LodManager::CalculateDistToCamera(const Geometry::Vector3 &p) const
|
---|
| 94 | {
|
---|
| 95 | return camera_pos.dotProduct(p);
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | float Geometry::LodManager::SelectRandomDistance(void) const
|
---|
| 99 | {
|
---|
| 100 | float linear_01 = (float)rand()/(float)RAND_MAX;
|
---|
| 101 | float exp_01 = linear_01*linear_01;
|
---|
| 102 | float real_dist = exp_01*near_range + (1.0f-exp_01)*far_range;
|
---|
| 103 | return real_dist;
|
---|
| 104 | }
|
---|