Reference


App

App provides a convenient way to structure the application. It is intended to be subclassed with its event handlers overwritten as needed. In the examples this subclass is typically called MyApp. By default it contains a Scene instance and a comprehensive set of event handlers. The MyApp is typically created and run from the application's main like this:

int main() {
    osg::ref_ptr<MyApp> app = new MyApp();
    return app->run();
}

What's this ref_ptr thing!? It's basically the same as MyApp* app = new MyApp() with the difference that app will delete itself automatically when done. Generally you don't need to know much about smart pointers unless you dive deeper into the osg API. If you are, nonetheless, interested and you like the idea of not having to free your dynamically allocated objects check out this tutorial and smart pointer guide.

App Event Handlers

As mentioned MyApp functions as the Grand Central of the application. All the interface events (keyboard, touch, mouse, pen, widgets) are dispatched to it. This makes it easy to react to events and affect other objects throughout the application and the scene. A touchDown flipping an image, for example, is straight forward to set up this way.

It's similarly easy to work with Widgets since their events can easily be dispatched to MyApp. Say you have a ButtonWidget and you want to handle its events in the MyApp. All you have to do is register the handler class with the button via myButton->addEventHandler(myApp).

Essentials

This is a selected list. For completeness see App docs.

Scene*  scene;
void update();
void resized(int w, int h);
// Keyboard events.
void keyPress( va::Key& key );
void keyRelease( va::Key& key );
// Touch events.
void touchEnter( va::Touch& touch );
void touchDown( va::Touch& touch );
void touchMove( va::Touch& touch );
void touchUp( va::Touch& touch );
void touchLeave( va::Touch& touch );
// Mouse Auxiliary Events.
// Primary mouse events are blended with touch events.
void mouseButton( va::Mouse& mouse );
void mouseScroll( va::Mouse& mouse );
// Pen events.
void penPressure( va::Pen& pen );
void penOrientation( va::Pen& pen );
void penEnter( va::Pen& pen );
void penLeave( va::Pen& pen );
// Widget events.
// They need to be enabled with someWidget->addEventHandler(...)
void widget( va::ButtonWidget& button );
void widget( va::SliderWidget& slider );
void widget( va::ToggleWidget& toggle );

Scene

The Scene class is central to va and and every App has an instance by default. It is the starting point for building the scene as it contains a camera and the root node. To build up a scene you do this by adding child Nodes. In the Examples this is typically done along the following lines:

void setup() {
    va::Node* node = new va::Node();
    scene->addChild(node);
}

Scene Events

The Scene also does all the hard work regarding system events such as mouse-, keyboard-, and pen-events. In addition it can handle multitouch events through user-land injection. It is important to note that all these events are delegated to the App and are typically handled there rather than in the Scene class (see App for details).

Widgets are special. All the pointer events are delegated to the particular Widget in the scene where appropriate. This means any mouse-, pen-, or touch-event is sent to the Widget(s) under it. In addition such Widget events can also be received by the App and any other objects. All widgets have appropriate event handlers named: touchDown(...), touchMove(...), and touchUp(...). For brevity they handle not just touch but also mouse and pen events.

Multitouch is supported by va even though system-level support is spotty as of this writing. For this reason va offers the option to inject touch events in user-land. Say you have a touch server running that receives the events from the hardware it can inject them into va via the following functions:

Essentials

A selection of useful class members is listed here. For completeness see: va/Scene.h

Member Functions

// Get the horizontal and vertical resolution the scene is rendered in.
int getWidth()
int getHeight()
// Set the background color of the scene 
// and whether it is auto cleared before each frame.
void setBackgroundColor( float r, float g, float b, float a=1.0f )
void setBackgroundColor( const osg::Vec4& color )
void setBackgroundAuto( bAuto = false )
// Get frame number and timing.
// Simulation time is in seconds from app launch
int getFrameNumber();
double getSimulationTime();
// Enable/disable default lighting. 
// This is a simple sky light. By default it's enabled.
void enableDefaultLighting();
void disableDefaultLighting();
// Enable/disable full screen anti-aliasing. Not all graphics cards support this.
void enableMultisampling( int val=4 );
void disableMultisampling();
// Add Nodes and Drawables to the scene.
void addChild( va::Node* node )
void addChild( osg::Node* node );
void addDrawable( va::Drawable* drawable );
void addDrawable( osg::Drawable* drawable );
// Inject touch events into the scene for widget intersection and event delegation.
void touchDown( float x, float y, int touchId )
void touchMove( float x, float y, int touchId )
void touchUp( float x, float y, int touchId )

