root/OpenSceneGraph/trunk/examples/osgthirdpersonview/osgthirdpersonview.cpp @ 7907

Revision 7907, 7.0 kB (checked in by robert, 7 years ago)

From Paul Martz, a third person view CompositeViewer? example

Line 
1/* OpenSceneGraph example, osgthirdpersonview.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18// This code is originally Copyright (c) 2008 Skew Matrix  Software LLC,
19// but you may use the code under the terms of the OSGPL as described above.
20
21// This example demonstrates how CompositeViewer can be used to
22// provide a third person view of another view, including eyepoint and
23// view frustum.
24//
25// The code creates a CompositeViewer with two Views. Each of the two
26// Views has its own window. One View is the typical scene view,
27// showing the loaded model(s).
28//
29// The second View is a third person view showing not just the loaded
30// model(s), but also a wireframe representation of the first View's
31// frustum. Interactions with the first View are reflect5ed in the
32// second View's displayed frustum.
33//
34// Command line arguments are taken to be models for display. If you
35// specify no command line arguments, the code attempts to load cow.osg.
36
37
38#include <osg/Geometry>
39#include <osg/DisplaySettings>
40#include <osg/MatrixTransform>
41#include <osg/LineWidth>
42#include <osgDB/ReadFile>
43#include <osgViewer/CompositeViewer>
44#include <osgGA/TrackballManipulator>
45
46
47// Given a Camera, create a wireframe representation of its
48// view frustum. Create a default representation if camera==NULL.
49osg::Node*
50makeFrustumFromCamera( osg::Camera* camera )
51{
52    // Projection and ModelView matrices
53    osg::Matrixd proj;
54    osg::Matrixd mv;
55    if (camera)
56    {
57        proj = camera->getProjectionMatrix();
58        mv = camera->getViewMatrix();
59    }
60    else
61    {
62        // Create some kind of reasonable default Projection matrix.
63        proj.makePerspective( 30., 1., 1., 10. );
64        // leave mv as identity
65    }
66
67    // Get near and far from the Projection matrix.
68    const double near = proj(3,2) / (proj(2,2)-1.0);
69    const double far = proj(3,2) / (1.0+proj(2,2));
70
71    // Get the sides of the near plane.
72    const double nLeft = near * (proj(2,0)-1.0) / proj(0,0);
73    const double nRight = near * (1.0+proj(2,0)) / proj(0,0);
74    const double nTop = near * (1.0+proj(2,1)) / proj(1,1);
75    const double nBottom = near * (proj(2,1)-1.0) / proj(1,1);
76
77    // Get the sides of the far plane.
78    const double fLeft = far * (proj(2,0)-1.0) / proj(0,0);
79    const double fRight = far * (1.0+proj(2,0)) / proj(0,0);
80    const double fTop = far * (1.0+proj(2,1)) / proj(1,1);
81    const double fBottom = far * (proj(2,1)-1.0) / proj(1,1);
82
83    // Our vertex array needs only 9 vertices: The origin, and the
84    // eight corners of the near and far planes.
85    osg::Vec3Array* v = new osg::Vec3Array;
86    v->resize( 9 );
87    (*v)[0].set( 0., 0., 0. );
88    (*v)[1].set( nLeft, nBottom, -near );
89    (*v)[2].set( nRight, nBottom, -near );
90    (*v)[3].set( nRight, nTop, -near );
91    (*v)[4].set( nLeft, nTop, -near );
92    (*v)[5].set( fLeft, fBottom, -far );
93    (*v)[6].set( fRight, fBottom, -far );
94    (*v)[7].set( fRight, fTop, -far );
95    (*v)[8].set( fLeft, fTop, -far );
96
97    osg::Geometry* geom = new osg::Geometry;
98    geom->setUseDisplayList( false );
99    geom->setVertexArray( v );
100
101    osg::Vec4Array* c = new osg::Vec4Array;
102    c->push_back( osg::Vec4( 1., 1., 1., 1. ) );
103    geom->setColorArray( c );
104    geom->setColorBinding( osg::Geometry::BIND_OVERALL );
105
106    GLushort idxLines[8] = {
107        0, 5, 0, 6, 0, 7, 0, 8 };
108    GLushort idxLoops0[4] = {
109        1, 2, 3, 4 };
110    GLushort idxLoops1[4] = {
111        5, 6, 7, 8 };
112    geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINES, 8, idxLines ) );
113    geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops0 ) );
114    geom->addPrimitiveSet( new osg::DrawElementsUShort( osg::PrimitiveSet::LINE_LOOP, 4, idxLoops1 ) );
115
116    osg::Geode* geode = new osg::Geode;
117    geode->addDrawable( geom );
118
119    geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
120
121
122    // Create parent MatrixTransform to transform the view volume by
123    // the inverse ModelView matrix.
124    osg::MatrixTransform* mt = new osg::MatrixTransform;
125    mt->setMatrix( osg::Matrixd::inverse( mv ) );
126    mt->addChild( geode );
127
128    return mt;
129}
130
131
132int
133main( int argc,
134      char ** argv )
135{
136    osg::ArgumentParser arguments( &argc, argv );
137
138    osg::ref_ptr< osg::Group > root = new osg::Group;
139
140    // Child 0: We'll replace this every frame with an updated representation
141    //   of the view frustum.
142    root->addChild( makeFrustumFromCamera( NULL ) );
143
144    osg::ref_ptr< osg::Node > scene;
145    scene = osgDB::readNodeFiles( arguments );
146    if (!scene)
147    {
148        // User didn't specify anything, or file(s) didn't exist.
149        // Try to load the cow...
150        osg::notify( osg::WARN ) << arguments.getApplicationName() << ": Could not find specified files. Trying \"cow.osg\" instead." << std::endl;
151        if ( !(scene = osgDB::readNodeFile( std::string( "cow.osg" ) ) ) )
152        {
153            osg::notify( osg::FATAL ) << arguments.getApplicationName() << ": No data loaded." << std::endl;
154            return 1;
155        }
156    }
157    root->addChild( scene.get() );
158
159
160    osgViewer::CompositeViewer viewer( arguments );
161    // Turn on FSAA, makes the lines look better.
162    osg::DisplaySettings::instance()->setNumMultiSamples( 4 );
163
164    // Create View 0 -- Just the loaded model.
165    {
166        osgViewer::View* view = new osgViewer::View;
167        viewer.addView( view );
168
169        view->setUpViewInWindow( 10, 10, 640, 480 );
170        view->setSceneData( scene.get() );
171        view->setCameraManipulator( new osgGA::TrackballManipulator );
172    }
173   
174    // Create view 1 -- Contains the loaded moel, as well as a wireframe frustum derived from View 0's Camera.
175    {
176        osgViewer::View* view = new osgViewer::View;
177        viewer.addView( view );
178
179        view->setUpViewInWindow( 10, 510, 640, 480 );
180        view->setSceneData( root.get() );
181        view->setCameraManipulator( new osgGA::TrackballManipulator );
182    }
183
184    while (!viewer.done())
185    {
186        // Update the wireframe frustum
187        root->removeChild( 0, 1 );
188        root->insertChild( 0, makeFrustumFromCamera(
189                viewer.getView( 0 )->getCamera() ) );
190
191        viewer.frame();
192    }
193    return 0;
194}
Note: See TracBrowser for help on using the browser.