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:
|
---|
20 | lodobj_idpos_node_t(LodObject *o):lodobj(o),must_recalculate_distance(true),dist2cam(0.0f){}
|
---|
21 | LodObject *lodobj;
|
---|
22 | float dist2cam; // used to index the lodobj in the other map
|
---|
23 | bool must_recalculate_distance;
|
---|
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 | {
|
---|
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 | }
|
---|
58 | camera_changed=false;
|
---|
59 | }
|
---|
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);
|
---|
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 | }
|
---|