root/OpenSceneGraph/trunk/src/osgUtil/LineSegmentIntersector.cpp @ 13376

Revision 13376, 22.5 kB (checked in by robert, 45 minutes ago)

From Mattias Helsing, "Seems I was only half right given what you asked for. CMP0017 only
says that modules that are found and ran from cmake modules dir should
prefer cmake-provided modules. find_package() and include() still look
in CMAKE_MODULE_PATH first.

After some investigating I've come up with a proposal examplified in
the attached FindGDAL.cmake script. It simply calls the cmake provided
FindGDAL.cmake if it exists and returns if it succeeds in finding GDAL
using that, otherwise continue with our local cmake code.
Pro: Wont clutter our root CMakeLists.txt
Con: If we begin to write more advanced Findxxx modules (using
COMPONENTS, REQUIRED etc.) we may have to revise this scheme.
"

  • 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
15#include <osgUtil/LineSegmentIntersector>
16
17#include <osg/Geometry>
18#include <osg/Notify>
19#include <osg/io_utils>
20#include <osg/TriangleFunctor>
21#include <osg/KdTree>
22#include <osg/Timer>
23#include <osg/TexMat>
24
25using namespace osgUtil;
26
27namespace LineSegmentIntersectorUtils
28{
29
30    struct TriangleIntersection
31    {
32        TriangleIntersection(unsigned int index, const osg::Vec3& normal, float r1, const osg::Vec3* v1, float r2, const osg::Vec3* v2, float r3, const osg::Vec3* v3):
33            _index(index),
34            _normal(normal),
35            _r1(r1),
36            _v1(v1),
37            _r2(r2),
38            _v2(v2),
39            _r3(r3),
40            _v3(v3) {}
41
42        unsigned int        _index;
43        const osg::Vec3     _normal;
44        float               _r1;
45        const osg::Vec3*    _v1;
46        float               _r2;
47        const osg::Vec3*    _v2;
48        float               _r3;
49        const osg::Vec3*    _v3;
50
51    protected:
52
53        TriangleIntersection& operator = (const TriangleIntersection&) { return *this; }
54    };
55
56    typedef std::multimap<float,TriangleIntersection> TriangleIntersections;
57
58    struct TriangleIntersector
59    {
60        osg::Vec3   _s;
61        osg::Vec3   _d;
62        float       _length;
63
64        int         _index;
65        float       _ratio;
66        bool        _hit;
67        bool        _limitOneIntersection;
68
69        TriangleIntersections _intersections;
70
71        TriangleIntersector()
72        {
73            _length = 0.0f;
74            _index = 0;
75            _ratio = 0.0f;
76            _hit = false;
77            _limitOneIntersection = false;
78        }
79
80        void set(const osg::Vec3d& start, osg::Vec3d& end, float ratio=FLT_MAX)
81        {
82            _hit=false;
83            _index = 0;
84            _ratio = ratio;
85
86            _s = start;
87            _d = end - start;
88            _length = _d.length();
89            _d /= _length;
90        }
91
92        inline void operator () (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3, bool treatVertexDataAsTemporary)
93        {
94            ++_index;
95
96            if (_limitOneIntersection && _hit) return;
97
98            if (v1==v2 || v2==v3 || v1==v3) return;
99
100            osg::Vec3 v12 = v2-v1;
101            osg::Vec3 n12 = v12^_d;
102            float ds12 = (_s-v1)*n12;
103            float d312 = (v3-v1)*n12;
104            if (d312>=0.0f)
105            {
106                if (ds12<0.0f) return;
107                if (ds12>d312) return;
108            }
109            else                     // d312 < 0
110            {
111                if (ds12>0.0f) return;
112                if (ds12<d312) return;
113            }
114
115            osg::Vec3 v23 = v3-v2;
116            osg::Vec3 n23 = v23^_d;
117            float ds23 = (_s-v2)*n23;
118            float d123 = (v1-v2)*n23;
119            if (d123>=0.0f)
120            {
121                if (ds23<0.0f) return;
122                if (ds23>d123) return;
123            }
124            else                     // d123 < 0
125            {
126                if (ds23>0.0f) return;
127                if (ds23<d123) return;
128            }
129
130            osg::Vec3 v31 = v1-v3;
131            osg::Vec3 n31 = v31^_d;
132            float ds31 = (_s-v3)*n31;
133            float d231 = (v2-v3)*n31;
134            if (d231>=0.0f)
135            {
136                if (ds31<0.0f) return;
137                if (ds31>d231) return;
138            }
139            else                     // d231 < 0
140            {
141                if (ds31>0.0f) return;
142                if (ds31<d231) return;
143            }
144
145
146            float r3;
147            if (ds12==0.0f) r3=0.0f;
148            else if (d312!=0.0f) r3 = ds12/d312;
149            else return; // the triangle and the line must be parallel intersection.
150
151            float r1;
152            if (ds23==0.0f) r1=0.0f;
153            else if (d123!=0.0f) r1 = ds23/d123;
154            else return; // the triangle and the line must be parallel intersection.
155
156            float r2;
157            if (ds31==0.0f) r2=0.0f;
158            else if (d231!=0.0f) r2 = ds31/d231;
159            else return; // the triangle and the line must be parallel intersection.
160
161            float total_r = (r1+r2+r3);
162            if (total_r!=1.0f)
163            {
164                if (total_r==0.0f) return; // the triangle and the line must be parallel intersection.
165                float inv_total_r = 1.0f/total_r;
166                r1 *= inv_total_r;
167                r2 *= inv_total_r;
168                r3 *= inv_total_r;
169            }
170
171            osg::Vec3 in = v1*r1+v2*r2+v3*r3;
172            if (!in.valid())
173            {
174                OSG_WARN<<"Warning:: Picked up error in TriangleIntersect"<<std::endl;
175                OSG_WARN<<"   ("<<v1<<",\t"<<v2<<",\t"<<v3<<")"<<std::endl;
176                OSG_WARN<<"   ("<<r1<<",\t"<<r2<<",\t"<<r3<<")"<<std::endl;
177                return;
178            }
179
180            float d = (in-_s)*_d;
181
182            if (d<0.0f) return;
183            if (d>_length) return;
184
185            osg::Vec3 normal = v12^v23;
186            normal.normalize();
187
188            float r = d/_length;
189
190
191            if (treatVertexDataAsTemporary)
192            {
193                _intersections.insert(std::pair<const float,TriangleIntersection>(r,TriangleIntersection(_index-1,normal,r1,0,r2,0,r3,0)));
194            }
195            else
196            {
197                _intersections.insert(std::pair<const float,TriangleIntersection>(r,TriangleIntersection(_index-1,normal,r1,&v1,r2,&v2,r3,&v3)));
198            }
199            _hit = true;
200
201        }
202
203    };
204
205}
206
207///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
208//
209//  LineSegmentIntersector
210//
211
212LineSegmentIntersector::LineSegmentIntersector(const osg::Vec3d& start, const osg::Vec3d& end):
213    _parent(0),
214    _start(start),
215    _end(end)
216{
217}
218
219LineSegmentIntersector::LineSegmentIntersector(CoordinateFrame cf, const osg::Vec3d& start, const osg::Vec3d& end):
220    Intersector(cf),
221    _parent(0),
222    _start(start),
223    _end(end)
224{
225}
226
227LineSegmentIntersector::LineSegmentIntersector(CoordinateFrame cf, double x, double y):
228    Intersector(cf),
229    _parent(0)
230{
231    switch(cf)
232    {
233        case WINDOW : _start.set(x,y,0.0); _end.set(x,y,1.0); break;
234        case PROJECTION : _start.set(x,y,-1.0); _end.set(x,y,1.0); break;
235        case VIEW : _start.set(x,y,0.0); _end.set(x,y,1.0); break;
236        case MODEL : _start.set(x,y,0.0); _end.set(x,y,1.0); break;
237    }
238}
239
240Intersector* LineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv)
241{
242    if (_coordinateFrame==MODEL && iv.getModelMatrix()==0)
243    {
244        osg::ref_ptr<LineSegmentIntersector> lsi = new LineSegmentIntersector(_start, _end);
245        lsi->_parent = this;
246        lsi->_intersectionLimit = this->_intersectionLimit;
247        return lsi.release();
248    }
249
250    // compute the matrix that takes this Intersector from its CoordinateFrame into the local MODEL coordinate frame
251    // that geometry in the scene graph will always be in.
252    osg::Matrix matrix;
253    switch (_coordinateFrame)
254    {
255        case(WINDOW):
256            if (iv.getWindowMatrix()) matrix.preMult( *iv.getWindowMatrix() );
257            if (iv.getProjectionMatrix()) matrix.preMult( *iv.getProjectionMatrix() );
258            if (iv.getViewMatrix()) matrix.preMult( *iv.getViewMatrix() );
259            if (iv.getModelMatrix()) matrix.preMult( *iv.getModelMatrix() );
260            break;
261        case(PROJECTION):
262            if (iv.getProjectionMatrix()) matrix.preMult( *iv.getProjectionMatrix() );
263            if (iv.getViewMatrix()) matrix.preMult( *iv.getViewMatrix() );
264            if (iv.getModelMatrix()) matrix.preMult( *iv.getModelMatrix() );
265            break;
266        case(VIEW):
267            if (iv.getViewMatrix()) matrix.preMult( *iv.getViewMatrix() );
268            if (iv.getModelMatrix()) matrix.preMult( *iv.getModelMatrix() );
269            break;
270        case(MODEL):
271            if (iv.getModelMatrix()) matrix = *iv.getModelMatrix();
272            break;
273    }
274
275    osg::Matrix inverse;
276    inverse.invert(matrix);
277
278    osg::ref_ptr<LineSegmentIntersector> lsi = new LineSegmentIntersector(_start * inverse, _end * inverse);
279    lsi->_parent = this;
280    lsi->_intersectionLimit = this->_intersectionLimit;
281    return lsi.release();
282}
283
284bool LineSegmentIntersector::enter(const osg::Node& node)
285{
286    if (reachedLimit()) return false;
287    return !node.isCullingActive() || intersects( node.getBound() );
288}
289
290void LineSegmentIntersector::leave()
291{
292    // do nothing
293}
294
295void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable)
296{
297    if (reachedLimit()) return;
298
299    osg::Vec3d s(_start), e(_end);
300    if ( !intersectAndClip( s, e, drawable->getBound() ) ) return;
301
302    if (iv.getDoDummyTraversal()) return;
303
304    osg::KdTree* kdTree = iv.getUseKdTreeWhenAvailable() ? dynamic_cast<osg::KdTree*>(drawable->getShape()) : 0;
305    if (kdTree)
306    {
307        osg::KdTree::LineSegmentIntersections intersections;
308        intersections.reserve(4);
309        if (kdTree->intersect(s,e,intersections))
310        {
311            // OSG_NOTICE<<"Got KdTree intersections"<<std::endl;
312            for(osg::KdTree::LineSegmentIntersections::iterator itr = intersections.begin();
313                itr != intersections.end();
314                ++itr)
315            {
316                osg::KdTree::LineSegmentIntersection& lsi = *(itr);
317
318                // get ratio in s,e range
319                double ratio = lsi.ratio;
320
321                // remap ratio into _start, _end range
322                double remap_ratio = ((s-_start).length() + ratio * (e-s).length() )/(_end-_start).length();
323
324
325                Intersection hit;
326                hit.ratio = remap_ratio;
327                hit.matrix = iv.getModelMatrix();
328                hit.nodePath = iv.getNodePath();
329                hit.drawable = drawable;
330                hit.primitiveIndex = lsi.primitiveIndex;
331
332                hit.localIntersectionPoint = _start*(1.0-remap_ratio) + _end*remap_ratio;
333
334                // OSG_NOTICE<<"KdTree: ratio="<<hit.ratio<<" ("<<hit.localIntersectionPoint<<")"<<std::endl;
335
336                hit.localIntersectionNormal = lsi.intersectionNormal;
337
338                hit.indexList.reserve(3);
339                hit.ratioList.reserve(3);
340                if (lsi.r0!=0.0f)
341                {
342                    hit.indexList.push_back(lsi.p0);
343                    hit.ratioList.push_back(lsi.r0);
344                }
345
346                if (lsi.r1!=0.0f)
347                {
348                    hit.indexList.push_back(lsi.p1);
349                    hit.ratioList.push_back(lsi.r1);
350                }
351
352                if (lsi.r2!=0.0f)
353                {
354                    hit.indexList.push_back(lsi.p2);
355                    hit.ratioList.push_back(lsi.r2);
356                }
357
358                insertIntersection(hit);
359            }
360        }
361
362        return;
363    }
364
365    osg::TriangleFunctor<LineSegmentIntersectorUtils::TriangleIntersector> ti;
366    ti.set(s,e);
367    ti._limitOneIntersection = (_intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE);
368    drawable->accept(ti);
369
370    if (ti._hit)
371    {
372        osg::Geometry* geometry = drawable->asGeometry();
373
374        for(LineSegmentIntersectorUtils::TriangleIntersections::iterator thitr = ti._intersections.begin();
375            thitr != ti._intersections.end();
376            ++thitr)
377        {
378
379            // get ratio in s,e range
380            double ratio = thitr->first;
381
382            // remap ratio into _start, _end range
383            double remap_ratio = ((s-_start).length() + ratio * (e-s).length() )/(_end-_start).length();
384
385            if ( _intersectionLimit == LIMIT_NEAREST && !getIntersections().empty() )
386            {
387                if (remap_ratio >= getIntersections().begin()->ratio )
388                    break;
389                else
390                    getIntersections().clear();
391            }
392
393            LineSegmentIntersectorUtils::TriangleIntersection& triHit = thitr->second;
394
395            Intersection hit;
396            hit.ratio = remap_ratio;
397            hit.matrix = iv.getModelMatrix();
398            hit.nodePath = iv.getNodePath();
399            hit.drawable = drawable;
400            hit.primitiveIndex = triHit._index;
401
402            hit.localIntersectionPoint = _start*(1.0-remap_ratio) + _end*remap_ratio;
403
404            // OSG_NOTICE<<"Conventional: ratio="<<hit.ratio<<" ("<<hit.localIntersectionPoint<<")"<<std::endl;
405
406            hit.localIntersectionNormal = triHit._normal;
407
408            if (geometry)
409            {
410                osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
411                if (vertices)
412                {
413                    osg::Vec3* first = &(vertices->front());
414                    if (triHit._v1)
415                    {
416                        hit.indexList.push_back(triHit._v1-first);
417                        hit.ratioList.push_back(triHit._r1);
418                    }
419                    if (triHit._v2)
420                    {
421                        hit.indexList.push_back(triHit._v2-first);
422                        hit.ratioList.push_back(triHit._r2);
423                    }
424                    if (triHit._v3)
425                    {
426                        hit.indexList.push_back(triHit._v3-first);
427                        hit.ratioList.push_back(triHit._r3);
428                    }
429                }
430            }
431
432            insertIntersection(hit);
433
434        }
435    }
436}
437
438void LineSegmentIntersector::reset()
439{
440    Intersector::reset();
441
442    _intersections.clear();
443}
444
445bool LineSegmentIntersector::intersects(const osg::BoundingSphere& bs)
446{
447    // if bs not valid then return true based on the assumption that an invalid sphere is yet to be defined.
448    if (!bs.valid()) return true;
449
450    osg::Vec3d sm = _start - bs._center;
451    double c = sm.length2()-bs._radius*bs._radius;
452    if (c<0.0) return true;
453
454    osg::Vec3d se = _end-_start;
455    double a = se.length2();
456    double b = (sm*se)*2.0;
457    double d = b*b-4.0*a*c;
458
459    if (d<0.0) return false;
460
461    d = sqrt(d);
462
463    double div = 1.0/(2.0*a);
464
465    double r1 = (-b-d)*div;
466    double r2 = (-b+d)*div;
467
468    if (r1<=0.0 && r2<=0.0) return false;
469
470    if (r1>=1.0 && r2>=1.0) return false;
471
472    if (_intersectionLimit == LIMIT_NEAREST && !getIntersections().empty())
473    {
474        double ratio = (sm.length() - bs._radius) / sqrt(a);
475        if (ratio >= getIntersections().begin()->ratio) return false;
476    }
477
478    // passed all the rejection tests so line must intersect bounding sphere, return true.
479    return true;
480}
481
482bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const osg::BoundingBox& bbInput)
483{
484    osg::Vec3d bb_min(bbInput._min);
485    osg::Vec3d bb_max(bbInput._max);
486
487#if 1
488    double epsilon = 1e-4;
489    bb_min.x() -= epsilon;
490    bb_min.y() -= epsilon;
491    bb_min.z() -= epsilon;
492    bb_max.x() += epsilon;
493    bb_max.y() += epsilon;
494    bb_max.z() += epsilon;
495#endif
496
497    // compate s and e against the xMin to xMax range of bb.
498    if (s.x()<=e.x())
499    {
500
501        // trivial reject of segment wholely outside.
502        if (e.x()<bb_min.x()) return false;
503        if (s.x()>bb_max.x()) return false;
504
505        if (s.x()<bb_min.x())
506        {
507            // clip s to xMin.
508            s = s+(e-s)*(bb_min.x()-s.x())/(e.x()-s.x());
509        }
510
511        if (e.x()>bb_max.x())
512        {
513            // clip e to xMax.
514            e = s+(e-s)*(bb_max.x()-s.x())/(e.x()-s.x());
515        }
516    }
517    else
518    {
519        if (s.x()<bb_min.x()) return false;
520        if (e.x()>bb_max.x()) return false;
521
522        if (e.x()<bb_min.x())
523        {
524            // clip s to xMin.
525            e = s+(e-s)*(bb_min.x()-s.x())/(e.x()-s.x());
526        }
527
528        if (s.x()>bb_max.x())
529        {
530            // clip e to xMax.
531            s = s+(e-s)*(bb_max.x()-s.x())/(e.x()-s.x());
532        }
533    }
534
535    // compate s and e against the yMin to yMax range of bb.
536    if (s.y()<=e.y())
537    {
538
539        // trivial reject of segment wholely outside.
540        if (e.y()<bb_min.y()) return false;
541        if (s.y()>bb_max.y()) return false;
542
543        if (s.y()<bb_min.y())
544        {
545            // clip s to yMin.
546            s = s+(e-s)*(bb_min.y()-s.y())/(e.y()-s.y());
547        }
548
549        if (e.y()>bb_max.y())
550        {
551            // clip e to yMax.
552            e = s+(e-s)*(bb_max.y()-s.y())/(e.y()-s.y());
553        }
554    }
555    else
556    {
557        if (s.y()<bb_min.y()) return false;
558        if (e.y()>bb_max.y()) return false;
559
560        if (e.y()<bb_min.y())
561        {
562            // clip s to yMin.
563            e = s+(e-s)*(bb_min.y()-s.y())/(e.y()-s.y());
564        }
565
566        if (s.y()>bb_max.y())
567        {
568            // clip e to yMax.
569            s = s+(e-s)*(bb_max.y()-s.y())/(e.y()-s.y());
570        }
571    }
572
573    // compate s and e against the zMin to zMax range of bb.
574    if (s.z()<=e.z())
575    {
576
577        // trivial reject of segment wholely outside.
578        if (e.z()<bb_min.z()) return false;
579        if (s.z()>bb_max.z()) return false;
580
581        if (s.z()<bb_min.z())
582        {
583            // clip s to zMin.
584            s = s+(e-s)*(bb_min.z()-s.z())/(e.z()-s.z());
585        }
586
587        if (e.z()>bb_max.z())
588        {
589            // clip e to zMax.
590            e = s+(e-s)*(bb_max.z()-s.z())/(e.z()-s.z());
591        }
592    }
593    else
594    {
595        if (s.z()<bb_min.z()) return false;
596        if (e.z()>bb_max.z()) return false;
597
598        if (e.z()<bb_min.z())
599        {
600            // clip s to zMin.
601            e = s+(e-s)*(bb_min.z()-s.z())/(e.z()-s.z());
602        }
603
604        if (s.z()>bb_max.z())
605        {
606            // clip e to zMax.
607            s = s+(e-s)*(bb_max.z()-s.z())/(e.z()-s.z());
608        }
609    }
610
611    // OSG_NOTICE<<"clampped segment "<<s<<" "<<e<<std::endl;
612
613    // if (s==e) return false;
614
615    return true;
616}
617
618osg::Texture* LineSegmentIntersector::Intersection::getTextureLookUp(osg::Vec3& tc) const
619{
620    osg::Geometry* geometry = drawable.valid() ? drawable->asGeometry() : 0;
621    osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0;
622   
623    if (vertices)
624    {
625        if (indexList.size()==3 && ratioList.size()==3)
626        {
627            unsigned int i1 = indexList[0];
628            unsigned int i2 = indexList[1];
629            unsigned int i3 = indexList[2];
630
631            float r1 = ratioList[0];
632            float r2 = ratioList[1];
633            float r3 = ratioList[2];
634
635            osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0;
636            osg::FloatArray* texcoords_FloatArray = dynamic_cast<osg::FloatArray*>(texcoords);
637            osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords);
638            osg::Vec3Array* texcoords_Vec3Array = dynamic_cast<osg::Vec3Array*>(texcoords);
639            if (texcoords_FloatArray)
640            {
641                // we have tex coord array so now we can compute the final tex coord at the point of intersection.
642                float tc1 = (*texcoords_FloatArray)[i1];
643                float tc2 = (*texcoords_FloatArray)[i2];
644                float tc3 = (*texcoords_FloatArray)[i3];
645                tc.x() = tc1*r1 + tc2*r2 + tc3*r3;
646            }
647            else if (texcoords_Vec2Array)
648            {
649                // we have tex coord array so now we can compute the final tex coord at the point of intersection.
650                const osg::Vec2& tc1 = (*texcoords_Vec2Array)[i1];
651                const osg::Vec2& tc2 = (*texcoords_Vec2Array)[i2];
652                const osg::Vec2& tc3 = (*texcoords_Vec2Array)[i3];
653                tc.x() = tc1.x()*r1 + tc2.x()*r2 + tc3.x()*r3;
654                tc.y() = tc1.y()*r1 + tc2.y()*r2 + tc3.y()*r3;
655            }
656            else if (texcoords_Vec3Array)
657            {
658                // we have tex coord array so now we can compute the final tex coord at the point of intersection.
659                const osg::Vec3& tc1 = (*texcoords_Vec3Array)[i1];
660                const osg::Vec3& tc2 = (*texcoords_Vec3Array)[i2];
661                const osg::Vec3& tc3 = (*texcoords_Vec3Array)[i3];
662                tc.x() = tc1.x()*r1 + tc2.x()*r2 + tc3.x()*r3;
663                tc.y() = tc1.y()*r1 + tc2.y()*r2 + tc3.y()*r3;
664                tc.z() = tc1.z()*r1 + tc2.z()*r2 + tc3.z()*r3;
665            }
666            else
667            {
668                return 0;
669            }
670        }
671
672        const osg::TexMat* activeTexMat = 0;
673        const osg::Texture* activeTexture = 0;
674
675        if (drawable->getStateSet())
676        {
677            const osg::TexMat* texMat = dynamic_cast<osg::TexMat*>(drawable->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXMAT));
678            if (texMat) activeTexMat = texMat;
679
680            const osg::Texture* texture = dynamic_cast<osg::Texture*>(drawable->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXTURE));
681            if (texture) activeTexture = texture;
682        }
683
684        for(osg::NodePath::const_reverse_iterator itr = nodePath.rbegin();
685            itr != nodePath.rend() && (!activeTexMat || !activeTexture);
686            ++itr)
687        {
688            const osg::Node* node = *itr;
689            if (node->getStateSet())
690            {
691                if (!activeTexMat)
692                {
693                    const osg::TexMat* texMat = dynamic_cast<const osg::TexMat*>(node->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXMAT));
694                    if (texMat) activeTexMat = texMat;
695                }
696
697                if (!activeTexture)
698                {
699                    const osg::Texture* texture = dynamic_cast<const osg::Texture*>(node->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXTURE));
700                    if (texture) activeTexture = texture;
701                }
702            }
703        }
704
705        if (activeTexMat)
706        {
707            osg::Vec4 tc_transformed = osg::Vec4(tc.x(), tc.y(), tc.z() ,0.0f) * activeTexMat->getMatrix();
708            tc.x() = tc_transformed.x();
709            tc.y() = tc_transformed.y();
710            tc.z() = tc_transformed.z();
711
712            if (activeTexture && activeTexMat->getScaleByTextureRectangleSize())
713            {
714                tc.x() *= static_cast<float>(activeTexture->getTextureWidth());
715                tc.y() *= static_cast<float>(activeTexture->getTextureHeight());
716                tc.z() *= static_cast<float>(activeTexture->getTextureDepth());
717            }
718        }
719
720        return const_cast<osg::Texture*>(activeTexture);
721       
722    }
723    return 0;
724}
Note: See TracBrowser for help on using the browser.