root/OpenSceneGraph/trunk/src/osgShadow/OccluderGeometry.cpp @ 13041

Revision 13041, 28.5 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgShadow/OccluderGeometry>
15
16#include <osg/Notify>
17#include <osg/Geode>
18#include <osg/io_utils>
19#include <osg/TriangleFunctor>
20#include <osg/TriangleIndexFunctor>
21#include <osg/GL>
22#include <osg/Timer>
23
24#include <algorithm>
25
26
27using namespace osgShadow;
28
29OccluderGeometry::OccluderGeometry()
30{
31}
32
33OccluderGeometry::OccluderGeometry(const OccluderGeometry& oc, const osg::CopyOp& copyop):
34    osg::Drawable(oc,copyop)
35{
36
37}
38
39
40class CollectOccludersVisitor : public osg::NodeVisitor
41{
42public:
43    CollectOccludersVisitor(OccluderGeometry* oc, osg::Matrix* matrix, float ratio):
44        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
45        _oc(oc),
46        _ratio(ratio)
47    {
48        if (matrix) pushMatrix(*matrix);
49    }
50
51    META_NodeVisitor("osgShadow","CollectOccludersVisitor")
52
53    void apply(osg::Node& node)
54    {
55        if (node.getStateSet()) pushState(node.getStateSet());
56
57        traverse(node);
58
59        if (node.getStateSet()) popState();
60    }
61
62    void apply(osg::Transform& transform)
63    {
64        if (transform.getStateSet()) pushState(transform.getStateSet());
65
66        osg::Matrix matrix;
67        if (!_matrixStack.empty()) matrix = _matrixStack.back();
68
69        transform.computeLocalToWorldMatrix(matrix,this);
70
71        pushMatrix(matrix);
72
73        traverse(transform);
74
75        popMatrix();
76
77        if (transform.getStateSet()) popState();
78    }
79
80    void apply(osg::Geode& geode)
81    {
82        if (geode.getStateSet()) pushState(geode.getStateSet());
83
84        for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
85        {
86            osg::Drawable* drawable = geode.getDrawable(i);
87
88            if (drawable->getStateSet()) pushState(drawable->getStateSet());
89
90            apply(geode.getDrawable(i));
91
92            if (drawable->getStateSet()) popState();
93        }
94
95        if (geode.getStateSet()) popState();
96    }
97
98    void pushState(osg::StateSet* stateset)
99    {
100        osg::StateAttribute::GLModeValue prevBlendModeValue = _blendModeStack.empty() ? osg::StateAttribute::GLModeValue(osg::StateAttribute::INHERIT) : _blendModeStack.back();
101        osg::StateAttribute::GLModeValue newBlendModeValue = stateset->getMode(GL_BLEND);
102
103        if (!(newBlendModeValue & osg::StateAttribute::PROTECTED) &&
104             (prevBlendModeValue & osg::StateAttribute::OVERRIDE) )
105        {
106            newBlendModeValue = prevBlendModeValue;
107        }
108
109        _blendModeStack.push_back(newBlendModeValue);
110    }
111
112    void popState()
113    {
114        _blendModeStack.pop_back();
115    }
116
117    void pushMatrix(osg::Matrix& matrix)
118    {
119        _matrixStack.push_back(matrix);
120    }
121
122    void popMatrix()
123    {
124        _matrixStack.pop_back();
125    }
126
127    void apply(osg::Drawable* drawable)
128    {
129        osg::StateAttribute::GLModeValue blendModeValue = _blendModeStack.empty() ? osg::StateAttribute::GLModeValue(osg::StateAttribute::INHERIT) : _blendModeStack.back();
130        if (blendModeValue & osg::StateAttribute::ON)
131        {
132            // OSG_NOTICE<<"Ignoring transparent drawable."<<std::endl;
133            return;
134        }
135
136        _oc->processGeometry(drawable, (_matrixStack.empty() ? 0 : &_matrixStack.back()), _ratio);
137
138    }
139
140protected:
141
142    OccluderGeometry* _oc;
143
144    typedef std::vector<osg::Matrix> MatrixStack;
145    typedef std::vector<osg::StateAttribute::GLModeValue> ModeStack;
146
147    float           _ratio;
148    MatrixStack     _matrixStack;
149    ModeStack       _blendModeStack;
150
151};
152
153void OccluderGeometry::computeOccluderGeometry(osg::Node* subgraph, osg::Matrix* matrix, float sampleRatio)
154{
155    OSG_NOTICE<<"computeOccluderGeometry(osg::Node* subgraph, float sampleRatio)"<<std::endl;
156
157    osg::Timer_t startTick = osg::Timer::instance()->tick();
158
159    CollectOccludersVisitor cov(this, matrix, sampleRatio);
160    subgraph->accept(cov);
161
162    setUpInternalStructures();
163
164    osg::Timer_t endTick = osg::Timer::instance()->tick();
165
166    OSG_NOTICE<<"done in "<<osg::Timer::instance()->delta_m(startTick, endTick)<<" ms"<<std::endl;
167}
168
169void OccluderGeometry::computeOccluderGeometry(osg::Drawable* drawable, osg::Matrix* matrix, float sampleRatio)
170{
171    processGeometry(drawable, matrix, sampleRatio);
172
173    setUpInternalStructures();
174}
175
176struct TriangleCollector
177{
178    OccluderGeometry::Vec3List* _vertices;
179    OccluderGeometry::UIntList* _triangleIndices;
180    osg::Matrix*                _matrix;
181
182    typedef std::vector<const osg::Vec3*> VertexPointers;
183    VertexPointers _vertexPointers;
184
185    OccluderGeometry::Vec3List _tempoaryTriangleVertices;
186
187    TriangleCollector():_matrix(0) { }
188
189    void set(OccluderGeometry::Vec3List* vertices, OccluderGeometry::UIntList* triangleIndices, osg::Matrix* matrix)
190    {
191        _vertices = vertices;
192        _triangleIndices = triangleIndices;
193        _matrix = matrix;
194    }
195
196
197    //   bool intersect(const Vec3& v1,const Vec3& v2,const Vec3& v3,float& r)
198    inline void operator () (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3, bool treatVertexDataAsTemporary)
199    {
200        if (treatVertexDataAsTemporary)
201        {
202            // OSG_NOTICE<<"Triangle temp ("<<v1<<") ("<<v2<<") ("<<v3<<")"<<std::endl;
203            _tempoaryTriangleVertices.push_back(v1);
204            _tempoaryTriangleVertices.push_back(v2);
205            _tempoaryTriangleVertices.push_back(v3);
206
207        }
208        else
209        {
210            // OSG_NOTICE<<"Triangle ("<<v1<<") ("<<v2<<") ("<<v3<<")"<<std::endl;
211            _vertexPointers.push_back(&v1);
212            _vertexPointers.push_back(&v2);
213            _vertexPointers.push_back(&v3);
214        }
215
216    }
217
218    void copyToLocalData()
219    {
220        if ((_vertexPointers.size()+_tempoaryTriangleVertices.size())<3) return;
221
222
223        const osg::Vec3* minVertex = _vertexPointers.empty() ? 0 : _vertexPointers.front();
224        const osg::Vec3* maxVertex = _vertexPointers.empty() ? 0 : _vertexPointers.front();
225
226        VertexPointers::iterator itr;
227        for(itr = _vertexPointers.begin();
228            itr != _vertexPointers.end();
229            ++itr)
230        {
231            if (*itr < minVertex) minVertex = *itr;
232            if (*itr > maxVertex) maxVertex = *itr;
233        }
234
235        unsigned int base = _vertices->size();
236        unsigned int numberNewVertices = _vertexPointers.empty() ? 0 : (maxVertex - minVertex) + 1;
237
238        // OSG_NOTICE<<"base = "<<base<<" numberNewVertices="<<numberNewVertices<<std::endl;
239
240        _vertices->resize(base + numberNewVertices + _tempoaryTriangleVertices.size());
241
242        for(itr = _vertexPointers.begin();
243            itr != _vertexPointers.end();
244            ++itr)
245        {
246            const osg::Vec3* vec = *itr;
247            unsigned int index = base + (vec - minVertex);
248            (*_vertices)[index] = *vec;
249            _triangleIndices->push_back(index);
250        }
251
252
253        unsigned int pos = base + numberNewVertices;
254        for(OccluderGeometry::Vec3List::iterator vitr = _tempoaryTriangleVertices.begin();
255             vitr != _tempoaryTriangleVertices.end();
256             ++vitr, ++pos)
257        {
258            (*_vertices)[pos] = *vitr;
259            _triangleIndices->push_back(pos);
260        }
261
262        if (_matrix)
263        {
264            for(unsigned int i=base; i<_vertices->size(); ++i)
265            {
266                (*_vertices)[i] = (*_vertices)[i] * (*_matrix);
267            }
268        }
269
270    }
271
272
273};
274typedef osg::TriangleFunctor<TriangleCollector> TriangleCollectorFunctor;
275
276void OccluderGeometry::processGeometry(osg::Drawable* drawable, osg::Matrix* matrix, float /*sampleRatio*/)
277{
278    // OSG_NOTICE<<"computeOccluderGeometry(osg::Node* subgraph, float sampleRatio)"<<std::endl;
279
280    TriangleCollectorFunctor tc;
281    tc.set(&_vertices, &_triangleIndices, matrix);
282
283    drawable->accept(tc);
284
285    tc.copyToLocalData();
286
287#if 0
288    for(Vec3List::iterator vitr = _vertices.begin();
289        vitr != _vertices.end();
290        ++vitr)
291    {
292        OSG_NOTICE<<"v "<<*vitr<<std::endl;
293    }
294
295    for(UIntList::iterator titr = _triangleIndices.begin();
296        titr != _triangleIndices.end();
297        )
298    {
299        OSG_NOTICE<<"t "<<*titr++<<" "<<*titr++<<" "<<*titr++<<std::endl;
300    }
301#endif
302}
303
304void OccluderGeometry::setUpInternalStructures()
305{
306
307    osg::Timer_t t0 = osg::Timer::instance()->tick();
308
309    removeDuplicateVertices();
310
311    osg::Timer_t t1 = osg::Timer::instance()->tick();
312
313    removeNullTriangles();
314
315    osg::Timer_t t2 = osg::Timer::instance()->tick();
316
317    computeNormals();
318
319    osg::Timer_t t3 = osg::Timer::instance()->tick();
320
321    buildEdgeMaps();
322
323    osg::Timer_t t4 = osg::Timer::instance()->tick();
324
325
326    OSG_NOTICE<<"removeDuplicateVertices "<<osg::Timer::instance()->delta_m(t0,t1)<<" ms"<<std::endl;
327    OSG_NOTICE<<"removeNullTriangles "<<osg::Timer::instance()->delta_m(t1,t2)<<" ms"<<std::endl;
328    OSG_NOTICE<<"computeNormals "<<osg::Timer::instance()->delta_m(t2,t3)<<" ms"<<std::endl;
329    OSG_NOTICE<<"buildEdgeMaps "<<osg::Timer::instance()->delta_m(t3,t4)<<" ms"<<std::endl;
330    OSG_NOTICE<<"setUpInternalStructures "<<osg::Timer::instance()->delta_m(t0,t4)<<" ms"<<std::endl;
331
332
333    dirtyBound();
334
335    dirtyDisplayList();
336}
337
338struct IndexVec3PtrPair
339{
340    IndexVec3PtrPair():
341        vec(0),
342        index(0) {}
343
344    IndexVec3PtrPair(const osg::Vec3* v, unsigned int i):
345        vec(v),
346        index(i) {}
347
348    inline bool operator < (const IndexVec3PtrPair& rhs) const
349    {
350        return *vec < *rhs.vec;
351    }
352
353    inline bool operator == (const IndexVec3PtrPair& rhs) const
354    {
355        return *vec == *rhs.vec;
356
357//        return (*vec - *rhs.vec).length2() < 1e-2;
358
359    }
360
361    const osg::Vec3* vec;
362    unsigned int index;
363};
364
365
366void OccluderGeometry::removeDuplicateVertices()
367{
368    if (_vertices.empty()) return;
369
370    OSG_NOTICE<<"OccluderGeometry::removeDuplicates() before = "<<_vertices.size()<<std::endl;
371
372    typedef std::vector<IndexVec3PtrPair> IndexVec3PtrPairs;
373    IndexVec3PtrPairs indexVec3PtrPairs;
374    indexVec3PtrPairs.reserve(_vertices.size());
375
376    unsigned int i = 0;
377    for(OccluderGeometry::Vec3List::iterator vitr = _vertices.begin();
378         vitr != _vertices.end();
379         ++vitr, ++i)
380    {
381        indexVec3PtrPairs.push_back(IndexVec3PtrPair(&(*vitr),i));
382    }
383    std::sort(indexVec3PtrPairs.begin(),indexVec3PtrPairs.end());;
384
385
386    // compute size
387    IndexVec3PtrPairs::iterator prev = indexVec3PtrPairs.begin();
388    IndexVec3PtrPairs::iterator curr = prev;
389    ++curr;
390
391    unsigned int numDuplicates = 0;
392    unsigned int numUnique = 1;
393
394    for(; curr != indexVec3PtrPairs.end(); ++curr)
395    {
396        if (*prev==*curr)
397        {
398            ++numDuplicates;
399        }
400        else
401        {
402            prev = curr;
403            ++numUnique;
404        }
405    }
406
407    OSG_NOTICE<<"Num diplicates = "<<numDuplicates<<std::endl;
408    OSG_NOTICE<<"Num unique = "<<numUnique<<std::endl;
409
410    if (numDuplicates==0) return;
411
412    // now assign the unique Vec3 to the newVertices arrays
413    typedef std::vector<unsigned int> IndexMap;
414    IndexMap indexMap(indexVec3PtrPairs.size());
415
416    Vec3List newVertices;
417    newVertices.reserve(numUnique);
418    unsigned int index = 0;
419
420    prev = indexVec3PtrPairs.begin();
421    curr = prev;
422
423    // add first vertex
424    indexMap[curr->index] = index;
425    newVertices.push_back(*(curr->vec));
426
427    ++curr;
428
429    for(; curr != indexVec3PtrPairs.end(); ++curr)
430    {
431        if (*prev==*curr)
432        {
433            indexMap[curr->index] = index;
434        }
435        else
436        {
437            ++index;
438
439            // add new unique vertex
440            indexMap[curr->index] = index;
441            newVertices.push_back(*(curr->vec));
442
443            prev = curr;
444        }
445    }
446
447    // copy over need arrays and index values
448    _vertices.swap(newVertices);
449
450    for(UIntList::iterator titr = _triangleIndices.begin();
451        titr != _triangleIndices.end();
452        ++titr)
453    {
454        *titr = indexMap[*titr];
455    }
456
457    // OSG_NOTICE<<"OccluderGeometry::removeDuplicates() after = "<<_vertices.size()<<std::endl;
458}
459
460void OccluderGeometry::removeNullTriangles()
461{
462    // OSG_NOTICE<<"OccluderGeometry::removeNullTriangles()"<<std::endl;
463
464
465    UIntList::iterator lastValidItr = _triangleIndices.begin();
466    for(UIntList::iterator titr = _triangleIndices.begin();
467        titr != _triangleIndices.end();
468        )
469    {
470        UIntList::iterator currItr = titr;
471        GLuint p1 = *titr++;
472        GLuint p2 = *titr++;
473        GLuint p3 = *titr++;
474        if ((p1 != p2) && (p1 != p3) && (p2 != p3))
475        {
476            if (lastValidItr!=currItr)
477            {
478                *lastValidItr++ = p1;
479                *lastValidItr++ = p2;
480                *lastValidItr++ = p3;
481            }
482            else
483            {
484                lastValidItr = titr;
485            }
486        }
487        else
488        {
489            // OSG_NOTICE<<"Null triangle"<<std::endl;
490        }
491    }
492    if (lastValidItr != _triangleIndices.end())
493    {
494        // OSG_NOTICE<<"Pruning end - before "<<_triangleIndices.size()<<std::endl;
495        _triangleIndices.erase(lastValidItr,_triangleIndices.end());
496        // OSG_NOTICE<<"Pruning end - after "<<_triangleIndices.size()<<std::endl;
497    }
498}
499
500void OccluderGeometry::computeNormals()
501{
502    // OSG_NOTICE<<"OccluderGeometry::computeNormals()"<<std::endl;
503
504    unsigned int numTriangles = _triangleIndices.size() / 3;
505    unsigned int redundentIndices = _triangleIndices.size() - numTriangles * 3;
506    if (redundentIndices)
507    {
508        OSG_NOTICE<<"Warning OccluderGeometry::computeNormals() has found redundent trailing indices"<<std::endl;
509        _triangleIndices.erase(_triangleIndices.begin() + numTriangles * 3, _triangleIndices.end());
510    }
511
512    _triangleNormals.clear();
513    _triangleNormals.reserve(numTriangles);
514
515    _normals.resize(_vertices.size());
516
517
518    for(UIntList::iterator titr = _triangleIndices.begin();
519        titr != _triangleIndices.end();
520        )
521    {
522        GLuint p1 = *titr++;
523        GLuint p2 = *titr++;
524        GLuint p3 = *titr++;
525        osg::Vec3 normal = (_vertices[p2] - _vertices[p1]) ^ (_vertices[p3] - _vertices[p2]);
526        normal.normalize();
527
528        _triangleNormals.push_back(normal);
529
530        if (!_normals.empty())
531        {
532            _normals[p1] += normal;
533            _normals[p2] += normal;
534            _normals[p3] += normal;
535        }
536    }
537
538    for(Vec3List::iterator nitr = _normals.begin();
539        nitr != _normals.end();
540        ++nitr)
541    {
542        nitr->normalize();
543    }
544
545
546}
547
548void OccluderGeometry::buildEdgeMaps()
549{
550    // OSG_NOTICE<<"OccluderGeometry::buildEdgeMaps()"<<std::endl;
551
552    typedef std::set<Edge> EdgeSet;
553    EdgeSet edgeSet;
554
555    unsigned int numTriangleErrors = 0;
556    unsigned int triNo=0;
557    for(UIntList::iterator titr = _triangleIndices.begin();
558        titr != _triangleIndices.end();
559        ++triNo)
560    {
561        GLuint p1 = *titr++;
562        GLuint p2 = *titr++;
563        GLuint p3 = *titr++;
564
565        {
566            Edge edge12(p1,p2);
567            EdgeSet::iterator itr = edgeSet.find(edge12);
568            if (itr == edgeSet.end())
569            {
570                if (!edge12.addTriangle(triNo)) ++numTriangleErrors;
571                edgeSet.insert(edge12);
572            }
573            else
574            {
575                if (!itr->addTriangle(triNo)) ++numTriangleErrors;
576            }
577        }
578
579        {
580            Edge edge23(p2,p3);
581            EdgeSet::iterator itr = edgeSet.find(edge23);
582            if (itr == edgeSet.end())
583            {
584                if (!edge23.addTriangle(triNo)) ++numTriangleErrors;
585                edgeSet.insert(edge23);
586            }
587            else
588            {
589                if (!itr->addTriangle(triNo)) ++numTriangleErrors;
590            }
591        }
592
593        {
594            Edge edge31(p3,p1);
595            EdgeSet::iterator itr = edgeSet.find(edge31);
596            if (itr == edgeSet.end())
597            {
598                if (!edge31.addTriangle(triNo)) ++numTriangleErrors;
599
600                edgeSet.insert(edge31);
601            }
602            else
603            {
604                if (!itr->addTriangle(triNo)) ++numTriangleErrors;
605            }
606        }
607    }
608
609    _edges.clear();
610    _edges.reserve(edgeSet.size());
611
612    unsigned int numEdgesWithNoTriangles = 0;
613    unsigned int numEdgesWithOneTriangles = 0;
614    unsigned int numEdgesWithTwoTriangles = 0;
615
616    for(EdgeSet::iterator eitr = edgeSet.begin();
617        eitr != edgeSet.end();
618        ++eitr)
619    {
620        const Edge& edge = *eitr;
621        osg::Vec3 pos(0.0,0.0,0.0);
622        osg::Vec3 mid = (_vertices[edge._p1] + _vertices[edge._p2]) * 0.5f;
623        unsigned int numTriangles = 0;
624        if (edge._t1>=0)
625        {
626            ++numTriangles;
627
628            GLuint p1 = _triangleIndices[edge._t1*3];
629            GLuint p2 = _triangleIndices[edge._t1*3+1];
630            GLuint p3 = _triangleIndices[edge._t1*3+2];
631            GLuint opposite = p1;
632            if (p1 != edge._p1 && p1 != edge._p2) opposite = p1;
633            else if (p2 != edge._p1 && p2 != edge._p2) opposite = p2;
634            else if (p3 != edge._p1 && p3 != edge._p2) opposite = p3;
635            pos = _vertices[opposite];
636        }
637
638        if (edge._t2>=0)
639        {
640            ++numTriangles;
641
642            GLuint p1 = _triangleIndices[edge._t2*3];
643            GLuint p2 = _triangleIndices[edge._t2*3+1];
644            GLuint p3 = _triangleIndices[edge._t2*3+2];
645            GLuint opposite = p1;
646            if (p1 != edge._p1 && p1 != edge._p2) opposite = p1;
647            else if (p2 != edge._p1 && p2 != edge._p2) opposite = p2;
648            else if (p3 != edge._p1 && p3 != edge._p2) opposite = p3;
649            pos += _vertices[opposite];
650        }
651
652        switch(numTriangles)
653        {
654            case(0):
655                ++numEdgesWithNoTriangles;
656                edge._normal.set(0.0,0.0,0.0);
657                OSG_NOTICE<<"Warning no triangles on edge."<<std::endl;
658                break;
659            case(1):
660                ++numEdgesWithOneTriangles;
661                edge._normal = pos - mid;
662                edge._normal.normalize();
663                break;
664            default:
665                ++numEdgesWithTwoTriangles;
666                edge._normal = (pos*0.5f) - mid;
667                edge._normal.normalize();
668                break;
669        }
670
671        _edges.push_back(edge);
672    }
673
674#if 0
675    OSG_NOTICE<<"Num of indices "<<_triangleIndices.size()<<std::endl;
676    OSG_NOTICE<<"Num of triangles "<<triNo<<std::endl;
677    OSG_NOTICE<<"Num of numTriangleErrors "<<numTriangleErrors<<std::endl;
678    OSG_NOTICE<<"Num of edges "<<edgeSet.size()<<std::endl;
679    OSG_NOTICE<<"Num of numEdgesWithNoTriangles "<<numEdgesWithNoTriangles<<std::endl;
680    OSG_NOTICE<<"Num of numEdgesWithOneTriangles "<<numEdgesWithOneTriangles<<std::endl;
681    OSG_NOTICE<<"Num of numEdgesWithTwoTriangles "<<numEdgesWithTwoTriangles<<std::endl;
682#endif
683}
684
685
686void OccluderGeometry::computeLightDirectionSilhouetteEdges(const osg::Vec3& lightdirection, UIntList& silhouetteIndices) const
687{
688    silhouetteIndices.clear();
689
690    for(EdgeList::const_iterator eitr = _edges.begin();
691        eitr != _edges.end();
692        ++eitr)
693    {
694        const Edge& edge = *eitr;
695        if (isLightDirectionSilhouetteEdge(lightdirection,edge))
696        {
697            const osg::Vec3& v1 = _vertices[edge._p1];
698            const osg::Vec3& v2 = _vertices[edge._p2];
699            osg::Vec3 normal = (v2-v1) ^ lightdirection;
700            if (normal * edge._normal > 0.0)
701            {
702                silhouetteIndices.push_back(edge._p1);
703                silhouetteIndices.push_back(edge._p2);
704            }
705            else
706            {
707                silhouetteIndices.push_back(edge._p2);
708                silhouetteIndices.push_back(edge._p1);
709            }
710        }
711    }
712}
713
714void OccluderGeometry::computeLightPositionSilhouetteEdges(const osg::Vec3& lightpos, UIntList& silhouetteIndices) const
715{
716    silhouetteIndices.clear();
717
718    for(EdgeList::const_iterator eitr = _edges.begin();
719        eitr != _edges.end();
720        ++eitr)
721    {
722        const Edge& edge = *eitr;
723        if (isLightPointSilhouetteEdge(lightpos,edge))
724        {
725            const osg::Vec3& v1 = _vertices[edge._p1];
726            const osg::Vec3& v2 = _vertices[edge._p2];
727            osg::Vec3 normal = (v2-v1) ^ (v1-lightpos);
728            if (normal * edge._normal > 0.0)
729            {
730                silhouetteIndices.push_back(edge._p1);
731                silhouetteIndices.push_back(edge._p2);
732            }
733            else
734            {
735                silhouetteIndices.push_back(edge._p2);
736                silhouetteIndices.push_back(edge._p1);
737            }
738
739        }
740    }
741}
742
743
744void OccluderGeometry::computeShadowVolumeGeometry(const osg::Vec4& lightpos, ShadowVolumeGeometry& svg) const
745{
746    // osg::Timer_t t0 = osg::Timer::instance()->tick();
747
748    ShadowVolumeGeometry::Vec3List& shadowVertices = svg.getVertices();
749    shadowVertices.clear();
750
751    ShadowVolumeGeometry::Vec3List& shadowNormals = svg.getNormals();
752    shadowNormals.clear();
753
754
755    // need to have some kind of handling of case when no planes exist.
756    if (_boundingPolytope.getPlaneList().empty())
757    {
758        OSG_NOTICE<<"Warning: no bounding polytope registered with OccluderGeometry."<<std::endl;
759        return;
760    }
761
762
763    if (lightpos.w()==0.0)
764    {
765        // directional light.
766        osg::Vec3 lightdirection( -lightpos.x(), -lightpos.y(), -lightpos.z());
767
768        // OSG_NOTICE<<"Directional light"<<std::endl;
769
770        // choose the base plane
771        const osg::Polytope::PlaneList& planes = _boundingPolytope.getPlaneList();
772        osg::Polytope::PlaneList::const_iterator pitr = planes.begin();
773        osg::Plane basePlane = *pitr;
774        ++pitr;
775
776        for(;
777            pitr != planes.end();
778            ++pitr)
779        {
780            if (basePlane.dotProductNormal(lightdirection)  > pitr->dotProductNormal(lightdirection))
781            {
782                basePlane = *pitr;
783            }
784        }
785
786        // compute the silhouette edge
787        UIntList silhouetteIndices;
788        computeLightDirectionSilhouetteEdges(lightdirection, silhouetteIndices);
789
790        osg::Vec3 offset( lightdirection*5.0f );
791
792        float directionScale = 1.0f / basePlane.dotProductNormal(lightdirection);
793
794        for(UIntList::iterator itr = silhouetteIndices.begin();
795            itr != silhouetteIndices.end();
796            )
797        {
798            const osg::Vec3& v1 = _vertices[*itr++];
799            const osg::Vec3& v2 = _vertices[*itr++];
800
801            float r1 = basePlane.distance(v1) * directionScale;
802            float r2 = basePlane.distance(v2) * directionScale;
803
804            osg::Vec3 v1_projected = v1 - (lightdirection * r1);
805            osg::Vec3 v2_projected = v2 - (lightdirection * r2);
806
807            shadowVertices.push_back( v1);
808            shadowVertices.push_back( v1_projected);
809            shadowVertices.push_back( v2_projected);
810            shadowVertices.push_back( v2);
811
812            osg::Vec3 normal = lightdirection ^ (v2-v1);
813            normal.normalize();
814            shadowNormals.push_back(normal);
815            shadowNormals.push_back(normal);
816            shadowNormals.push_back(normal);
817            shadowNormals.push_back(normal);
818        }
819
820    }
821    else
822    {
823        // positional light
824        osg::Vec3 lightposition( lightpos.x(), lightpos.y(), lightpos.z());
825
826        osg::Plane basePlane(0.0, 0.0, 1.0, 0.0);
827
828        // OSG_NOTICE<<"Positional light"<<std::endl;
829        UIntList silhouetteIndices;
830        computeLightPositionSilhouetteEdges(lightposition, silhouetteIndices);
831
832        // OSG_NOTICE<<"basePlane "<<basePlane[0]<<" "<<basePlane[1]<<" "<<basePlane[2]<<" "<<basePlane[3]<<std::endl;
833        // OSG_NOTICE<<"lightpos  = "<<std::endl;
834        const osg::Polytope::PlaneList& planes = _boundingPolytope.getPlaneList();
835
836        for(UIntList::iterator itr = silhouetteIndices.begin();
837            itr != silhouetteIndices.end();
838            )
839        {
840            const osg::Vec3& v1 = _vertices[*itr++];
841            const osg::Vec3& v2 = _vertices[*itr++];
842
843            osg::Vec3 d1 = v1 - lightposition;
844            osg::Vec3 d2 = v2 - lightposition;
845
846            osg::Polytope::PlaneList::const_iterator pitr = planes.begin();
847            float r1 = - pitr->distance(v1) / (pitr->dotProductNormal(d1));
848            float r2 = - pitr->distance(v2) / (pitr->dotProductNormal(d2));
849            ++pitr;
850
851            for(;
852                pitr != planes.end();
853                ++pitr)
854            {
855                float lr1 = - pitr->distance(v1) / (pitr->dotProductNormal(d1));
856                float lr2 = - pitr->distance(v2) / (pitr->dotProductNormal(d2));
857
858                if (lr1>=0.0f && lr2>=0.0f && (lr1+lr2)<(r1+r2))
859                {
860                    r1 = lr1;
861                    r2 = lr2;
862                }
863            }
864
865            osg::Vec3 v1_projected = v1 + (d1 * r1);
866            osg::Vec3 v2_projected = v2 + (d2 * r2);
867
868            shadowVertices.push_back( v1);
869            shadowVertices.push_back( v1_projected);
870            shadowVertices.push_back( v2_projected);
871            shadowVertices.push_back( v2);
872
873            osg::Vec3 normal = d1 ^ (v2-v1);
874            normal.normalize();
875            shadowNormals.push_back(normal);
876            shadowNormals.push_back(normal);
877            shadowNormals.push_back(normal);
878            shadowNormals.push_back(normal);
879        }
880
881    }
882
883    svg.dirtyDisplayList();
884    svg.dirtyBound();
885
886    // osg::Timer_t t1 = osg::Timer::instance()->tick();
887    // OSG_NOTICE<<"computeShadowVolumeGeometry "<<osg::Timer::instance()->delta_m(t0,t1)<<" ms"<<std::endl;
888}
889
890void OccluderGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
891{
892    renderInfo.getState()->disableAllVertexArrays();
893
894    renderInfo.getState()->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) );
895
896    if (!_normals.empty())
897    {
898        renderInfo.getState()->setNormalPointer( GL_FLOAT, 0, &(_normals.front()) );
899    }
900
901    if (!_triangleIndices.empty())
902    {
903        glDrawElements(GL_TRIANGLES, _triangleIndices.size(), GL_UNSIGNED_INT, &(_triangleIndices.front()) );
904    }
905}
906
907osg::BoundingBox OccluderGeometry::computeBound() const
908{
909    osg::BoundingBox bb;
910    for(Vec3List::const_iterator itr =  _vertices.begin();
911        itr != _vertices.end();
912        ++itr)
913    {
914        bb.expandBy(*itr);
915    }
916
917    return bb;
918}
919
920///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
921//
922//  ShadowVolumeGeometry
923//
924ShadowVolumeGeometry::ShadowVolumeGeometry():
925    _drawMode(GEOMETRY)
926{
927}
928
929ShadowVolumeGeometry::ShadowVolumeGeometry(const ShadowVolumeGeometry& oc, const osg::CopyOp& copyop):
930    osg::Drawable(oc,copyop)
931{
932}
933
934void ShadowVolumeGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
935{
936    if (_drawMode==GEOMETRY)
937    {
938        osg::State* state = renderInfo.getState();
939
940        state->disableAllVertexArrays();
941
942        state->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) );
943
944        if (!_normals.empty())
945        {
946            state->setNormalPointer( GL_FLOAT, 0, &(_normals.front()) );
947        }
948        else
949        {
950            state->Normal(0.0f, 0.0f, 0.0f);
951        }
952
953
954        state->Color(0.5f, 1.0f, 1.0f, 1.0f);
955
956        glDrawArrays( GL_QUADS, 0, _vertices.size() );
957    }
958    else if (_drawMode==STENCIL_TWO_PASS)
959    {
960        osg::State* state = renderInfo.getState();
961
962        state->disableAllVertexArrays();
963        state->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) );
964
965        // draw front faces of shadow volume
966        glCullFace(GL_BACK);
967        glStencilOp( GL_KEEP, GL_KEEP, GL_INCR);
968
969        glDrawArrays( GL_QUADS, 0, _vertices.size() );
970
971        // draw back faces of shadow volume
972        glCullFace(GL_FRONT);
973        glStencilOp( GL_KEEP, GL_KEEP, GL_DECR);
974
975        glDrawArrays( GL_QUADS, 0, _vertices.size() );
976
977        state->haveAppliedAttribute(osg::StateAttribute::CULLFACE);
978        state->haveAppliedAttribute(osg::StateAttribute::STENCIL);
979
980    }
981    else // stencil two sided, note state all set up separately.
982    {
983        osg::State* state = renderInfo.getState();
984
985        state->disableAllVertexArrays();
986        state->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) );
987
988        glDrawArrays( GL_QUADS, 0, _vertices.size() );
989    }
990}
991
992osg::BoundingBox ShadowVolumeGeometry::computeBound() const
993{
994    osg::BoundingBox bb;
995    for(Vec3List::const_iterator itr =  _vertices.begin();
996        itr != _vertices.end();
997        ++itr)
998    {
999        bb.expandBy(*itr);
1000    }
1001
1002    return bb;
1003}
Note: See TracBrowser for help on using the browser.