Nodes

Nodes are the basic building blocks of the scene. They can be added to the scene and also to other nodes. Node-derived classes come in all kinds of flavors. The two prominent sets are Shapes and Widgets.

Nodes, at the very least, are groups for their child nodes. Say you have a complex geometry like a city center. For each house you would have a node grouping all the geometry of the house. Within the house you would have nodes grouping all the geometry of a door and so on.

The purpose of nodes goes beyond grouping because each node has its own transformation and transforms all its children with it. This is what assures that, for example, buttons always move in relation to the panel they belong to.

This get more advanced when you think of rotational motion. Imagine you want to render a solar system and the sun is stationary in space. The earth circles around the sun and the moon around the earth. If you were to describe the motion of the moon from the sun's point of view you would be looking at a rather complicated path. Looking at the earth and moon orbit separately is simple though. Both just circle around their 'parent'. The same simplification can be made by making the moon a child node of the earth. This will cause the moon to move with the earth and its orbit can be described without bothering about the earth's orbit around the sun.

Example

Create a plain node, add a circle and a rectangle, and move both by setting the parent node's position.

va::Node* group = va::Node();
 
va::CircleShape* circle = va::CircleShape(20);
va::RectangleShape* rect = va::RectangleShape(20);
 
group->addChild(circle);
group->addChild(rect);
 
group->setPosition(100,100,0);

Essentials

This is a selected list. For completeness see Node docs.

Scene Graph Hierarchy:

bool  addChild( va::Node* node );
bool  insertChild( unsigned int index, va::Node* node );
bool  removeChild( va::Node* node );
bool  replaceChild( va::Node* origNode, va::Node* newNode );
unsigned int  getNumChildren();
bool          setChild( unsigned int index, va::Node* node );
va::Node*       getChild( unsigned int index );
bool          containsNode( va::Node* node );
unsigned int  getChildIndex( va::Node* node );

Translation:

float getX();
float getY();
float getZ();
osg::Vec3 getPosition();
 
void setX( float x );
void setY( float y );
void setZ( float z );
void setPosition( float x, float y, float z );
void setPosition( const osg::Vec3& pnt );
   
void addX( float x );
void addY( float y );
void addZ( float z );
void addPosition( float x, float y, float z );
void addPosition( const osg::Vec3& pnt );

Rotation:

float getRotationAngle();
osg::Vec3 getRotationAxis();
osg::Quat getRotation();
 
void setRotation( float angle, float x, float y, float z );
void setRotation( const osg::Quat& quat );
void setRotation( float x1, float y1, float z1, float x2, float y2, float z2 );
void setRotation( const osg::Vec3& vec1, const osg::Vec3& vec2 );
void setRotation( float slerpPct, const osg::Quat& quat1, const osg::Quat& quat2 );
 
void addRotationX( float x );
void addRotationY( float y );
void addRotationZ( float z );
void addRotation( float angle, float x, float y, float z );
void addRotation( const osg::Quat& quat );
void addRotation( float x1, float y1, float z1, float x2, float y2, float z2 );
void addRotation( const osg::Vec3& vec1, const osg::Vec3& vec2 );

Scale:

float getScaleX();
float getScaleY();
float getScaleZ();
osg::Vec3 getScale();
 
void setScaleX( float x );
void setScaleY( float y );
void setScaleZ( float z );
void setScale( float x, float y, float z );
void setScale( const osg::Vec3& scale );
   
void multScaleX( float x );
void multScaleY( float y );
void multScaleZ( float z );
void multScale( float x, float y, float z );
void multScale( const osg::Vec3& scale );

Pivot:

float getPivotX();
float getPivotY();
float getPivotZ();
osg::Vec3 getPivot();
 
