root/OpenSceneGraph/trunk/src/osgSim/OverlayNode.cpp @ 13041

Revision 13041, 62.5 kB (checked in by robert, 2 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 <osg/ComputeBoundsVisitor>
15#include <osg/Texture2D>
16#include <osg/CoordinateSystemNode>
17#include <osg/TexEnv>
18#include <osg/Geometry>
19#include <osg/io_utils>
20
21#include <osgDB/FileUtils>
22
23#include <osgUtil/CullVisitor>
24#include <osgSim/OverlayNode>
25
26using namespace osgSim;
27using namespace osg;
28
29
30namespace osgSim
31{
32
33class CustomPolytope
34{
35public:
36
37    CustomPolytope() {}
38
39    typedef std::vector<Vec3d> Vertices;
40
41    struct Face
42    {
43        std::string name;
44        osg::Plane  plane;
45        Vertices    vertices;
46    };
47
48    Face& createFace() { _faces.push_back(Face()); return _faces.back(); }
49
50
51    /** Create a Polytope which is a cube, centered at 0,0,0, with sides of 2 units.*/
52    void setToUnitFrustum(bool withNear=true, bool withFar=true)
53    {
54        const osg::Vec3d v000(-1.0,-1.0,-1.0);
55        const osg::Vec3d v010(-1.0,1.0,-1.0);
56        const osg::Vec3d v001(-1.0,-1.0,1.0);
57        const osg::Vec3d v011(-1.0,1.0,1.0);
58        const osg::Vec3d v100(1.0,-1.0,-1.0);
59        const osg::Vec3d v110(1.0,1.0,-1.0);
60        const osg::Vec3d v101(1.0,-1.0,1.0);
61        const osg::Vec3d v111(1.0,1.0,1.0);
62
63        _faces.clear();
64
65        {   // left plane.
66            Face& face = createFace();
67            face.name = "left";
68            face.plane.set(1.0,0.0,0.0,1.0);
69            face.vertices.reserve(4);
70            face.vertices.push_back(v000);
71            face.vertices.push_back(v001);
72            face.vertices.push_back(v011);
73            face.vertices.push_back(v010);
74        }
75
76        {   // right plane.
77            Face& face = createFace();
78            face.name = "right";
79            face.plane.set(-1.0,0.0,0.0,1.0);
80            face.vertices.reserve(4);
81            face.vertices.push_back(v100);
82            face.vertices.push_back(v110);
83            face.vertices.push_back(v111);
84            face.vertices.push_back(v101);
85        }
86
87        {   // bottom plane.
88            Face& face = createFace();
89            face.name = "bottom";
90            face.plane.set(0.0,1.0,0.0,1.0);
91            face.vertices.reserve(4);
92            face.vertices.push_back(v000);
93            face.vertices.push_back(v100);
94            face.vertices.push_back(v101);
95            face.vertices.push_back(v001);
96        }
97
98        {   // top plane.
99            Face& face = createFace();
100            face.name = "top";
101            face.plane.set(0.0,-1.0,0.0,1.0);
102            face.vertices.reserve(4);
103            face.vertices.push_back(v111);
104            face.vertices.push_back(v011);
105            face.vertices.push_back(v010);
106            face.vertices.push_back(v110);
107        }
108
109        if (withNear)
110        {   // near plane
111            Face& face = createFace();
112            face.name = "near";
113            face.plane.set(0.0,0.0,1.0,1.0);
114            face.vertices.reserve(4);
115            face.vertices.push_back(v000);
116            face.vertices.push_back(v010);
117            face.vertices.push_back(v110);
118            face.vertices.push_back(v100);
119        }
120
121        if (withFar)
122        {   // far plane
123            Face& face = createFace();
124            face.name = "far";
125            face.plane.set(0.0,0.0,-1.0,1.0);
126            face.vertices.reserve(4);
127            face.vertices.push_back(v001);
128            face.vertices.push_back(v101);
129            face.vertices.push_back(v111);
130            face.vertices.push_back(v011);
131        }
132
133    }
134
135    void setToBoundingBox(const osg::BoundingBox& bb)
136    {
137#if 0
138        OSG_NOTICE<<"setToBoundingBox xrange "<<bb.xMin()<<" "<<bb.xMax()<<std::endl;
139        OSG_NOTICE<<"                        "<<bb.yMin()<<" "<<bb.yMax()<<std::endl;
140        OSG_NOTICE<<"                        "<<bb.zMin()<<" "<<bb.zMax()<<std::endl;
141#endif
142        const osg::Vec3d v000(bb.xMin(),bb.yMin(), bb.zMin());
143        const osg::Vec3d v010(bb.xMin(),bb.yMax(), bb.zMin());
144        const osg::Vec3d v001(bb.xMin(),bb.yMin(), bb.zMax());
145        const osg::Vec3d v011(bb.xMin(),bb.yMax(), bb.zMax());
146        const osg::Vec3d v100(bb.xMax(),bb.yMin(), bb.zMin());
147        const osg::Vec3d v110(bb.xMax(),bb.yMax(), bb.zMin());
148        const osg::Vec3d v101(bb.xMax(),bb.yMin(), bb.zMax());
149        const osg::Vec3d v111(bb.xMax(),bb.yMax(), bb.zMax());
150
151        _faces.clear();
152
153        {   // x min plane
154            Face& face = createFace();
155            face.name = "xMin";
156            face.plane.set(1.0,0.0,0.0,-bb.xMin());
157            face.vertices.reserve(4);
158            face.vertices.push_back(v000);
159            face.vertices.push_back(v001);
160            face.vertices.push_back(v011);
161            face.vertices.push_back(v010);
162        }
163
164        {   // x max plane.
165            Face& face = createFace();
166            face.name = "xMax";
167            face.plane.set(-1.0,0.0,0.0,bb.xMax());
168            face.vertices.reserve(4);
169            face.vertices.push_back(v100);
170            face.vertices.push_back(v110);
171            face.vertices.push_back(v111);
172            face.vertices.push_back(v101);
173        }
174
175        {   // y min plane.
176            Face& face = createFace();
177            face.name = "yMin";
178            face.plane.set(0.0,1.0,0.0,-bb.yMin());
179            face.vertices.reserve(4);
180            face.vertices.push_back(v000);
181            face.vertices.push_back(v100);
182            face.vertices.push_back(v101);
183            face.vertices.push_back(v001);
184        }
185
186        {   // y max plane.
187            Face& face = createFace();
188            face.name = "yMax";
189            face.plane.set(0.0,-1.0,0.0,bb.yMax());
190            face.vertices.reserve(4);
191            face.vertices.push_back(v111);
192            face.vertices.push_back(v011);
193            face.vertices.push_back(v010);
194            face.vertices.push_back(v110);
195        }
196        {   // z min plane
197            Face& face = createFace();
198            face.name = "zMin";
199            face.plane.set(0.0,0.0,1.0,-bb.zMin());
200            face.vertices.reserve(4);
201            face.vertices.push_back(v000);
202            face.vertices.push_back(v010);
203            face.vertices.push_back(v110);
204            face.vertices.push_back(v100);
205        }
206
207        {   // z max plane
208            Face& face = createFace();
209            face.name = "zMax";
210            face.plane.set(0.0,0.0,-1.0,bb.zMax());
211            face.vertices.reserve(4);
212            face.vertices.push_back(v001);
213            face.vertices.push_back(v101);
214            face.vertices.push_back(v111);
215            face.vertices.push_back(v011);
216        }
217
218    }
219
220    void transform(const osg::Matrix& matrix, const osg::Matrix& inverse)
221    {
222        for(Faces::iterator itr = _faces.begin();
223            itr != _faces.end();
224            ++itr)
225        {
226            Face& face = *itr;
227            face.plane.transformProvidingInverse(inverse);
228            for(Vertices::iterator vitr = face.vertices.begin();
229                vitr != face.vertices.end();
230                ++vitr)
231            {
232                *vitr = *vitr * matrix;
233            }
234        }
235    }
236
237
238    void insertVertex(const osg::Vec3d& vertex, osg::EllipsoidModel* em=0, double minHeight=0.0)
239    {
240        // OSG_NOTICE<<"Inserting vertex "<<vertex<<std::endl;
241
242        Faces removedFaces;
243
244        Faces::iterator itr;
245        for(itr = _faces.begin();
246            itr != _faces.end();
247            )
248        {
249            Face& face = *itr;
250            if (face.plane.distance(vertex)<0.0)
251            {
252                removedFaces.push_back(face);
253                itr = _faces.erase(itr);
254            }
255            else
256            {
257                ++itr;
258            }
259        }
260
261        if (removedFaces.empty()) return;
262
263        typedef std::pair<osg::Vec3d, osg::Vec3d> Edge;
264        typedef std::map<Edge,int> Edges;
265        Edges edges;
266
267        double numVerticesAdded=0.0;
268        osg::Vec3d center;
269        for(itr = removedFaces.begin();
270            itr != removedFaces.end();
271            ++itr)
272        {
273            Face& face = *itr;
274            Vertices& vertices = face.vertices;
275            for(unsigned int i=0; i<vertices.size(); ++i)
276            {
277                osg::Vec3d& a = vertices[i];
278                osg::Vec3d& b = vertices[ (i+1) % vertices.size()];
279                if (a<b) ++edges[Edge(a,b)];
280                else ++edges[Edge(b,a)];
281
282                center += a;
283                numVerticesAdded += 1.0;
284            }
285        }
286
287        if (numVerticesAdded==0.0) return;
288        center /= numVerticesAdded;
289
290        typedef std::set<osg::Vec3> VertexSet;
291        VertexSet uniqueVertices;
292
293        for(Edges::iterator eitr = edges.begin();
294            eitr != edges.end();
295            ++eitr)
296        {
297            if (eitr->second==1)
298            {
299                // OSG_NOTICE<<"     edge Ok"<<std::endl;
300                const Edge& edge = eitr->first;
301                Face face;
302                face.name = "baseSide";
303                face.plane.set(vertex, edge.first, edge.second);
304                face.vertices.push_back(vertex);
305                face.vertices.push_back(edge.first);
306                face.vertices.push_back(edge.second);
307                if (face.plane.distance(center)<0.0) face.plane.flip();
308                _faces.push_back(face);
309
310                uniqueVertices.insert(edge.first);
311                uniqueVertices.insert(edge.second);
312            }
313        }
314
315        // now trim the new polytope back the desired height
316        if (em)
317        {
318            // compute the base vertices at the new height
319            Vertices baseVertices;
320            for(VertexSet::iterator itr = uniqueVertices.begin();
321                itr != uniqueVertices.end();
322                ++itr)
323            {
324                const osg::Vec3d& point = *itr;
325                double latitude, longitude, height;
326                em->convertXYZToLatLongHeight(point.x(), point.y(), point.z(), latitude, longitude, height);
327                osg::Vec3d normal(point);
328                normal.normalize();
329                baseVertices.push_back(point - normal * (height - minHeight));
330            }
331
332            //compute centroid of the base vertices
333            osg::Vec3d center;
334            double totalArea = 0;
335            for(unsigned int i=0; i<baseVertices.size()-1; ++i)
336            {
337                const osg::Vec3d& a = baseVertices[i];
338                const osg::Vec3d& b = baseVertices[i+1];
339                const osg::Vec3d& c = baseVertices[(i+2)%baseVertices.size()];
340                double area = ((a-b)^(b-c)).length()*0.5;
341                osg::Vec3d localCenter = (a+b+c)/3.0;
342                center += localCenter*area;
343                totalArea += area;
344            }
345            center /= totalArea;
346            osg::Vec3d normal(center);
347            normal.normalize();
348
349            osg::Plane basePlane(normal, center);
350
351            cut(basePlane,"basePlane");
352        }
353
354
355        // OSG_NOTICE<<"  Removed faces "<<removedFaces.size()<<std::endl;
356    }
357
358
359    void projectDowntoBase(const osg::Vec3d& control, const osg::Vec3d& normal)
360    {
361        // OSG_NOTICE<<"CustomPolytope::projectDowntoBase not implementated yet."<<std::endl;
362
363        Faces removedFaces;
364
365        Faces::iterator itr;
366        for(itr = _faces.begin();
367            itr != _faces.end();
368            )
369        {
370            Face& face = *itr;
371            if ((face.plane.getNormal()*normal)>=0.0)
372            {
373                removedFaces.push_back(face);
374                itr = _faces.erase(itr);
375            }
376            else
377            {
378                ++itr;
379            }
380        }
381
382        if (removedFaces.empty()) return;
383
384        typedef std::pair<osg::Vec3d, osg::Vec3d> Edge;
385        typedef std::map<Edge,int> Edges;
386        Edges edges;
387
388        double numVerticesAdded=0.0;
389        osg::Vec3d center;
390        for(itr = removedFaces.begin();
391            itr != removedFaces.end();
392            ++itr)
393        {
394            Face& face = *itr;
395            Vertices& vertices = face.vertices;
396            for(unsigned int i=0; i<vertices.size(); ++i)
397            {
398                osg::Vec3d& a = vertices[i];
399                osg::Vec3d& b = vertices[ (i+1) % vertices.size()];
400                if (a<b) ++edges[Edge(a,b)];
401                else ++edges[Edge(b,a)];
402
403                center += a;
404                numVerticesAdded += 1.0;
405            }
406        }
407
408        if (numVerticesAdded==0.0) return;
409        center /= numVerticesAdded;
410
411        typedef std::set<osg::Vec3> VertexSet;
412        VertexSet uniqueVertices;
413
414        for(Edges::iterator eitr = edges.begin();
415            eitr != edges.end();
416            ++eitr)
417        {
418            if (eitr->second==1)
419            {
420                // OSG_NOTICE<<"     edge Ok"<<std::endl;
421                const Edge& edge = eitr->first;
422
423                double h_first = (edge.first-control) * normal;
424                osg::Vec3d projected_first = edge.first - normal * h_first;
425
426                double h_second = (edge.second-control) * normal;
427                osg::Vec3d projected_second = edge.second - normal * h_second;
428
429                Face face;
430                face.name = "baseSide";
431                face.plane.set(projected_first, edge.first, edge.second);
432                face.vertices.push_back(projected_first);
433                face.vertices.push_back(projected_second);
434                face.vertices.push_back(edge.second);
435                face.vertices.push_back(edge.first);
436
437                if (face.plane.distance(center)<0.0) face.plane.flip();
438                _faces.push_back(face);
439
440                uniqueVertices.insert(projected_first);
441                uniqueVertices.insert(projected_second);
442            }
443        }
444
445        Face newFace;
446        newFace.name = "basePlane";
447        newFace.plane.set(normal,control);
448
449        osg::Vec3d side = ( fabs(normal.x()) < fabs(normal.y()) ) ?
450                          osg::Vec3(1.0, 0.0, 0.0) :
451                          osg::Vec3(0.0, 1.0, 0.0);
452
453        osg::Vec3 v = normal ^ side;
454        v.normalize();
455
456        osg::Vec3 u = v ^ normal;
457        u.normalize();
458
459        typedef std::map<double, Vec3d> AnglePositions;
460        AnglePositions anglePositions;
461        for(VertexSet::iterator vitr = uniqueVertices.begin();
462            vitr != uniqueVertices.end();
463            ++vitr)
464        {
465            osg::Vec3d delta = *vitr - center;
466            double angle = atan2(delta * u, delta * v);
467            if (angle<0.0) angle += 2.0*osg::PI;
468            anglePositions[angle] = *vitr;
469        }
470
471        for(AnglePositions::iterator aitr = anglePositions.begin();
472            aitr != anglePositions.end();
473            ++aitr)
474        {
475            newFace.vertices.push_back(aitr->second);
476        }
477
478        _faces.push_back(newFace);
479
480
481    }
482
483    void computeSilhoette(const osg::Vec3d& normal, Vertices& vertices)
484    {
485
486        typedef std::pair<osg::Vec3d, osg::Vec3d> EdgePair;
487        typedef std::vector<Face*> EdgeFaces;
488        typedef std::map<EdgePair, EdgeFaces> EdgeMap;
489
490        EdgeMap edgeMap;
491
492
493        for(Faces::iterator itr = _faces.begin();
494            itr != _faces.end();
495            ++itr)
496        {
497            Face& face = *itr;
498            for(unsigned int i=0; i<face.vertices.size(); ++i)
499            {
500                osg::Vec3d& va = face.vertices[i];
501                osg::Vec3d& vb = face.vertices[(i+1)%face.vertices.size()];
502                if (va < vb) edgeMap[EdgePair(va,vb)].push_back(&face);
503                else edgeMap[EdgePair(vb,va)].push_back(&face);
504            }
505        }
506
507        typedef std::set<osg::Vec3> VertexSet;
508        VertexSet uniqueVertices;
509
510        for(EdgeMap::iterator eitr = edgeMap.begin();
511            eitr != edgeMap.end();
512            ++eitr)
513        {
514            const EdgePair& edge = eitr->first;
515            const EdgeFaces& edgeFaces = eitr->second;
516            if (edgeFaces.size()==1)
517            {
518                // OSG_NOTICE<<"Open edge found "<<edgeFaces.front()->name<<std::endl;
519            }
520            else if (edgeFaces.size()==2)
521            {
522
523                double dotProduct0 = edgeFaces[0]->plane.getNormal() * normal;
524                double dotProduct1 = edgeFaces[1]->plane.getNormal() * normal;
525                if (dotProduct0 * dotProduct1 <0.0)
526                {
527                    // OSG_NOTICE<<"  Silhoette edge found "<<edgeFaces[0]->name<<" "<<edgeFaces[1]->name<<std::endl;
528                    uniqueVertices.insert(edge.first);
529                    uniqueVertices.insert(edge.second);
530                }
531                else
532                {
533                    // OSG_NOTICE<<"  Non silhoette edge found "<<edgeFaces[0]->name<<" "<<edgeFaces[1]->name<<std::endl;
534                }
535
536            }
537            else
538            {
539                // OSG_NOTICE<<"Confused edge found "<<edgeFaces.size()<<std::endl;
540            }
541        }
542
543
544        // compute center
545        osg::Vec3d center;
546
547        VertexSet::iterator vitr;
548        for(vitr = uniqueVertices.begin();
549            vitr != uniqueVertices.end();
550            ++vitr)
551        {
552            center += *vitr;
553        }
554        center /= (double)(uniqueVertices.size());
555
556
557        // compute the ordered points around silhoette
558        osg::Vec3d side = ( fabs(normal.x()) < fabs(normal.y()) ) ?
559                          osg::Vec3(1.0, 0.0, 0.0) :
560                          osg::Vec3(0.0, 1.0, 0.0);
561
562        osg::Vec3 v = normal ^ side;
563        v.normalize();
564
565        osg::Vec3 u = v ^ normal;
566        u.normalize();
567
568        typedef std::map<double, Vec3d> AnglePositions;
569        AnglePositions anglePositions;
570        for(vitr = uniqueVertices.begin();
571            vitr != uniqueVertices.end();
572            ++vitr)
573        {
574            osg::Vec3d delta = *vitr - center;
575            double angle = atan2(delta * u, delta * v);
576            if (angle<0.0) angle += 2.0*osg::PI;
577            anglePositions[angle] = *vitr;
578        }
579
580        for(AnglePositions::iterator aitr = anglePositions.begin();
581            aitr != anglePositions.end();
582            ++aitr)
583        {
584            vertices.push_back(aitr->second);
585        }
586
587
588    }
589
590
591    void cut(const osg::Polytope& polytope)
592    {
593        // OSG_NOTICE<<"Cutting with polytope "<<std::endl;
594        for(osg::Polytope::PlaneList::const_iterator itr = polytope.getPlaneList().begin();
595            itr != polytope.getPlaneList().end();
596            ++itr)
597        {
598            cut(*itr);
599        }
600    }
601
602    void cut(const CustomPolytope& polytope)
603    {
604        // OSG_NOTICE<<"Cutting with polytope "<<std::endl;
605        for(Faces::const_iterator itr = polytope._faces.begin();
606            itr != polytope._faces.end();
607            ++itr)
608        {
609            cut(itr->plane, itr->name);
610        }
611    }
612
613    void cut(const osg::Plane& plane, const std::string& name=std::string())
614    {
615        // OSG_NOTICE<<"  Cutting plane "<<plane<<std::endl;
616        Face newFace;
617        typedef std::vector<double> Distances;
618        Distances distances;
619        Vertices newVertices;
620
621        for(Faces::iterator itr = _faces.begin();
622            itr != _faces.end();
623            )
624        {
625            Face& face = *itr;
626            int intersect = plane.intersect(face.vertices);
627            if (intersect==1)
628            {
629                // OSG_NOTICE<<"    Face inside"<<std::endl;
630                ++itr;
631            }
632            else if (intersect==0)
633            {
634                // OSG_NOTICE<<"    Face intersecting - before "<<face.vertices.size()<<std::endl;
635
636                Vertices& vertices = face.vertices;
637                newVertices.clear();
638
639                distances.clear();
640                distances.reserve(face.vertices.size());
641                for(Vertices::iterator vitr = vertices.begin();
642                    vitr != vertices.end();
643                    ++vitr)
644                {
645                    distances.push_back(plane.distance(*vitr));
646                }
647
648                for(unsigned int i=0; i<vertices.size(); ++i)
649                {
650                    osg::Vec3d& va = vertices[i];
651                    osg::Vec3d& vb = vertices[(i+1)%vertices.size()];
652                    double distance_a = distances[i];
653                    double distance_b = distances[(i+1)%vertices.size()];
654
655                    // is first edge point inside plane?
656                    if (distance_a>=0.0) newVertices.push_back(vertices[i]);
657
658                    // add point to new face if point exactly on a plane
659                    if (distance_a==0.0) newFace.vertices.push_back(vertices[i]);
660
661                    // does edge intersect plane
662                    if (distance_a * distance_b<0.0)
663                    {
664                        // inserting vertex
665                        osg::Vec3d intersection = (vb*distance_a - va*distance_b)/(distance_a-distance_b);
666                        newVertices.push_back(intersection);
667                        newFace.vertices.push_back(intersection);
668
669                        // OSG_NOTICE<<"  intersection distance "<<plane.distance(intersection)<<std::endl;
670                    }
671                }
672
673                vertices.swap(newVertices);
674
675                // OSG_NOTICE<<"        intersecting - after "<<face.vertices.size()<<std::endl;
676
677                ++itr;
678            }
679            else if (intersect==-1)
680            {
681                // OSG_NOTICE<<"    Face outside"<<_faces.size()<<std::endl;
682                itr = _faces.erase(itr);
683            }
684        }
685
686        if (!newFace.vertices.empty())
687        {
688            // OSG_NOTICE<<"    inserting newFace intersecting "<<newFace.vertices.size()<<std::endl;
689            newFace.name = name;
690            newFace.plane = plane;
691
692            Vertices& vertices = newFace.vertices;
693
694            osg::Vec3d side = ( fabs(plane.getNormal().x()) < fabs(plane.getNormal().y()) ) ?
695                              osg::Vec3(1.0, 0.0, 0.0) :
696                              osg::Vec3(0.0, 1.0, 0.0);
697
698            osg::Vec3 v = plane.getNormal() ^ side;
699            v.normalize();
700
701            osg::Vec3 u = v ^ plane.getNormal();
702            u.normalize();
703
704            osg::Vec3d center;
705            Vertices::iterator vitr;
706            for(vitr = vertices.begin();
707                vitr != vertices.end();
708                ++vitr)
709            {
710                center += *vitr;
711            }
712            center /= vertices.size();
713
714            typedef std::map<double, Vec3d> AnglePositions;
715            AnglePositions anglePositions;
716            for(vitr = vertices.begin();
717                vitr != vertices.end();
718                ++vitr)
719            {
720                osg::Vec3d delta = *vitr - center;
721                double angle = atan2(delta * u, delta * v);
722                if (angle<0.0) angle += 2.0*osg::PI;
723                anglePositions[angle] = *vitr;
724            }
725
726
727            newVertices.clear();
728            newVertices.reserve(anglePositions.size());
729            for(AnglePositions::iterator aitr = anglePositions.begin();
730                aitr != anglePositions.end();
731                ++aitr)
732            {
733                newVertices.push_back(aitr->second);
734            }
735
736            newVertices.swap(vertices);
737
738            // OSG_NOTICE<<"     after angle sort  "<<newFace.vertices.size()<<std::endl;
739
740            _faces.push_back(newFace);
741        }
742    }
743
744    void getPolytope(osg::Polytope& polytope)
745    {
746        for(Faces::const_iterator itr = _faces.begin();
747            itr != _faces.end();
748            ++itr)
749        {
750            polytope.add(itr->plane);
751        }
752    }
753
754    void getPoints(Vertices& vertices)
755    {
756        typedef std::set<osg::Vec3d> VerticesSet;
757        VerticesSet verticesSet;
758        for(Faces::iterator itr = _faces.begin();
759            itr != _faces.end();
760            ++itr)
761        {
762            Face& face = *itr;
763            for(Vertices::iterator vitr = face.vertices.begin();
764                vitr != face.vertices.end();
765                ++vitr)
766            {
767                verticesSet.insert(*vitr);
768            }
769        }
770
771        for(VerticesSet::iterator sitr = verticesSet.begin();
772            sitr != verticesSet.end();
773            ++sitr)
774        {
775            vertices.push_back(*sitr);
776        }
777    }
778
779
780    osg::Drawable* createDrawable(const osg::Vec4d& colour)
781    {
782        osg::Geometry* geometry = new osg::Geometry;
783        osg::Vec3Array* vertices = new osg::Vec3Array;
784        geometry->setVertexArray(vertices);
785
786        for(Faces::iterator itr = _faces.begin();
787            itr != _faces.end();
788            ++itr)
789        {
790            Face& face = *itr;
791            geometry->addPrimitiveSet( new osg::DrawArrays(GL_LINE_LOOP, vertices->size(), face.vertices.size()) );
792            for(Vertices::iterator vitr = face.vertices.begin();
793                vitr != face.vertices.end();
794                ++vitr)
795            {
796                vertices->push_back(*vitr);
797            }
798        }
799
800        osg::Vec4Array* colours = new osg::Vec4Array;
801        colours->push_back(colour);
802        geometry->setColorArray(colours);
803        geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
804
805        osg::StateSet* stateset = geometry->getOrCreateStateSet();
806        stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
807        stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF);
808        stateset->setTextureMode(1, GL_TEXTURE_2D, osg::StateAttribute::OFF);
809
810        return geometry;
811    }
812
813protected:
814
815    typedef std::list<Face> Faces;
816    Faces _faces;
817
818
819};
820
821}
822
823
824OverlayNode::OverlayNode(OverlayTechnique technique):
825    _overlayTechnique(technique),
826    _texEnvMode(GL_DECAL),
827    _textureUnit(1),
828    _textureSizeHint(1024),
829    _overlayClearColor(0.0f,0.0f,0.0f,0.0f),
830    _continuousUpdate(false),
831    _overlayBaseHeight(-100.0),
832    _updateCamera(false),
833    _renderTargetImpl(osg::Camera::FRAME_BUFFER_OBJECT)
834{
835    setNumChildrenRequiringUpdateTraversal(1);
836    init();
837}
838
839OverlayNode::OverlayNode(const OverlayNode& copy, const osg::CopyOp& copyop):
840    osg::Group(copy,copyop),
841    _overlayTechnique(copy._overlayTechnique),
842    _overlaySubgraph(copy._overlaySubgraph),
843    _texEnvMode(copy._texEnvMode),
844    _textureUnit(copy._textureUnit),
845    _textureSizeHint(copy._textureSizeHint),
846    _overlayClearColor(copy._overlayClearColor),
847    _continuousUpdate(copy._continuousUpdate),
848    _overlayBaseHeight(copy._overlayBaseHeight),
849    _updateCamera(false),
850    _renderTargetImpl(copy._renderTargetImpl)
851{
852    setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);
853    init();
854}
855
856void OverlayNode::OverlayData::setThreadSafeRefUnref(bool threadSafe)
857{
858    if (_camera.valid()) _camera->setThreadSafeRefUnref(threadSafe);
859    if (_texgenNode.valid()) _texgenNode->setThreadSafeRefUnref(threadSafe);
860    if (_overlayStateSet.valid()) _overlayStateSet->setThreadSafeRefUnref(threadSafe);
861    if (_mainSubgraphStateSet.valid()) _mainSubgraphStateSet->setThreadSafeRefUnref(threadSafe);
862    if (_texture.valid()) _texture->setThreadSafeRefUnref(threadSafe);
863}
864
865void OverlayNode::OverlayData::resizeGLObjectBuffers(unsigned int maxSize)
866{
867    if (_camera.valid()) _camera->resizeGLObjectBuffers(maxSize);
868    if (_texgenNode.valid()) _texgenNode->resizeGLObjectBuffers(maxSize);
869    if (_overlayStateSet.valid()) _overlayStateSet->resizeGLObjectBuffers(maxSize);
870    if (_mainSubgraphStateSet.valid()) _mainSubgraphStateSet->resizeGLObjectBuffers(maxSize);
871    if (_texture.valid()) _texture->resizeGLObjectBuffers(maxSize);
872}
873
874void OverlayNode::OverlayData::releaseGLObjects(osg::State* state) const
875{
876    if (_camera.valid()) _camera->releaseGLObjects(state);
877    if (_texgenNode.valid()) _texgenNode->releaseGLObjects(state);
878    if (_overlayStateSet.valid()) _overlayStateSet->releaseGLObjects(state);
879    if (_mainSubgraphStateSet.valid()) _mainSubgraphStateSet->releaseGLObjects(state);
880    if (_texture.valid()) _texture->releaseGLObjects(state);
881}
882
883void OverlayNode::setThreadSafeRefUnref(bool threadSafe)
884{
885    osg::Group::setThreadSafeRefUnref(threadSafe);
886
887    if (_overlaySubgraph.valid()) _overlaySubgraph->setThreadSafeRefUnref(threadSafe);
888
889    for(OverlayDataMap::iterator itr = _overlayDataMap.begin();
890        itr != _overlayDataMap.end();
891        ++itr)
892    {
893        itr->second->setThreadSafeRefUnref(threadSafe);
894    }
895}
896
897void OverlayNode::resizeGLObjectBuffers(unsigned int maxSize)
898{
899    osg::Group::resizeGLObjectBuffers(maxSize);
900
901    if (_overlaySubgraph.valid()) _overlaySubgraph->resizeGLObjectBuffers(maxSize);
902
903    for(OverlayDataMap::iterator itr = _overlayDataMap.begin();
904        itr != _overlayDataMap.end();
905        ++itr)
906    {
907        itr->second->resizeGLObjectBuffers(maxSize);
908    }
909}
910
911void OverlayNode::releaseGLObjects(osg::State* state) const
912{
913    osg::Group::releaseGLObjects(state);
914
915    if (_overlaySubgraph.valid()) _overlaySubgraph->releaseGLObjects(state);
916
917    for(OverlayDataMap::const_iterator itr = _overlayDataMap.begin();
918        itr != _overlayDataMap.end();
919        ++itr)
920    {
921        itr->second->releaseGLObjects(state);
922    }
923}
924
925void OverlayNode::setOverlayTechnique(OverlayTechnique technique)
926{
927    if (_overlayTechnique==technique) return;
928
929    _overlayTechnique = technique;
930
931    init();
932}
933
934void OverlayNode::setRenderTargetImplementation(osg::Camera::RenderTargetImplementation impl)
935{
936    if(_renderTargetImpl==impl) return;
937
938    _renderTargetImpl = impl;
939
940    init();
941    for(OverlayDataMap::const_iterator itr = _overlayDataMap.begin();
942      itr != _overlayDataMap.end();
943      ++itr)
944    {
945      itr->second->_camera->setRenderTargetImplementation(_renderTargetImpl);
946    }
947}
948
949OverlayNode::OverlayData* OverlayNode::getOverlayData(osgUtil::CullVisitor* cv)
950{
951    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_overlayDataMapMutex);
952    OverlayDataMap::iterator itr = _overlayDataMap.find(cv);
953    if (itr != _overlayDataMap.end()) return itr->second.get();
954
955    _overlayDataMap[cv] = new OverlayData;
956
957    OverlayData* overlayData = _overlayDataMap[cv].get();
958
959
960    unsigned int tex_width = _textureSizeHint;
961    unsigned int tex_height = _textureSizeHint;
962
963    if (!overlayData->_texture)
964    {
965        // OSG_NOTICE<<"   setting up texture"<<std::endl;
966
967        osg::Texture2D* texture = new osg::Texture2D;
968        texture->setTextureSize(tex_width, tex_height);
969        texture->setInternalFormat(GL_RGBA);
970        texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
971        texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
972        texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
973        texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
974#if 1
975        texture->setBorderColor(osg::Vec4(_overlayClearColor));
976#else
977        texture->setBorderColor(osg::Vec4(1.0,0.0,0.0,0.5));
978#endif
979        overlayData->_texture = texture;
980    }
981
982    // set up the render to texture camera.
983    if (!overlayData->_camera || overlayData->_camera->getRenderTargetImplementation() != _renderTargetImpl)
984    {
985        // OSG_NOTICE<<"   setting up camera"<<std::endl;
986
987        // create the camera
988        overlayData->_camera = new osg::Camera;
989
990        overlayData->_camera->setClearColor(_overlayClearColor);
991
992        overlayData->_camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
993
994        // set viewport
995        overlayData->_camera->setViewport(0,0,tex_width,tex_height);
996
997        overlayData->_camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
998
999        // set the camera to render before the main camera.
1000        overlayData->_camera->setRenderOrder(osg::Camera::PRE_RENDER);
1001
1002        // tell the camera to use OpenGL frame buffer object where supported.
1003        overlayData->_camera->setRenderTargetImplementation(_renderTargetImpl);
1004
1005        // attach the texture and use it as the color buffer.
1006        overlayData->_camera->attach(osg::Camera::COLOR_BUFFER, overlayData->_texture.get());
1007
1008        if (_overlaySubgraph.valid()) overlayData->_camera->addChild(_overlaySubgraph.get());
1009    }
1010
1011    if (!overlayData->_texgenNode)
1012    {
1013        overlayData->_texgenNode = new osg::TexGenNode;
1014        overlayData->_texgenNode->setTextureUnit(_textureUnit);
1015    }
1016
1017    if (!overlayData->_y0) overlayData->_y0 = new osg::Uniform("y0",0.0f);
1018    if (!overlayData->_lightingEnabled) overlayData->_lightingEnabled = new osg::Uniform("lightingEnabled",true);
1019
1020    if (!overlayData->_overlayStateSet)
1021    {
1022        overlayData->_overlayStateSet = new osg::StateSet;
1023        overlayData->_overlayStateSet->addUniform(overlayData->_y0.get());
1024        overlayData->_overlayStateSet->addUniform(overlayData->_lightingEnabled.get());
1025
1026        osg::Program* program = new osg::Program;
1027        overlayData->_overlayStateSet->setAttribute(program);
1028
1029        // get shaders from source
1030        std::string vertexShaderFile = osgDB::findDataFile("shaders/overlay_perspective_rtt.vert");
1031        if (!vertexShaderFile.empty())
1032        {
1033            program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, vertexShaderFile));
1034        }
1035        else
1036        {
1037            char vertexShaderSource[] =
1038                "uniform float y0; \n"
1039                "uniform bool lightingEnabled; \n"
1040                " \n"
1041                "vec4 warp(in vec4 source) \n"
1042                "{ \n"
1043                "    float divisor = source.y + y0; \n"
1044                "    return vec4(source.x * (1.0 + y0 ), source.y * y0 + 1.0, (source.z * y0 + 1.0)*0.01, source.w * divisor); \n"
1045                "} \n"
1046                " \n"
1047                "vec3 fnormal(void) \n"
1048                "{ \n"
1049                "    //Compute the normal  \n"
1050                "    vec3 normal = gl_NormalMatrix * gl_Normal; \n"
1051                "    normal = normalize(normal); \n"
1052                "    return normal; \n"
1053                "} \n"
1054                " \n"
1055                "void directionalLight(in int i, \n"
1056                "                      in vec3 normal, \n"
1057                "                      inout vec4 ambient, \n"
1058                "                      inout vec4 diffuse, \n"
1059                "                      inout vec4 specular) \n"
1060                "{ \n"
1061                "   float nDotVP;         // normal . light direction \n"
1062                "   float nDotHV;         // normal . light half vector \n"
1063                "   float pf;             // power factor \n"
1064                " \n"
1065                "   nDotVP = max(0.0, dot(normal, normalize(vec3 (gl_LightSource[i].position)))); \n"
1066                "   nDotHV = max(0.0, dot(normal, vec3 (gl_LightSource[i].halfVector))); \n"
1067                " \n"
1068                "   if (nDotVP == 0.0) \n"
1069                "   { \n"
1070                "       pf = 0.0; \n"
1071                "   } \n"
1072                "   else \n"
1073                "   { \n"
1074                "       pf = pow(nDotHV, gl_FrontMaterial.shininess); \n"
1075                " \n"
1076                "   } \n"
1077                "   ambient  += gl_LightSource[i].ambient; \n"
1078                "   diffuse  += gl_LightSource[i].diffuse * nDotVP; \n"
1079                "   specular += gl_LightSource[i].specular * pf; \n"
1080                "} \n"
1081                "void main() \n"
1082                "{ \n"
1083                "    gl_Position = warp(ftransform()); \n"
1084                " \n"
1085                "    if (lightingEnabled) \n"
1086                "    {     \n"
1087                "        vec4 ambient = vec4(0.0); \n"
1088                "        vec4 diffuse = vec4(0.0); \n"
1089                "        vec4 specular = vec4(0.0); \n"
1090                " \n"
1091                "        vec3 normal = fnormal(); \n"
1092                " \n"
1093                "        directionalLight(0, normal, ambient, diffuse, specular); \n"
1094                " \n"
1095                "        vec4 color = gl_FrontLightModelProduct.sceneColor + \n"
1096                "                     ambient  * gl_FrontMaterial.ambient + \n"
1097                "                     diffuse  * gl_FrontMaterial.diffuse + \n"
1098                "                     specular * gl_FrontMaterial.specular; \n"
1099                " \n"
1100                "        gl_FrontColor = color; \n"
1101                " \n"
1102                "    } \n"
1103                "    else \n"
1104                "    { \n"
1105                "        gl_FrontColor = gl_Color; \n"
1106                "    } \n"
1107                "   \n"
1108                "} \n";
1109
1110            osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource);
1111            program->addShader(vertex_shader);
1112        }
1113
1114    }
1115
1116    if (!overlayData->_mainSubgraphProgram)
1117    {
1118        overlayData->_mainSubgraphProgram = new osg::Program;
1119
1120        // get shaders from source
1121        std::string fragmentShaderFile = osgDB::findDataFile("shaders/overlay_perspective_main.frag");
1122        if (!fragmentShaderFile.empty())
1123        {
1124            overlayData->_mainSubgraphProgram->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, fragmentShaderFile));
1125        }
1126        else
1127        {
1128            char fragmentShaderSource[] =
1129                "uniform sampler2D texture_0; \n"
1130                "uniform sampler2D texture_1; \n"
1131                " \n"
1132                "uniform float y0; \n"
1133                " \n"
1134                "vec2 warp(in vec2 source) \n"
1135                "{ \n"
1136                "    float inv_divisor = 1.0 / (source.y + y0); \n"
1137                "    return vec2(source.x * (1.0 + y0 ) * inv_divisor , (source.y * y0 + 1.0 ) * inv_divisor); \n"
1138                "} \n"
1139                " \n"
1140                "void main() \n"
1141                "{ \n"
1142                "    vec2 coord = gl_TexCoord[1].xy; \n"
1143                "    coord.x = coord.x*2.0 - 1.0; \n"
1144                "    coord.y = coord.y*2.0 - 1.0; \n"
1145                " \n"
1146                "    vec2 warped = warp(coord); \n"
1147                "    warped.x = (warped.x + 1.0)*0.5; \n"
1148                "    warped.y = (warped.y + 1.0)*0.5; \n"
1149                " \n"
1150                "    vec4 base_color = texture2D(texture_0, gl_TexCoord[0].xy); \n"
1151                "    vec4 overlay_color = texture2D(texture_1, warped ); \n"
1152                "    vec3 mixed_color = mix(base_color.rgb, overlay_color.rgb, overlay_color.a); \n"
1153                "    gl_FragColor = vec4(mixed_color, base_color.a); \n"
1154                "} \n";
1155
1156            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource);
1157            overlayData->_mainSubgraphProgram->addShader(fragment_shader);
1158        }
1159    }
1160
1161    if (!overlayData->_mainSubgraphStateSet)
1162    {
1163        overlayData->_mainSubgraphStateSet = new osg::StateSet;
1164
1165        overlayData->_mainSubgraphStateSet->addUniform(overlayData->_y0.get());
1166        overlayData->_mainSubgraphStateSet->addUniform(new osg::Uniform("texture_0",0));
1167        overlayData->_mainSubgraphStateSet->addUniform(new osg::Uniform("texture_1",1));
1168
1169        overlayData->_mainSubgraphStateSet->setTextureAttributeAndModes(_textureUnit, overlayData->_texture.get(), osg::StateAttribute::ON);
1170        overlayData->_mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_S, osg::StateAttribute::ON);
1171        overlayData->_mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_T, osg::StateAttribute::ON);
1172        overlayData->_mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_R, osg::StateAttribute::ON);
1173        overlayData->_mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_Q, osg::StateAttribute::ON);
1174
1175        if (_texEnvMode!=GL_NONE)
1176        {
1177            overlayData->_mainSubgraphStateSet->setTextureAttribute(_textureUnit, new osg::TexEnv((osg::TexEnv::Mode)_texEnvMode));
1178        }
1179    }
1180
1181    return overlayData;
1182}
1183
1184void OverlayNode::init()
1185{
1186    switch(_overlayTechnique)
1187    {
1188        case(OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY):
1189            init_OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY();
1190            break;
1191        case(VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY):
1192            init_VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY();
1193            break;
1194        case(VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY):
1195            init_VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY();
1196            break;
1197    }
1198}
1199
1200void OverlayNode::init_OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY()
1201{
1202    OSG_INFO<<"OverlayNode::init() - OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY"<<std::endl;
1203
1204    // force initialization of _overlayDataMap for the key 0 (or NULL)
1205    getOverlayData(0);
1206}
1207
1208void OverlayNode::init_VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY()
1209{
1210    OSG_INFO<<"OverlayNode::init() - VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY"<<std::endl;
1211}
1212
1213void OverlayNode::init_VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY()
1214{
1215    OSG_INFO<<"OverlayNode::init() - VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY"<<std::endl;
1216}
1217
1218void OverlayNode::traverse(osg::NodeVisitor& nv)
1219{
1220    switch(_overlayTechnique)
1221    {
1222        case(OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY):
1223            traverse_OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY(nv);
1224            break;
1225        case(VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY):
1226            traverse_VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY(nv);
1227            break;
1228        case(VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY):
1229            traverse_VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY(nv);
1230            break;
1231    }
1232}
1233
1234void OverlayNode::traverse_OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY(osg::NodeVisitor& nv)
1235{
1236    OverlayData& overlayData = *getOverlayData(0);
1237    osg::Camera* camera = overlayData._camera.get();
1238
1239    if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
1240    {
1241
1242        Group::traverse(nv);
1243
1244        if (_continuousUpdate || _updateCamera)
1245        {
1246
1247
1248            // now compute the camera's view and projection matrix to point at the shadower (the camera's children)
1249            osg::BoundingSphere bs;
1250            for(unsigned int i=0; i<camera->getNumChildren(); ++i)
1251            {
1252                bs.expandBy(camera->getChild(i)->getBound());
1253            }
1254
1255            if (bs.valid())
1256            {
1257                // see if we are within a coordinate system node.
1258                osg::CoordinateSystemNode* csn = 0;
1259                osg::NodePath& nodePath = nv.getNodePath();
1260                for(osg::NodePath::reverse_iterator itr = nodePath.rbegin();
1261                    itr != nodePath.rend() && csn==0;
1262                    ++itr)
1263                {
1264                    csn = dynamic_cast<osg::CoordinateSystemNode*>(*itr);
1265                }
1266
1267                osg::EllipsoidModel* em = csn ? csn->getEllipsoidModel() : 0;
1268
1269
1270                if (em)
1271                {
1272                    osg::Vec3d eyePoint(0.0,0.0,0.0); // center of the planet
1273                    double centerDistance = (eyePoint-osg::Vec3d(bs.center())).length();
1274
1275                    double znear = centerDistance-bs.radius();
1276                    double zfar  = centerDistance+bs.radius();
1277                    double zNearRatio = 0.001f;
1278                    if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
1279
1280                    double top   = (bs.radius()/centerDistance)*znear;
1281                    double right = top;
1282
1283                    camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar);
1284                    camera->setViewMatrixAsLookAt(eyePoint, bs.center(), osg::Vec3(0.0f,1.0f,0.0f));
1285                }
1286                else
1287                {
1288                    osg::Vec3d upDirection(0.0,1.0,0.0);
1289                    osg::Vec3d viewDirection(0.0,0.0,1.0);
1290
1291                    double viewDistance = 2.0*bs.radius();
1292                    osg::Vec3d center = bs.center();
1293                    osg::Vec3d eyePoint = center+viewDirection*viewDistance;
1294
1295                    double znear = viewDistance-bs.radius();
1296                    double zfar  = viewDistance+bs.radius();
1297
1298                    float top   = bs.radius();
1299                    float right = top;
1300
1301                    camera->setProjectionMatrixAsOrtho(-right,right,-top,top,znear,zfar);
1302                    camera->setViewMatrixAsLookAt(eyePoint,center,upDirection);
1303
1304                }
1305
1306
1307                // compute the matrix which takes a vertex from local coords into tex coords
1308                // will use this later to specify osg::TexGen..
1309                osg::Matrix MVP = camera->getViewMatrix() *
1310                                  camera->getProjectionMatrix();
1311
1312                osg::Matrix MVPT = MVP *
1313                                   osg::Matrix::translate(1.0,1.0,1.0) *
1314                                   osg::Matrix::scale(0.5,0.5,0.5);
1315
1316                overlayData._texgenNode->getTexGen()->setMode(osg::TexGen::EYE_LINEAR);
1317                overlayData._texgenNode->getTexGen()->setPlanesFromMatrix(MVPT);
1318
1319                overlayData._textureFrustum.setToUnitFrustum(false,false);
1320                overlayData._textureFrustum.transformProvidingInverse(MVP);
1321            }
1322            _updateCamera = false;
1323        }
1324
1325        return;
1326    }
1327
1328    if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)
1329    {
1330        Group::traverse(nv);
1331        return;
1332    }
1333
1334    osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
1335    if (!cv)
1336    {
1337        Group::traverse(nv);
1338        return;
1339    }
1340
1341
1342    unsigned int contextID = cv->getState()!=0 ? cv->getState()->getContextID() : 0;
1343
1344    // if we need to redraw then do cull traversal on camera.
1345    if (!_textureObjectValidList[contextID] || _continuousUpdate)
1346    {
1347        camera->setClearColor(_overlayClearColor);
1348        camera->accept(*cv);
1349        _textureObjectValidList[contextID] = 1;
1350    }
1351
1352
1353    // now set up the drawing of the main scene.
1354    {
1355
1356        overlayData._texgenNode->accept(*cv);
1357
1358        const osg::Matrix modelView = *(cv->getModelViewMatrix());
1359        osg::Polytope viewTextureFrustum;
1360        viewTextureFrustum.setAndTransformProvidingInverse(overlayData._textureFrustum, osg::Matrix::inverse(modelView));
1361
1362        cv->getProjectionCullingStack().back().addStateFrustum(overlayData._mainSubgraphStateSet.get(), viewTextureFrustum);
1363        cv->getCurrentCullingSet().addStateFrustum(overlayData._mainSubgraphStateSet.get(), overlayData._textureFrustum);
1364
1365        // push the stateset.
1366        // cv->pushStateSet(_mainSubgraphStateSet.get());
1367
1368        Group::traverse(nv);
1369
1370        // cv->popStateSet();
1371
1372        cv->getCurrentCullingSet().getStateFrustumList().pop_back();
1373        cv->getProjectionCullingStack().back().getStateFrustumList().pop_back();
1374    }
1375}
1376
1377void OverlayNode::traverse_VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY(osg::NodeVisitor& nv)
1378{
1379    // OSG_NOTICE<<"OverlayNode::traverse() - VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY"<<std::endl;
1380
1381
1382    if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)
1383    {
1384        Group::traverse(nv);
1385        return;
1386    }
1387
1388    osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
1389    if (!cv)
1390    {
1391        Group::traverse(nv);
1392        return;
1393    }
1394
1395    OverlayData& overlayData = *getOverlayData(cv);
1396    osg::Camera* camera = overlayData._camera.get();
1397
1398    if (_overlaySubgraph.valid())
1399    {
1400
1401#if 0
1402        if (!overlayData._geode)
1403        {
1404            overlayData._geode = new osg::Geode;
1405        }
1406#endif
1407        // see if we are within a coordinate system node.
1408        osg::CoordinateSystemNode* csn = 0;
1409        osg::NodePath& nodePath = nv.getNodePath();
1410        for(osg::NodePath::reverse_iterator itr = nodePath.rbegin();
1411            itr != nodePath.rend() && csn==0;
1412            ++itr)
1413        {
1414            csn = dynamic_cast<osg::CoordinateSystemNode*>(*itr);
1415        }
1416
1417        osg::EllipsoidModel* em = csn ? csn->getEllipsoidModel() : 0;
1418
1419        osg::BoundingSphere bs = _overlaySubgraph->getBound();
1420
1421        // push the stateset.
1422        cv->pushStateSet(overlayData._mainSubgraphStateSet.get());
1423
1424        Group::traverse(nv);
1425
1426        cv->popStateSet();
1427
1428        osg::Matrix pm = *(cv->getProjectionMatrix());
1429
1430        double znear = cv->getCalculatedNearPlane();
1431        double zfar = cv->getCalculatedFarPlane();
1432
1433        // OSG_NOTICE<<" before znear ="<<znear<<"\t zfar ="<<zfar<<std::endl;
1434
1435        cv->computeNearPlane();
1436
1437        znear = cv->getCalculatedNearPlane();
1438        zfar = cv->getCalculatedFarPlane();
1439
1440        // OSG_NOTICE<<" after znear ="<<znear<<"\t zfar ="<<zfar<<std::endl;
1441
1442        // OSG_NOTICE<<" before clamp pm="<<pm<<std::endl;
1443
1444        cv->clampProjectionMatrixImplementation(pm, znear,zfar);
1445
1446        // OSG_NOTICE<<" after clamp pm="<<pm<<std::endl;
1447
1448        osg::Matrix MVP = *(cv->getModelViewMatrix()) * pm;
1449        osg::Matrix inverseMVP;
1450        inverseMVP.invert(MVP);
1451
1452        // create polytope for the view frustum in local coords
1453        CustomPolytope frustum;
1454#if 0
1455        frustum.setToUnitFrustum(false, false);
1456#else
1457        frustum.setToUnitFrustum(true, true);
1458#endif
1459        frustum.transform(inverseMVP, MVP);
1460
1461
1462        // create polytope for the overlay subgraph in local coords
1463        CustomPolytope overlayPolytope;
1464
1465        // get the bounds of the model.
1466        osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
1467        _overlaySubgraph->accept(cbbv);
1468        overlayPolytope.setToBoundingBox(cbbv.getBoundingBox());
1469
1470        if (em)
1471        {
1472            overlayPolytope.insertVertex(osg::Vec3d(0.0,0.0,0.0), em, _overlayBaseHeight);
1473        }
1474        else
1475        {
1476            overlayPolytope.projectDowntoBase(osg::Vec3d(0.0,0.0,_overlayBaseHeight), osg::Vec3d(0.0,0.0,1.0));
1477        }
1478
1479
1480        if (overlayData._geode.valid() && overlayData._geode->getNumDrawables()>100)
1481        {
1482            overlayData._geode->removeDrawables(0, 3);
1483        }
1484
1485        if (overlayData._geode.valid())
1486        {
1487            overlayData._geode->addDrawable(overlayPolytope.createDrawable(osg::Vec4d(1.0f,1.0f,0.0f,1.0f)));
1488            overlayData._geode->addDrawable(frustum.createDrawable(osg::Vec4d(0.0f,0.0f,1.0f,1.0f)));
1489        }
1490
1491
1492
1493
1494
1495        // OSG_NOTICE<<"AFTER CUT corners = "<<corners.size()<<std::endl;
1496
1497
1498        osg::Vec3d center = _overlaySubgraph->getBound().center();
1499
1500        osg::Vec3d lookVector(0.0,0.0,-1.0);
1501        if (em)
1502        {
1503            lookVector = -center;
1504            lookVector.normalize();
1505        }
1506
1507        osg::Vec3d sideVectorLV = lookVector ^ cv->getLookVectorLocal();
1508        osg::Vec3d sideVectorUP = lookVector ^ cv->getUpLocal();
1509
1510        osg::Vec3d sideVector = sideVectorLV.length() > sideVectorUP.length() ?
1511            sideVectorLV :
1512            sideVectorUP;
1513
1514        sideVector.normalize();
1515
1516        osg::Vec3d upVector = sideVector ^ lookVector;
1517        upVector.normalize();
1518
1519        osg::Vec3d overlayLookVector = upVector ^ sideVector;
1520        overlayLookVector.normalize();
1521
1522
1523        overlayPolytope.cut(frustum);
1524
1525        CustomPolytope::Vertices corners;
1526#if 0
1527        overlayPolytope.getPoints(corners);
1528#else
1529        overlayPolytope.computeSilhoette(lookVector, corners);
1530#endif
1531        if (corners.empty())
1532        {
1533            camera->setClearColor(_overlayClearColor);
1534            //camera->setStateSet(overlayData._overlayStateSet.get());
1535            camera->accept(*cv);
1536            return;
1537        }
1538
1539        if (overlayData._geode.valid())
1540        {
1541            overlayData._geode->addDrawable(overlayPolytope.createDrawable(osg::Vec4d(1.0f,1.0f,1.0f,1.0f)));
1542        }
1543
1544
1545        // OSG_NOTICE<<"    lookVector ="<<lookVector<<std::endl;
1546
1547        double min_side = DBL_MAX;
1548        double max_side = -DBL_MAX;
1549        double min_up = DBL_MAX;
1550        double max_up = -DBL_MAX;
1551        double min_distanceEye = DBL_MAX;
1552        double max_distanceEye = -DBL_MAX;
1553
1554        double zNear = -bs.radius();
1555        double zFar = bs.radius();
1556
1557        typedef std::vector<osg::Vec2d> ProjectedVertices;
1558        ProjectedVertices projectedVertices;
1559
1560        osg::Vec3 eyeLocal = cv->getEyeLocal();
1561
1562
1563        // computed the expected near/far ratio
1564        unsigned int i;
1565        for(i=0; i< corners.size(); ++i)
1566        {
1567            double distanceEye = (corners[i] - eyeLocal).length();
1568            if (distanceEye < min_distanceEye) min_distanceEye = distanceEye;
1569            if (distanceEye > max_distanceEye) max_distanceEye = distanceEye;
1570
1571            osg::Vec3d delta = corners[i] - center;
1572            double distance_side = delta * sideVector;
1573            double distance_up = delta * upVector;
1574            projectedVertices.push_back(osg::Vec2d(distance_side, distance_up));
1575
1576            if (distance_side<min_side)
1577            {
1578                min_side = distance_side;
1579            }
1580            if (distance_side>max_side)
1581            {
1582                max_side = distance_side;
1583            }
1584            if (distance_up<min_up) min_up = distance_up;
1585            if (distance_up>max_up) max_up = distance_up;
1586        }
1587
1588        double mid_side = (min_side + max_side) * 0.5;
1589        double ratio = min_distanceEye / max_distanceEye;
1590        bool usePerspectiveShaders = (_overlayTechnique==VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY);
1591
1592        if (usePerspectiveShaders)
1593        {
1594//            OSG_NOTICE<<"ratio = "<<ratio<<std::endl;
1595//            double original_width = max_side-min_side;
1596
1597            double minRatio = 0.02;
1598            if (ratio<minRatio) ratio = minRatio;
1599
1600            double base_up = min_up - (max_up - min_up) * ratio / (1.0 - ratio);
1601            double max_side_over_up = 0.0;
1602            for(i=0; i< projectedVertices.size(); ++i)
1603            {
1604                double delta_side = fabs(projectedVertices[i].x() - mid_side);
1605                double delta_up = projectedVertices[i].y() - base_up;
1606                double side_over_up = delta_side / delta_up;
1607                if (side_over_up > max_side_over_up) max_side_over_up = side_over_up;
1608            }
1609            osg::Vec3d v000 = osg::Vec3d(-1.0, -1.0, -1.0) * inverseMVP;
1610            osg::Vec3d v010 = osg::Vec3d(-1.0, 1.0, -1.0) * inverseMVP;
1611            osg::Vec3d v100 = osg::Vec3d(1.0, -1.0, -1.0) * inverseMVP;
1612            osg::Vec3d v110 = osg::Vec3d(1.0, 1.0, -1.0) * inverseMVP;
1613
1614            osg::Vec3d v001 = osg::Vec3d(-1.0, -1.0, 1.0) * inverseMVP;
1615            osg::Vec3d v011 = osg::Vec3d(-1.0, 1.0, 1.0) * inverseMVP;
1616            osg::Vec3d v101 = osg::Vec3d(1.0, -1.0, 1.0) * inverseMVP;
1617            osg::Vec3d v111 = osg::Vec3d(1.0, 1.0, 1.0) * inverseMVP;
1618
1619
1620            osg::Vec3d edgeBottomLeft = v001-v000;
1621            osg::Vec3d edgeBottomRight = v101-v100;
1622            osg::Vec3d edgeTopRight = v111-v110;
1623            osg::Vec3d edgeTopLeft = v011-v010;
1624            edgeBottomLeft.normalize();
1625            edgeBottomRight.normalize();
1626            edgeTopLeft.normalize();
1627            edgeTopRight.normalize();
1628
1629
1630            double frustumDiagonal = osg::RadiansToDegrees(acos(edgeBottomLeft * edgeBottomRight));
1631
1632
1633            //OSG_NOTICE<<"  width ratio  = "<<new_width/original_width<<std::endl;
1634            //OSG_NOTICE<<"  near ratio  = "<<ratio * new_width/original_width<<std::endl;
1635            double angle = 2.0*osg::RadiansToDegrees(atan(max_side_over_up));
1636
1637
1638            if (angle > frustumDiagonal)
1639            {
1640                double maxHalfAngle = osg::DegreesToRadians(30.0);
1641
1642                // move ratio back
1643                max_side_over_up = tan(maxHalfAngle);
1644                double lowest_up = min_up;
1645
1646                for(i=0; i< projectedVertices.size(); ++i)
1647                {
1648                    double delta_side = fabs(projectedVertices[i].x() - mid_side);
1649                    double delta_up = delta_side / max_side_over_up;
1650                    double local_base_up = projectedVertices[i].y() - delta_up;
1651                    if (local_base_up < lowest_up)
1652                    {
1653                        lowest_up = local_base_up;
1654//                        double side_over_up = delta_side / delta_up;
1655                    }
1656                }
1657
1658                double new_ratio = (min_up-lowest_up)/(max_up-lowest_up);
1659
1660                //OSG_NOTICE<<"  originalRatio  = "<<ratio<<" new_ratio="<<new_ratio<<std::endl;
1661
1662                if (new_ratio > ratio) ratio = new_ratio;
1663
1664                base_up = lowest_up;
1665
1666            }
1667
1668            double max_half_width = max_side_over_up*(max_up - base_up);
1669            min_side = mid_side - max_half_width;
1670            max_side = mid_side + max_half_width;
1671
1672//            double new_width = max_side-min_side;
1673
1674
1675            double y0 = (1.0 + ratio) / (1.0 - ratio);
1676            overlayData._y0->set(static_cast<float>(y0));
1677
1678
1679            // OSG_NOTICE<<"y0 = "<<y0<<std::endl;
1680
1681            overlayData._mainSubgraphStateSet->setAttribute(overlayData._mainSubgraphProgram.get());
1682
1683            osg::Matrixd projection;
1684            projection.makeOrtho(min_side,max_side,min_up,max_up,zNear ,zFar);
1685
1686            camera->setProjectionMatrix(projection);
1687
1688        }
1689        else
1690        {
1691            overlayData._mainSubgraphStateSet->removeAttribute(osg::StateAttribute::PROGRAM);
1692            camera->setProjectionMatrixAsOrtho(min_side, max_side, min_up, max_up, zNear ,zFar);
1693        }
1694
1695
1696#if 0
1697        double width = max_side-min_side;
1698        double height = max_up-min_up;
1699        double area = width*height;
1700
1701        OSG_NOTICE<<"width = "<<width<<"\t height = "<<height<<"\t area = "<<area<<std::endl;
1702
1703        OSG_NOTICE<<"a  min_side    = "<<min_side<<std::endl;
1704        OSG_NOTICE<<"a  max_side  = "<<max_side<<std::endl;
1705        OSG_NOTICE<<"a  min_up    = "<<min_up<<std::endl;
1706        OSG_NOTICE<<"a  max_up  = "<<max_up<<std::endl;
1707#endif
1708
1709        if (em)
1710        {
1711            camera->setViewMatrixAsLookAt(bs.center(), osg::Vec3d(0.0f,0.0f,0.0f), upVector);
1712        }
1713        else
1714        {
1715            camera->setViewMatrixAsLookAt(bs.center(), bs.center()+overlayLookVector, upVector);
1716        }
1717
1718
1719        // compute the matrix which takes a vertex from local coords into tex coords
1720        // will use this later to specify osg::TexGen..
1721        MVP = camera->getViewMatrix() * camera->getProjectionMatrix();
1722
1723        osg::Matrix MVPT = MVP *
1724                           osg::Matrix::translate(1.0,1.0,1.0) *
1725                           osg::Matrix::scale(0.5,0.5,0.5);
1726
1727        //overlayData._texgenNode->setReferenceFrame(osg::TexGenNode::ABSOLUTE_RF);
1728        overlayData._texgenNode->getTexGen()->setMode(osg::TexGen::EYE_LINEAR);
1729        overlayData._texgenNode->getTexGen()->setPlanesFromMatrix(MVPT);
1730
1731        overlayData._textureFrustum.setToUnitFrustum(false,false);
1732        overlayData._textureFrustum.transformProvidingInverse(MVP);
1733
1734        // OSG_NOTICE<<std::endl;
1735
1736        unsigned int contextID = cv->getState()!=0 ? cv->getState()->getContextID() : 0;
1737
1738        if (usePerspectiveShaders)
1739        {
1740            cv->pushStateSet(overlayData._overlayStateSet.get());
1741
1742            typedef std::list<const osg::StateSet*> StateSetStack;
1743            StateSetStack statesetStack;
1744
1745            osgUtil::StateGraph* sg = cv->getCurrentStateGraph();
1746            while(sg)
1747            {
1748                const osg::StateSet* stateset = sg->getStateSet();
1749                if (stateset)
1750                {
1751                    statesetStack.push_front(stateset);
1752                }
1753                sg = sg->_parent;
1754            }
1755
1756            osg::StateAttribute::GLModeValue base_mode = osg::StateAttribute::ON;
1757            for(StateSetStack::iterator itr = statesetStack.begin();
1758                itr != statesetStack.end();
1759                ++itr)
1760            {
1761                osg::StateAttribute::GLModeValue mode = (*itr)->getMode(GL_LIGHTING);
1762                if ((mode & ~osg::StateAttribute::INHERIT)!=0)
1763                {
1764                    if ((mode & osg::StateAttribute::PROTECTED)!=0 ||
1765                        (base_mode & osg::StateAttribute::OVERRIDE)==0)
1766                    {
1767                        base_mode = mode;
1768                    }
1769                }
1770            }
1771
1772            overlayData._lightingEnabled->set((base_mode & osg::StateAttribute::ON)!=0);
1773        }
1774
1775        // if we need to redraw then do cull traversal on camera.
1776        camera->setClearColor(_overlayClearColor);
1777        //camera->setStateSet(overlayData._overlayStateSet.get());
1778        camera->accept(*cv);
1779
1780        if (usePerspectiveShaders) cv->popStateSet();
1781
1782        _textureObjectValidList[contextID] = 1;
1783
1784        overlayData._texgenNode->accept(*cv);
1785
1786        if (overlayData._geode.valid())
1787        {
1788               overlayData._geode->accept(*cv);
1789        }
1790
1791    }
1792    else
1793    {
1794        Group::traverse(nv);
1795    }
1796
1797    // OSG_NOTICE<<"   "<<&overlayData<<std::endl;
1798}
1799
1800void OverlayNode::traverse_VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY(osg::NodeVisitor& nv)
1801{
1802    traverse_VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY(nv);
1803}
1804
1805
1806void OverlayNode::setOverlaySubgraph(osg::Node* node)
1807{
1808    if (_overlaySubgraph == node) return;
1809
1810    _overlaySubgraph = node;
1811
1812    for(OverlayDataMap::iterator itr = _overlayDataMap.begin();
1813        itr != _overlayDataMap.end();
1814        ++itr)
1815    {
1816        osg::Camera* camera = itr->second->_camera.get();
1817        if (camera)
1818        {
1819            camera->removeChildren(0, camera->getNumChildren());
1820            camera->addChild(node);
1821        }
1822    }
1823
1824
1825    dirtyOverlayTexture();
1826}
1827
1828void OverlayNode::dirtyOverlayTexture()
1829{
1830    _textureObjectValidList.setAllElementsTo(0);
1831    _updateCamera = true;
1832}
1833
1834
1835void OverlayNode::setTexEnvMode(GLenum mode)
1836{
1837    _texEnvMode = mode;
1838    updateMainSubgraphStateSet();
1839}
1840
1841
1842void OverlayNode::setOverlayTextureUnit(unsigned int unit)
1843{
1844    _textureUnit = unit;
1845
1846    updateMainSubgraphStateSet();
1847}
1848
1849void OverlayNode::setOverlayTextureSizeHint(unsigned int size)
1850{
1851    if (_textureSizeHint == size) return;
1852
1853    _textureSizeHint = size;
1854
1855
1856    for(OverlayDataMap::iterator itr = _overlayDataMap.begin();
1857        itr != _overlayDataMap.end();
1858        ++itr)
1859    {
1860        if (itr->second->_texture.valid()) itr->second->_texture->setTextureSize(_textureSizeHint, _textureSizeHint);
1861        if (itr->second->_camera.valid()) itr->second->_camera->setViewport(0,0,_textureSizeHint,_textureSizeHint);
1862    }
1863
1864    //_texture->dirtyTextureObject();
1865}
1866
1867void OverlayNode::updateMainSubgraphStateSet()
1868{
1869   OSG_INFO<<"OverlayNode::updateMainSubgraphStateSet()"<<std::endl;
1870
1871   for(OverlayDataMap::iterator itr = _overlayDataMap.begin();
1872        itr != _overlayDataMap.end();
1873        ++itr)
1874    {
1875        osg::TexGenNode* texgenNode = itr->second->_texgenNode.get();
1876        if (texgenNode) texgenNode->setTextureUnit(_textureUnit);
1877
1878        osg::StateSet* mainSubgraphStateSet = itr->second->_mainSubgraphStateSet.get();
1879        if (mainSubgraphStateSet)
1880        {
1881            mainSubgraphStateSet->clear();
1882            mainSubgraphStateSet->setTextureAttributeAndModes(_textureUnit, itr->second->_texture.get(), osg::StateAttribute::ON);
1883            mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_S, osg::StateAttribute::ON);
1884            mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_T, osg::StateAttribute::ON);
1885            mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_R, osg::StateAttribute::ON);
1886            mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_Q, osg::StateAttribute::ON);
1887
1888            if (_texEnvMode!=GL_NONE)
1889            {
1890                mainSubgraphStateSet->setTextureAttribute(_textureUnit, new osg::TexEnv((osg::TexEnv::Mode)_texEnvMode));
1891            }
1892        }
1893    }
1894}
Note: See TracBrowser for help on using the browser.