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

Revision 13376, 22.5 kB (checked in by robert, 2 days ago)

Improved support for controlling the ShadingModel? via the VolumeSettings? object

  • 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.