void setPivotX( float x );
void setPivotY( float y );
void setPivotZ( float z );
void setPivot( float x, float y, float z );
void setPivot( const osg::Vec3& pnt );
   
void addPivotX( float x );
void addPivotY( float y );
void addPivotZ( float z );
void addPivot( float x, float y, float z );
void addPivot( const osg::Vec3& pnt );

Shapes

Shapes are nodes with geometry. Like all scene Nodes they are derived from Node and are therefore fully transformable and nestable. While va comes with the following basic primitives the real power house is VertexShape.

With VertexShape you can draw anything from points and lines to complex polygon shapes. To use this class you give it a list of vertices and tell it how they should be drawn. By default it draws points and a quick call to setMode( mode ) can change this to lines or triangles. The mode argument maps directly to the capabilities of OpenGL. VertexShape can also tesselate complex planar polygons.

Example

Use VertexShape to create a filled quad and add it to another node:

va::Node*  node = new va::Node();
 
va::VertexShape* myQuad = new va::VertexShape();
myQuad->setMode(GL_TRIANGLES);
myQuad->addVertex(100,100,0);
myQuad->addVertex(300,100,0);
myQuad->addVertex(320,320,0);
myQuad->addVertex(130,330,0);
 
node->addChild(myQuad);

Advanced Example

For more complex shapes it usually makes sense to create a custom class. Simply subclass it from Shape and then add any amount of VertexShape members to it. MonsterShape is a good example for how this is done:

class MonsterShape: public Shape {
 
    public:
 
        MonsterShape();        
        
        void setColor( float r, float g, float b, float a );
        void setColor( const osg::Vec4& color );
    
    protected:
        osg::ref_ptr<VertexShape> _body;
        osg::ref_ptr<VertexShape> _mouth;
        osg::ref_ptr<VertexShape> _leye;
        osg::ref_ptr<VertexShape> _reye;
        
    
};

Implementation file: MonsterShape.cpp

VertexShape Essentials

This is a selected list. For completeness see VertexShape docs.

Member Functions

// Setting the drawing mode.
// 'mode' defines how the vertices are transformed into geometry:
// GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP
// GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN
// GL_QUADS,  GL_QUAD_STRIP,  GL_POLYGON  
void setMode( GLenum mode );
GLenum getMode();
// Vertex Colors. 
// This can be either one color for all vertices or one per vertex.
// When using per vertex color the number should match the vertex number.                    
void setColor( float r, float g, float b, float a );
void setColor( const osg::Vec4& color );
const osg::Vec4& getColor();
// per vertex color                  
void addVertexColor( float r, float g, float b, float a );
void addVertexColor( const osg::Vec4& colorvec );
void setVertexColor( unsigned int index, const osg::Vec4& colorvec );
const osg::Vec4& getVertexColor( unsigned int index );
void clearVertexColors();
// Vertex Normals. 
// This can be either one normal for all vertices or one per vertex.
// When using per vertex normals the number should match the vertex number. vertices.
void setNormal( float x, float y, float z );
void setNormal( const osg::Vec3& color );
const osg::Vec3& getNormal();
// per vertex normals                  
void addVertexNormal( float x, float y, float z );
void addVertexNormal( const osg::Vec3& normal );
void setVertexNormal( unsigned int index, const osg::Vec3& normal );
const osg::Vec3& getVertexNormal( unsigned int index );
void clearVertexNormals();
// Tesselate shape.
// For concave polygons call this after adding all ter vertices.
// Also make sure you set the mode right. GL_POLYGON usually works well.
void tesselate();

Widgets

Widgets are Nodes for building interactive scenes. They inherit all the functionality from Node and add things relevant to pointer interaction (mouse, pen, touch). Primarily this means when pointers touch them, their handlers, touchDown(...), touchMove(...), touchUp(...) are called accordingly.

In addition to receiving these events in the Widget, they can also be delegated to another class, typically MyApp. This makes the event handling very flexible. It is especially useful when widgets want to talk to other scene nodes, including other widgets. For example a ButtonWidget can delegate a button press to widget( va::Button& button ) in MyApp. Code in this event handler has then access to all the nodes that were created in MyApp. The only thing that needs to be done for this kind of delegation is to register the handler class with the button via a call to mybutton->addEventHandler(myapp). Each kind of widget has a corresponding handler. See EventHandlers and App for details.

