1 #include <GL/glew.h>
2 #include <wrap/gl/space.h>
3 #include <wrap/gl/trimesh.h>
4 #include <wrap/gl/splatting_apss/splatrenderer.h>
5 #include "impostor_definition.h"
6 #include "ocme_definition.h"
7 #include "ocme_extract.h"
8 #include "ocme_disk_loader.h"
9 #include <vcg/space/point4.h>
10
11
12 extern unsigned int generic_bool ;
13 int COff(const int & h);
14
15
DrawCellSel(CellKey & ck,int mode=0)16 void DrawCellSel ( CellKey & ck, int mode = 0 )
17 {
18 vcg::Point3f p = ck.P3f();
19 int lev = ck.h;
20 float stepf = ( lev>0 ) ? ( 1<<lev ) : 1.f/ ( float ) ( 1<< ( -lev ) ) ;
21
22 vcg::Box3f ubox;
23 ubox.min=vcg::Point3f ( -0.5,-0.5,-0.5 );
24 ubox.max=-ubox.min;
25
26
27 vcg::Color4b c;
28 c = c.Scatter ( 255,lev+127 );
29 c.ColorRamp(-10.f, 10.f, lev );
30 c[3] = 127;
31 glColor( c );
32
33 glPushMatrix();
34
35 switch ( mode )
36 {
37 case 0: glTranslatef ( ( p[0]+ 0.5 ) *stepf, ( p[1]+ 0.5 ) *stepf, ( p[2]+ 0.5 ) *stepf );
38 glScalef ( stepf*0.1 ,stepf*0.1 ,stepf*0.1 );
39 vcg::glBoxFlat ( ubox );
40 break;
41 case 1:;
42 case 3: glTranslatef ( ( p[0]+ 0.5 ) *stepf, ( p[1]+ 0.5 ) *stepf, ( p[2]+ 0.5 ) *stepf );
43 glScalef ( stepf ,stepf ,stepf );
44 vcg::glBoxFlat ( ubox );
45 break;
46 case 2: glTranslatef ( ( p[0]+ 0.5 ) *stepf, ( p[1]+ 0.5 ) *stepf, ( p[2]+ 0.5 ) *stepf );
47 glScalef ( stepf*0.1 ,stepf*0.1 ,stepf*0.1 );
48 GLUquadricObj* q = gluNewQuadric();
49 gluSphere ( q,1.0,10,10 );
50 gluDeleteQuadric(q);
51 break;
52 }
53
54 glPopMatrix();
55
56 }
57
InitRender()58 void OCME::InitRender()
59 {
60 renderParams.one_level = false;
61 renderParams.only_impostors = true;
62 renderParams.visitOn = true;
63 renderParams.render_subcells = false;
64 renderParams.level = 0;
65 renderParams.memory_limit_in_core = 500 * (1<<20);
66 renderParams.memory_limit_video = 150 * (1<<20);
67
68 glEnable(GL_COLOR_MATERIAL);
69 glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
70
71 }
72
73
IsToRefineScreenErr(Cell * & c,float & prio)74 bool OCME::IsToRefineScreenErr(Cell * & c, float & prio ){
75 vcg::Point4f pos4;
76 vcg::Point3f pos3;
77 float scale;
78 const CellKey & ck = c->key;
79
80 pos3 = ck.BBox3f().Center();
81 memcpy(&pos4[0],&pos3[0],3*sizeof(float));pos4[3]=1.0;
82
83 scale = pow(mm.Determinant(),1/(float)3.0);
84 pos4 = mm*pos4; // position of cube center in view space
85
86 float dis0 = sqrt( pos4[0]*pos4[0] + pos4[1]*pos4[1]+ pos4[2]*pos4[2]);// distance viewer - center
87 float dis = dis0 - ( ck.BBox3f().Diag()*0.5*scale); // distance viewer - closest point
88
89 vcg::Point4f prj = pm * vcg::Point4f(0,ck.BBox3f().Diag()* scale/2,-dis,1.0);
90
91 float projerr =0.5*vp[2]*prj[1]/prj[3]; // error on screen
92
93 prio = projerr;
94 if(projerr<0) return true;
95 return (projerr > 50.0);
96 }
97
98
IsInFrustum(Cell * c,vcg::Point3f * f,float & dist,bool bsphere_or_bbox)99 bool OCME::IsInFrustum(Cell * c, vcg::Point3f * f, float &dist, bool bsphere_or_bbox ){
100 const vcg::Point3f pos3 = (bsphere_or_bbox)?c->key.BBox3f().Center():c->bbox.bbox3.Center();
101
102 const float radius = ((bsphere_or_bbox)? c->key.BBox3f().Diag():c->bbox.bbox3.Diag())*0.5f;
103
104 vcg::Point3f n_l = ((f[6]-f[0])^(f[4]-f[0])).Normalize();
105 dist = (pos3-f[0])*n_l-radius;
106 if(dist > 0)
107 return false;
108
109 vcg::Point3f n_r = ((f[5]-f[1])^(f[7]-f[1])).Normalize();
110 dist = std::max<float>(dist ,(pos3-f[1])*n_r-radius);
111
112 if(dist > 0)
113 return false;
114
115 vcg::Point3f n_t = ((f[7]-f[3])^(f[6]-f[3])).Normalize();
116 dist = std::max<float>(dist ,(pos3-f[3])*n_t-radius);
117
118 if(dist > 0)
119 return false;
120
121 vcg::Point3f n_b = ((f[4]-f[0])^(f[5]-f[0])).Normalize();
122 dist = std::max<float>(dist ,(pos3-f[1])*n_b-radius);
123
124 if(dist > 0)
125 return false;
126
127 vcg::Point3f n_n = ((f[3]-f[0])^(f[2]-f[0])).Normalize();
128 dist = std::max<float>(dist ,(pos3-f[3])*n_n-radius);
129
130 if(dist > 0)
131 return false;
132
133 vcg::Point3f n_f = ((f[6]-f[5])^(f[7]-f[5])).Normalize();
134 dist = std::max<float>(dist ,(pos3-f[7])*n_f-radius);
135
136 if(dist > 0)
137 return false;
138
139
140 return true;
141 }
142
Visit(std::vector<Cell * > & to_render)143 void OCME::Visit(std::vector<Cell*> & to_render){
144 std::list<Cell*>::iterator ori;
145 for(ori = octree_roots.begin(); ori != octree_roots.end(); ++ori)
146 Visit((*ori)->key, to_render);
147
148 }
Visit(CellKey root,std::vector<Cell * > & to_render)149 void OCME::Visit(CellKey root, std::vector<Cell*> & to_render){
150
151 float _dist;
152 std::vector<Cell*> que;
153 que.push_back(GetCell(root,false));
154 std::vector<CellKey> children;
155 do{
156 Cell * c = que.back();
157 que.pop_back();
158
159 if( IsToRefineScreenErr(c,c->rd->priority) && c->impostor->non_empty_children && IsInFrustum(c,this->frustum,_dist) ){
160 children.clear();
161 Children(c->key,children);
162 for(unsigned int ci = 0; ci < 8 ; ++ci)
163 if(c->impostor->non_empty_children & (1 << ci))// non empty (save a GetCell ..useless..)
164 {
165 Cell * to_add = GetCell(children[ci],false);
166 if(!to_add) continue;
167 que.push_back(to_add);
168 if ( !to_add->IsEmpty())
169 if(!to_add->rd->to_render())
170 {
171 c->rd->to_render = FBool(& to_render_fbool);
172 c->rd->to_render = true;
173 to_render.push_back(to_add);
174 }
175 }
176 }
177 else
178 {
179 if(!c->rd->to_render())
180 {
181 c->rd->to_render = FBool(& to_render_fbool);
182 c->rd->to_render = true;
183 to_render.push_back(c);
184 }
185 }
186 } while (!que.empty());
187 }
188
189
ConvertFrustumView2World(vcg::Point4f * fv,vcg::Point3f * fw)190 void OCME::ConvertFrustumView2World(vcg::Point4f * fv,vcg::Point3f * fw){
191 vcg::Point4f p4;
192 vcg::Matrix44f mm_inv,pm_inv;
193 mm_inv = vcg::Inverse(mm);
194 pm_inv = vcg::Inverse(pm);
195
196 // bring the canonical view frustum in world space
197 for(int i = 0 ; i < 8; ++i){
198 p4 = (mm_inv * pm_inv * fv[i]).HomoNormalize() ;
199 memcpy( &fw[i][0], &p4[0], sizeof(float) * 3);
200 }
201 }
202
Select(std::vector<Cell * > & selected)203 void OCME::Select(std::vector<Cell*> & selected){
204 RAssert(MemDbg::CheckHeap(1));
205 /* get the viewing parameters */
206 glGetFloatv(GL_MODELVIEW_MATRIX,&mm[0][0]);
207 vcg::Transpose(mm);
208
209 glGetFloatv(GL_PROJECTION_MATRIX,&pm[0][0]);
210 vcg::Transpose(pm);
211
212 glGetIntegerv(GL_VIEWPORT,&vp[0]);
213 ConvertFrustumView2World(this->sel_corners,this->sel_frustum);
214
215 std::vector<std::pair<float,Cell*> > selected_dist;
216 float dist;
217 for(unsigned int i = 0; i < cells_to_render.size(); ++i)
218 if(IsInFrustum(cells_to_render[i],sel_frustum,dist,false))
219 selected_dist.push_back(make_pair<float,Cell*>(dist,cells_to_render[i]));
220 std::sort(selected_dist.begin(),selected_dist.end());
221 for(unsigned int i = 0; i < selected_dist.size();++i)
222 selected.push_back(selected_dist[i].second);
223 }
DeSelect(std::vector<Cell * > & selected)224 void OCME::DeSelect(std::vector<Cell*> & selected){
225 }
226
Render(int impostorRenderMode)227 void OCME::Render(int impostorRenderMode){
228 bool useSplatting = (impostorRenderMode==0);
229 bool useBox = (impostorRenderMode==2);
230
231 render_mutex.lock();
232 RAssert(MemDbg::CheckHeap(1));
233
234 vcg::Color4b c;
235
236
237 /* increase mark */
238 ++to_render_fbool;
239
240 /* get the viewing paramters */
241 glGetFloatv(GL_MODELVIEW_MATRIX,&mm[0][0]);
242 vcg::Transpose(mm);
243
244 glGetFloatv(GL_PROJECTION_MATRIX,&pm[0][0]);
245 vcg::Transpose(pm);
246
247 glGetIntegerv(GL_VIEWPORT,&vp[0]);
248
249 /* update the frustum in world space */
250 ConvertFrustumView2World(corners,this->frustum);
251
252 if(renderParams.visitOn){
253 cells_to_render.clear();
254 Visit(cells_to_render);
255 }
256 RAssert(MemDbg::CheckHeap(1));
257
258 if(!renderParams.only_impostors){
259 for(unsigned int i = 0; i < cells_to_render.size(); ++i)
260 if(cells_to_render[i]->face->Size())
261 NeedCell(cells_to_render[i]);
262
263 stat.cells_to_render = cells_to_render.size();
264
265 }
266
267 RAssert(MemDbg::CheckHeap(1));
268 ::RemoveDuplicates(cells_to_render);
269 std::vector<Impostor*> impostor_to_render;
270 std::vector< std::vector<vcg::Point3f> * > positions;
271 std::vector< std::vector<vcg::Point3f> * > normals;
272 std::vector< std::vector<vcg::Point3<unsigned char> > * > colors;
273 std::vector<float> radiuses;
274
275 for(unsigned int i = 0; i < cells_to_render.size(); ++i)
276 if(!cells_to_render[i]->generic_bool())
277 { // generic_bool() == the cell is taken in editing
278 if(cells_to_render[i]->rd->renderCacheToken && cells_to_render[i]->rd->renderCacheToken->lock() )
279 {
280 // c = c.Scatter ( 32,COff(cells_to_render[i]->key.h) );
281 //glColor ( c );
282
283 default_renderer.m = &cells_to_render[i]->rd->Mesh();
284
285 if(vcg::tri::HasPerVertexColor(cells_to_render[i]->rd->Mesh()))
286 // default_renderer.Draw<vcg::GLW::DMPoints , vcg::GLW::CMPerVert, vcg::GLW::TMNone>();
287 default_renderer.Draw<vcg::GLW::DMFlat , vcg::GLW::CMPerVert, vcg::GLW::TMNone>();
288 // default_renderer.DrawPointsBase<vcg::GLW::NMPerVert,vcg::GLW::CMPerVert>();
289 else
290 // default_renderer.Draw<vcg::GLW::DMPoints,vcg::GLW::CMLast,vcg::GLW::TMNone>();
291 default_renderer.Draw<vcg::GLW::DMFlat,vcg::GLW::CMNone,vcg::GLW::TMNone>();
292
293 cells_to_render[i]->rd->renderCacheToken->unlock();
294 }
295 else
296 {
297 if(!useSplatting){
298 if(useBox)
299 DrawCellSel(cells_to_render[i]->key,3);
300 else
301 cells_to_render[i]->impostor->Render( 0);
302 }
303 else{
304 // impostor_to_render.push_back(cells_to_render[i]->impostor);
305 positions.push_back(&cells_to_render[i]->impostor->positionsV);
306 normals.push_back(&cells_to_render[i]->impostor->normalsV);
307 colors.push_back(&cells_to_render[i]->impostor->colorsV);
308 radiuses.push_back( CS( cells_to_render[i]->key.h)/Impostor::Gridsize());
309 }
310 }
311 }
312
313 //for(std::vector<Impostor * > :: iterator i =impostor_to_render.begin(); i != impostor_to_render.end();++i)
314 // (*i)->Render(this->renderParams.render_subcells);
315 if(useSplatting)
316 {
317 glPushAttrib(GL_ALL_ATTRIB_BITS);
318 splat_renderer.Render(positions,normals,colors,radiuses,vcg::GLW::CMPerMesh,
319 vcg::GLW::TMNone);
320 glPopAttrib();
321 }
322
323 renderCache.controller.updatePriorities();
324
325 render_mutex.unlock();
326 }
327
328
NeedCell(Cell * c)329 void OCME::NeedCell(Cell * c){
330 this->renderCache.Req(c,c->rd->priority);
331 }
332
StopAndFlushRendering()333 void OCME::StopAndFlushRendering(){
334 render_mutex.lock();
335 this->cells_to_render.clear();
336 this->renderCache.controller.pause();
337 }
StartRendering()338 void OCME::StartRendering(){
339 render_mutex.unlock();
340 }
341