1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
47 #include "OSGConfig.h"
48 #include "OSGBaseFunctions.h"
49 #include "OSGTriangleIterator.h"
50 #include "OSGTileGeometryLoad.h"
54 /** \class OSG::TileGeometryLoad
56 * \brief TileGeometryLoad holds the load caused by geometry rendering
60 /*-------------------------------------------------------------------------*/
66 TileGeometryLoad::TileGeometryLoad(UInt32 nodeId
,
67 bool useFaceDistribution
):
71 _faceDistribution ( ),
75 _useFaceDistribution(useFaceDistribution
),
79 if(_directions
.size()==0)
81 // create directions for face distribution
82 _directions
.push_back(
83 Plane(Vec3f( 1, 0, 0) ,Pnt3f(0,0,0)));
84 _directions
.push_back(
85 Plane(Vec3f( 0, 1, 0) ,Pnt3f(0,0,0)));
86 _directions
.push_back(
87 Plane(Vec3f( 0, 0, 1) ,Pnt3f(0,0,0)));
89 _directions
.push_back(
90 Plane(Vec3f( 1, 1, 1)*(1/osgSqrt(3.0f
)),Pnt3f(0,0,0)));
91 _directions
.push_back(
92 Plane(Vec3f(-1, 1, 1)*(1/osgSqrt(3.0f
)),Pnt3f(1,0,0)));
93 _directions
.push_back(
94 Plane(Vec3f( 1,-1, 1)*(1/osgSqrt(3.0f
)),Pnt3f(0,1,0)));
95 _directions
.push_back(
96 Plane(Vec3f( 1, 1,-1)*(1/osgSqrt(3.0f
)),Pnt3f(0,0,1)));
98 _directions
.push_back(
99 Plane(Vec3f( 1, 1, 0)*(1/osgSqrt(2.0f
)),Pnt3f(0,0,0)));
100 _directions
.push_back(
101 Plane(Vec3f( 1,-1, 0)*(1/osgSqrt(2.0f
)),Pnt3f(0,1,0)));
102 _directions
.push_back(
103 Plane(Vec3f( 0, 1, 1)*(1/osgSqrt(2.0f
)),Pnt3f(0,0,0)));
104 _directions
.push_back(
105 Plane(Vec3f( 0,-1, 1)*(1/osgSqrt(2.0f
)),Pnt3f(0,1,0)));
106 _directions
.push_back(
107 Plane(Vec3f( 1, 0, 1)*(1/osgSqrt(2.0f
)),Pnt3f(0,0,0)));
108 _directions
.push_back(
109 Plane(Vec3f(-1, 0, 1)*(1/osgSqrt(2.0f
)),Pnt3f(1,0,0)));
119 TileGeometryLoad::TileGeometryLoad(const TileGeometryLoad
&source
):
121 _nodeId (source
._nodeId
),
122 _geometry (source
._geometry
),
123 _faces (source
._faces
),
124 _faceDistribution (source
._faceDistribution
),
125 _faceDistDirX (source
._faceDistDirX
),
126 _faceDistDirY (source
._faceDistDirY
),
127 _visible (source
._visible
),
128 _useFaceDistribution(source
._useFaceDistribution
),
129 _areaSize (source
._areaSize
),
130 _valid (source
._valid
)
132 _min
[0] = source
._min
[0];
133 _min
[1] = source
._min
[1];
134 _max
[0] = source
._max
[0];
135 _max
[1] = source
._max
[1];
138 /*-------------------------------------------------------------------------*/
141 /** Destructor documentation
143 TileGeometryLoad::~TileGeometryLoad(void)
147 /** Update the view dependend load parameters
150 void TileGeometryLoad::updateView(Matrix
&viewing
,
158 Real32 minx
= 0.0,miny
= 0.0;
159 Real32 maxx
= 0.0,maxy
= 0.0;
166 Node
*node
= dynamic_cast<Node
*>(
167 FieldContainerFactory::the()->getContainer(_nodeId
));
172 // get whole transformation
173 Matrix m
=node
->getToWorld();
175 // get transformed volume
176 node
->updateVolume();
177 BoxVolume volume
= node
->getVolume();
188 volume
.getBounds(vol
[0], vol
[1]);
190 if(vol
[0][2] > -rNear
)
196 // find best directon for face distribution
197 if(_useFaceDistribution
)
200 Vec3f
xdir(m
[0][0],m
[1][0],m
[2][0]);
201 Vec3f
ydir(m
[0][1],m
[1][1],m
[2][1]);
204 bestScalX
=bestScalY
=0;
205 for(UInt32 dir
=0;dir
<_directions
.size();++dir
)
207 scal
=_directions
[dir
].getNormal()*xdir
;
213 if((-scal
)>bestScalX
)
218 scal
=_directions
[dir
].getNormal()*ydir
;
224 if((-scal
)>bestScalY
)
230 // cout << "x " << xdir << " " << _directions[bestDirX>>1].getNormal() << endl;
231 // cout << "y " << ydir << " " << _directions[bestDirY>>1].getNormal() << endl;
232 _faceDistDirX
=bestDirX
;
233 _faceDistDirY
=bestDirY
;
234 // cout << "best X:" << bestDirX << endl;
235 // cout << "best Y:" << bestDirY << endl;
238 if(vol
[1][2] > -rNear
)
240 // volume lays on the fron clipping plane
246 // volume lays on the visible side of the clipping plane
247 node
->getVolume().getBounds(vol
[0], vol
[1]);
248 m
.multLeft(projection
);
251 // create corners of a bounding box
254 p
->multFull(Pnt3f( vol
[ (i
)&1 ][0] ,
256 vol
[ (i
>>2)&1 ][2]) , pnt
);
259 if(minx
> pnt
[0]) minx
= pnt
[0];
260 if(miny
> pnt
[1]) miny
= pnt
[1];
261 if(maxx
< pnt
[0]) maxx
= pnt
[0];
262 if(maxy
< pnt
[1]) maxy
= pnt
[1];
266 maxx
= minx
= pnt
[0];
267 maxy
= miny
= pnt
[1];
271 if(maxx
<-1 || maxy
<-1 ||
278 minx
=width
* ( minx
+ 1.0f
) / 2.0f
- .5f
;
279 maxx
=width
* ( maxx
+ 1.0f
) / 2.0f
+ .5f
;
280 miny
=height
* ( miny
+ 1.0f
) / 2.0f
- .5f
;
281 maxy
=height
* ( maxy
+ 1.0f
) / 2.0f
+ .5f
;
288 Real32( _max
[0] - _min
[0] + 1 ) *
289 Real32( _max
[1] - _min
[1] + 1 );
291 if(_min[0]<0) _min[0]=0;
292 if(_min[1]<0) _min[1]=0;
293 if(_max[0]>=width ) _max[0]=width-1;
294 if(_max[1]>=height) _max[1]=height-1;
300 /** Update geometry dependend load parameters
302 * This funciton should only be called when geometies have changed.
304 * todo: Use a simple cost estimation mechanism for rapidly changeing
308 void TileGeometryLoad::updateGeometry()
311 dynamic_cast<Node
*>(
312 FieldContainerFactory::the()->getContainer(_nodeId
));
317 const OSG::Volume
&volume
= node
->getVolume();
322 Real32 min
= 0.0,max
= 0.0;
323 PrimitiveIterator it
;
326 const Real32 sq2
= osgSqrt(2.0f
);
327 const Real32 sq3
= osgSqrt(3.0f
);
330 core
=node
->getCore();
331 if(node
->getCore() == NULL
)
333 geo
=dynamic_cast<Geometry
*>(core
);
337 // get volume min,max
338 volume
.getBounds(vmin
,vmax
);
341 for(f
=geo
->beginTriangles() ; f
!=geo
->endTriangles() ; ++f
)
345 if(_useFaceDistribution
)
347 _faceDistribution
.resize(_directions
.size()*2);
348 // loop through all directions
349 for(UInt32 d
=0;d
<_directions
.size();++d
)
352 _faceDistribution
[d
*2 ].resize(FACE_DISTRIBUTION_SAMPLING_COUNT
);
353 _faceDistribution
[d
*2+1].resize(FACE_DISTRIBUTION_SAMPLING_COUNT
);
354 for(s
=0;s
<FACE_DISTRIBUTION_SAMPLING_COUNT
;++s
)
356 _faceDistribution
[d
*2 ][s
]=0;
357 _faceDistribution
[d
*2+1][s
]=0;
359 // loop over all faces
360 for(f
=geo
->beginTriangles() ;
361 f
!=geo
->endTriangles() ;
366 // get point and rescale
367 pos
=(f
.getPosition(p
) - vmin
);
368 pos
[0]/=vmax
[0]-vmin
[0];
369 pos
[1]/=vmax
[1]-vmin
[1];
370 pos
[2]/=vmax
[2]-vmin
[2];
373 max
=min
=_directions
[d
].distance(pos
);
377 max
=osgMax(max
,_directions
[d
].distance(pos
));
378 min
=osgMin(min
,_directions
[d
].distance(pos
));
394 (FACE_DISTRIBUTION_SAMPLING_COUNT
-1)))]++;
398 (FACE_DISTRIBUTION_SAMPLING_COUNT
-1)))]++;
401 for(UInt32 d
=0;d
<_directions
.size();++d
)
403 _faceDistribution
[d
*2 ][0]/=_faces
;
404 _faceDistribution
[d
*2+1][0]/=_faces
;
405 for(s
=1;s
<FACE_DISTRIBUTION_SAMPLING_COUNT
;++s
)
407 _faceDistribution
[d
*2 ][s
]/=_faces
;
408 _faceDistribution
[d
*2+1][s
]/=_faces
;
409 _faceDistribution
[d
*2 ][s
]+=_faceDistribution
[d
*2 ][s
-1];
410 _faceDistribution
[d
*2+1][s
]+=_faceDistribution
[d
*2+1][s
-1];
414 for(s
=0;s
<FACE_DISTRIBUTION_SAMPLING_COUNT
;++s
)
415 printf("%4.3f ",_faceDistribution
[d
*2 ][s
]);
417 for(s
=0;s
<FACE_DISTRIBUTION_SAMPLING_COUNT
;++s
)
418 printf("%4.3f ",_faceDistribution
[d
*2+1][s
]);
425 /*-------------------------------------------------------------------------*/
430 TileGeometryLoad
& TileGeometryLoad::operator=(const TileGeometryLoad
&source
)
434 _min
[0] = source
._min
[0];
435 _min
[1] = source
._min
[1];
436 _max
[0] = source
._max
[0];
437 _max
[1] = source
._max
[1];
438 _faces
= source
._faces
;
439 _visible
= source
._visible
;
440 _faceDistribution
= source
._faceDistribution
;
441 _faceDistDirX
= source
._faceDistDirX
;
442 _faceDistDirY
= source
._faceDistDirY
;
443 _nodeId
= source
._nodeId
;
444 _useFaceDistribution
= source
._useFaceDistribution
;
445 _areaSize
= source
._areaSize
;
450 /*-------------------------------------------------------------------------*/
453 void TileGeometryLoad::dump(void)
458 << _min
[0] << " " << _min
[1] << " / "
459 << _max
[0] << " " << _max
[1] << std::endl
;
463 SLOG
<< "invisible " << std::endl
;
465 SLOG
<< "Faces :" << _faces
<< std::endl
;
468 /*-------------------------------------------------------------------------*/
471 /** Return min valuse in window coordinates
473 const Int32
*TileGeometryLoad::getMin()
478 /** Return max valuse in window coordinates
480 const Int32
*TileGeometryLoad::getMax()
485 /** Is the geometry visible in the current viewport
487 bool TileGeometryLoad::isVisible() const
494 Node
*TileGeometryLoad::getNode() const
497 dynamic_cast<Node
*>(
498 FieldContainerFactory::the()->getContainer(_nodeId
));
501 /** Get number of faces in the geometry
503 UInt32
TileGeometryLoad::getFaces()
508 /** Which part of the faces are visible
510 Real32
TileGeometryLoad::getVisibleFraction( const Int32 wmin
[2],
521 if(!getVisibleArea(wmin
,wmax
,viswmin
,viswmax
))
526 // geometry complete in region?
527 if(viswmin
[0] == _min
[0] &&
528 viswmin
[1] == _min
[1] &&
529 viswmax
[0] == _max
[0] &&
530 viswmax
[1] == _max
[1])
535 if(_useFaceDistribution
)
537 x
=1.0f
/(_max
[0]-_min
[0]+1);
538 y
=1.0f
/(_max
[1]-_min
[1]+1);
540 (getFaceDistribution(_faceDistDirX
^1,
541 1.0f
- (viswmin
[0] - _min
[0] ) * x
) +
542 getFaceDistribution(_faceDistDirX
,
543 (viswmax
[0] - _min
[0] + 1) * x
) - 1)
545 (getFaceDistribution(_faceDistDirY
^1,
546 1.0f
- (viswmin
[1] - _min
[1] ) * y
) +
547 getFaceDistribution(_faceDistDirY
,
548 (viswmax
[1] - _min
[1] + 1) * y
) - 1);
553 (Real32(viswmax
[0] - viswmin
[0] + 1) *
554 Real32(viswmax
[1] - viswmin
[1] + 1)) / _areaSize
;
558 /** Which area overlaps the given region
560 bool TileGeometryLoad::getVisibleArea( const Int32 wmin
[2],
565 viswmin
[0] = osgMax(wmin
[0],_min
[0]);
566 viswmin
[1] = osgMax(wmin
[1],_min
[1]);
567 viswmax
[0] = osgMin(wmax
[0],_max
[0]);
568 viswmax
[1] = osgMin(wmax
[1],_max
[1]);
570 if(viswmin
[0] > viswmax
[0] ||
571 viswmin
[1] > viswmax
[1])
577 /** Check if one part of the geometry lays in the given region
579 * \param min [ minx, miny ]
580 * \param max [ maxx, maxy ]
583 bool TileGeometryLoad::checkRegion( Int32 min
[2],
586 if(min
[0] > _max
[0] ||
595 void TileGeometryLoad::setValid(bool s
)
600 bool TileGeometryLoad::isInvalid(void)
605 /*-------------------------------------------------------------------------*/
608 std::vector
<Plane
> TileGeometryLoad::_directions
;