Widget is the base class for all widgets. va comes with the following:

Essentials

This is a selected list. For completeness see Widget docs.

void reshape()
void update()
void setName( const std::string& name)
const std::string& getName()
void setWidth( float w )
void setHeight( float w )
float getWidth()
float getHeight()
void setBackgroundColor( float r, float g, float b, float a )
void setBackgroundColor( const osg::Vec4& color )
const osg::Vec4& getBackgroundColor()
void setBorderColor( float r, float g, float b, float a )
void setBorderColor( const osg::Vec4& color )
const osg::Vec4& getBorderColor()
void touchDown( va::Touch& touch )
void touchMove( va::Touch& touch )
void touchUp( va::Touch& touch )

EventHandlers

All App-derived classes (e.g: MyApp) can handle app events by overwriting and implementing the appropriate handler functions. App event handlers comprise windowing, key, touch, mouse, pen, and widget events. For convenience the App class implements them all and it's perfectly fine to do all the event handling in MyApp. All the example code is written around this approach. To make this sound less abstract an example follows.

Key Handling Example

Suppose you want to react to key presses in your MyApp class. Specifically you want to change the scene's background color to red when the 'r' key is pressed:

// In MyApp.h:
void keyPress( va::Key& key );
 
// In MyApp.cpp
void MyApp::keyPress( va::Key& key ){
    if (key.getKey() == 'r') {
        scene->setBackgroundColor(1.0f, 0.0f, 0.0f);
    }
}

MyApp is a good place to handle these kinds of events. In addition any class can be setup to handle app events. Simply subclass one of the event handler classes in va/EventHandlers.h, overwrite the handler function (eg: keyPress) and register the class with the scene (eg: scene->addKeyHandler(handler)). This is exactly how the App class does it internally.

All App Event Handlers

MyApp.h:

#ifndef VA_MYAPP
#define VA_MYAPP
 
#include <va/Main.h>
 
 
class MyApp : public va::App {
	
    public:
    
        MyApp();
        virtual ~MyApp();
 
        
        void update();
        void resize( int w, int h );
 
        void keyPress( va::Key& key );
        void keyRelease( va::Key& key );
 
        void touchEnter( va::Touch& touch );
        void touchDown( va::Touch& touch );
        void touchMove( va::Touch& touch );
        void touchUp( va::Touch& touch );
        void touchLeave( va::Touch& touch );
        
        void mouseButton( va::Mouse& mouse );
        void mouseScroll( va::Mouse& mouse );
 
        void penPressure( va::Pen& pen );
        void penOrientation( va::Pen& pen );
        void penEnter( va::Pen& pen );
        void penLeave( va::Pen& pen );
 
        void widget( va::ButtonWidget& button );
        void widget( va::SliderWidget& slider );
        void widget( va::ToggleWidget& toggle );           
};
 
#endif

MyApp.cpp:

#include "MyApp.h"
 
 
MyApp::MyApp(){}
MyApp::~MyApp(){}
 
 
void MyApp::update(){}
void MyApp::resize( int w, int h ){}
 
void MyApp::keyPress( va::Key& key ){}
void MyApp::keyRelease( va::Key& key ){}
 
void MyApp::touchEnter( va::Touch& touch ){}
void MyApp::touchDown( va::Touch& touch ){}
void MyApp::touchMove( va::Touch& touch ){}
void MyApp::touchUp( va::Touch& touch ){}
void MyApp::touchLeave( va::Touch& touch ){}
 
void MyApp::mouseButton( va::Mouse& mouse ){}
void MyApp::mouseScroll( va::Mouse& mouse ){}
 
void MyApp::penPressure( va::Pen& pen ){}
void MyApp::penOrientation( va::Pen& pen ){}
void MyApp::penEnter( va::Pen& pen ){}
void MyApp::penLeave( va::Pen& pen ){}
 
void MyApp::widget( va::ButtonWidget& button ) {}
void MyApp::widget( va::SliderWidget& slider ) {}
void MyApp::widget( va::ToggleWidget& toggle ) {}