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 | #include <algorithm>
|
---|
15 | /*
|
---|
16 | namespace Geometry
|
---|
17 | {
|
---|
18 |
|
---|
19 |
|
---|
20 | class lodobj_idpos_node_t
|
---|
21 | {
|
---|
22 | public:
|
---|
23 | lodobj_idpos_node_t(LodObject *o):lodobj(o),must_recalculate_distance(true),dist2cam(0.0f){}
|
---|
24 | LodObject *lodobj;
|
---|
25 | float dist2cam; // used to index the lodobj in the other map
|
---|
26 | bool operator < (const lodobj_idpos_node_t &o) const { return (lodobj->GetUniqueID()<o.lodobj->GetUniqueID()); }
|
---|
27 | };
|
---|
28 | }*/
|
---|
29 |
|
---|
30 | using namespace Geometry;
|
---|
31 |
|
---|
32 | LodManager::LodManager(float near, float far, const Geometry::Vector3 &campos)
|
---|
33 | :targetFPS(30),camera_changed(true),camera_pos(campos),
|
---|
34 | near_range(near),far_range(far)
|
---|
35 | {
|
---|
36 | // make the lodobj_dists vector into a heap
|
---|
37 | make_heap(lodobj_dists.begin(),lodobj_dists.end());
|
---|
38 | }
|
---|
39 |
|
---|
40 | void Geometry::LodManager::AddLodObj(LodObject * o, const Geometry::Vector3 &p)
|
---|
41 | {
|
---|
42 | float dist = CalculateDistToCamera(p);
|
---|
43 | lodobj_dists.push_back(lodobj_dist_node_t(dist,o));
|
---|
44 | push_heap(lodobj_dists.begin(),lodobj_dists.end());
|
---|
45 | // lodobj_dists[dist] = lodobj_dist_node_t(o);
|
---|
46 | UpdateLODObjectPos(o,p);
|
---|
47 | }
|
---|
48 |
|
---|
49 |
|
---|
50 | void Geometry::LodManager::UpdateLOD(void)
|
---|
51 | {
|
---|
52 | if (!lodobj_dists.empty())
|
---|
53 | {
|
---|
54 | // update distances to the camera
|
---|
55 | bool must_resort = false;
|
---|
56 | for (std::vector<lodobj_dist_node_t>::iterator it=lodobj_dists.begin(); it!=lodobj_dists.end(); it++)
|
---|
57 | {
|
---|
58 | lodobj_dist_node_t & node = *it;
|
---|
59 | if (camera_changed || node.must_recalculate_distance)
|
---|
60 | {
|
---|
61 | RecalculateDist(node);
|
---|
62 | must_resort=true;
|
---|
63 | }
|
---|
64 | }
|
---|
65 | if (must_resort)
|
---|
66 | sort_heap(lodobj_dists.begin(),lodobj_dists.end());
|
---|
67 |
|
---|
68 | // select a tree to change its LOD
|
---|
69 | // float random_dist = SelectRandomDistance();
|
---|
70 | // std::map<float,Geometry::lodobj_dist_node_t>::iterator nearest = lodobj_dists.upper_bound(random_dist);
|
---|
71 |
|
---|
72 | // the begining of the list is the greater element (greater dist)
|
---|
73 | lodobj_dist_node_t & node = lodobj_dists.front();
|
---|
74 | }
|
---|
75 | camera_changed=false;
|
---|
76 | }
|
---|
77 |
|
---|
78 | void Geometry::LodManager::RecalculateDist(lodobj_dist_node_t & node)
|
---|
79 | {
|
---|
80 | std::map<uint32,Vector3>::iterator posit = lodobj_pos.find(node.lodobj->GetUniqueID());
|
---|
81 | assert(posit!=lodobj_pos.end());
|
---|
82 | const Vector3 & pos = posit->second;
|
---|
83 |
|
---|
84 | node.dist2cam = CalculateDistToCamera(pos);
|
---|
85 | }
|
---|
86 |
|
---|
87 |
|
---|
88 | void Geometry::LodManager::UpdateCamera(const Geometry::Vector3 &p)
|
---|
89 | {
|
---|
90 | camera_pos = p;
|
---|
91 | camera_changed = true;
|
---|
92 | }
|
---|
93 |
|
---|
94 | void Geometry::LodManager::UpdateLODObjectPos(LodObject *o, const Geometry::Vector3 &p)
|
---|
95 | {
|
---|
96 | lodobj_pos[o->GetUniqueID()] = p;
|
---|
97 | }
|
---|
98 |
|
---|
99 |
|
---|
100 | float Geometry::LodManager::CalculateDistToCamera(const Geometry::Vector3 &p) const
|
---|
101 | {
|
---|
102 | return camera_pos.dotProduct(p);
|
---|
103 | }
|
---|
104 |
|
---|
105 | float Geometry::LodManager::SelectRandomDistance(void) const
|
---|
106 | {
|
---|
107 | float linear_01 = (float)rand()/(float)RAND_MAX;
|
---|
108 | float exp_01 = linear_01*linear_01;
|
---|
109 | float real_dist = exp_01*near_range + (1.0f-exp_01)*far_range;
|
---|
110 | return real_dist;
|
---|
111 | }
|
---|