OSG Development Overview 1 OSG Basics
ØOSG, an abbreviation for open Scene Graphic, was born in 1997 to the hand of a glider enthusiast, and Don Burns in order to simulate the flight of a glider, the library of OpenGL was encapsulated, and OSG's embryonic form was born, 1998 Don Burns met Robert Osfield, who also likes gliders and computer graphics, and since then Robert Osfield has joined the development team of OSG and has been the leader of the development group.
ØOSG not only has OpenGL's cross-platform features and high rendering performance, but also offers a range of functional interfaces for 3D program developers, including 2D and 3D data file loading, texture font support, LOD control, multi-threaded data paging, and more. OSG is widely used in flight simulation and other fields, including FlightGear, and the U.S. Military Investment simulation project DELTA3D, etc.
1.1 Basic knowledge of computer graphics
Ø first of all, we must first look at how we paint in the world of display.
Ø in the real world, draw a picture, what we need is color pens, white paper. By selecting different color pens and moving on white paper, the different dots on the white paper can be painted in different colors, and all of these points are connected, and from the macroscopic view of the person, they constitute a meaningful painting for people.
O analogy to the reality of the computer. In the world of computers. What is the process of painting?
Ø Similarly, to draw virtual images, also need "color pens" and "white paper". In the world of computers, "crayons" is a drawing API function such as Direct3D, and "white paper" is the memory that stores the data. We divide an area in memory, where the data is a simulation of a real world. A data describes the properties of a point in the real world. Before we painted, they had only one initial value, just like white paper before painting. And after the painting, each data has a unique meaning, the whole piece of data connected together to see, is a meaningful picture. The process of painting is the process of assigning each data in memory, which is the equivalent of coloring a point on a white paper with a color marker. Choose different API functions to draw different shapes.
1.2 OSG Program Framework
Ø one of the simplest OSG programs is shown below, of course, if you are editing under VS, you need to set the OSG Lib and include directories.
1 #include <osgDB/ReadFile>
2
3 #include <osgViewer/Viewer>
4
5 void Main ()
6
7 {
8
9 Osgviewer::viewer Viewer;
10
Viewer.setscenedata (Osgdb::readnodefile ("GLIDER.OSG"));
12
Viewer.realize ();
14
Viewer.run ();
16
17}
18
Osgviewer::viewer Viewer has applied for a viewer that can be understood as applying for an observer that can view the model
Viewer.setscenedata (Osgdb::readnodefile ("GLIDER.OSG")) here is the data in the Observer viewer, in other words, with the observer, you can add the model.
Viewer.realize () This statement expresses a lot of meaning, In fact, you can locate the realize function of the Viewer.cpp, you will find that the operation is very much, you can understand that this is the last step before rendering, will check and set the graphics context, screen ah what, will make your previous settings, the viewer settings are in effect.
Viewer.run (); The meaning of this sentence is to render, if you want to explain its meaning, you can use the following several statements to replace:
while (!viewer.done ()) {viewer.frame ();}. This means that, as long as the viewer is not finished, it draws every frame [frame].
1.3 OSG Simple Model control 1.3.1 Add model
In the OSG model is loaded together using Osg::group and Osg::node, for example, you need to add two models, Model A, the model B,ab each is a node, then you can use the following statement to do, first use a group, and then group-> AddChild (A), again, then Group->addchild (B). Then add the group to the viewer. 3.1 shows the relationship between AB. It is to be stated here that node is the parent of group, and there are corresponding methods in the class to move to each other, so node and group
is generic, node can also be used as a group.
Figure AB is added to group
The simple example code is as follows:
1 #include <osgDB/ReadFile>
2
3 #include <osgViewer/Viewer>
4
5 #include <osg/Node>
6
7 void Main ()
8
9 {
10
One osgviewer::viewer Viewer;
12
Osg::group * root=new osg::group ();
14
Root->addchild (Osgdb::readnodefile ("GLIDER.OSG"));
16
Root->addchild (Osgdb::readnodefile ("OSGCOOL.OSG"));
18
Viewer.setscenedata (root);
20
Viewer.realize ();
22
Viewer.run ();
24
25}
26
The result of the operation is:
Figure 32 Example Run results
1.3.2 Deleting nodes
If we don't need a junction, it's a little bit more than 3.2 of us looking at the small plane, and we want to remove it from the scene. Do not know for a certain purpose, anyway now to delete, may be starting to want to see it now do not want to see it. Can be through the RemoveChild method, in addition to many children can also through the Removechildren method, the parameters of some need to index values, some need to node itself pointers, readers can try. It is important to note that if a node is to be deleted, then all nodes under that node will be deleted. If a node is added to a group two times, then these two times are separate, delete once and another time. Delete operation is not a dangerous operation, sometimes, especially when there are moving nodes and so on mixed together, the deletion of the operation occasionally will occur some strange phenomenon. In memory images, if a model is read once and used more than once, the space occupied will not change.
1.3.3 Hidden model and node switch
Ø Hidden model
Hidden models In fact the model is still in the rendering, so the loss is not reduced, but only hidden, hiding is really not a good operation, but sometimes the small model is really practical. Node->setnodemask can be set to hide and display.
Ø node switch
In OSG, there is a class that is responsible for opening and closing the node, the class named Osg::switch, which has a corresponding method to control the opening and closing of the nodes it manages.
Two methods can control the display and hiding of the model, the difference is that the hidden model method will not let the model disappear in memory, so the frequent calls to small objects will save some time, and for some large modules may be a long time after the use of a second time, this time with the node switch can destroy the model, Re-use the memory again to prevent more resources from being consumed.
1.3.4 Super pointer
The mechanism of the super pointer, in fact, is to refer to a counter, this counter will calculate the number of times the box is quoted, the counter is quoted one time, others do not need one time, that is: release once, then the counter minus one. When it is reduced to 0 o'clock, the memory is dropped.
Let's look at three ways to use a node, and compare them:
ø//method One, the best method, very safe, is also the most common method in OSG, how many versions it has not changed
Osg::ref_ptr<osg::node>anode (New Osg::node ());
Group->addchild (Anode.get ());
ø//method Two, also a very good method, sometimes not applicable, but also very safe
Group->addchild (New Osg::node ());
ø//method Three, very dangerous, but a way for many people to make desperate
Osg::node*anothernode=new Osg::node ();
Group->addchild (Anothernode);
Method One: A node resource is requested at New::node (), and the calculator referencing that node in the heap is set to 1. The Group->addchild (Anode.get ()) was quoted once and added 1. At the end of these two references, node's resources are freed.
Method Two: This method is also very useful, but can not lead to the pointer node, may be used elsewhere, in fact, will be used frequently. If you have already done this, it is not possible to get the node pointer, you can use Nodevisitor to get node pointers, or you can use the Findchild method to do this.
Method Three: This should be the most common, but the worst way, because if the osg::node*antherode=new Osg::node () After the error occurred, throw an exception, who will release the resources that Node occupies. And this anomaly is caught in the back, the program goes on normally, and the memory is not properly dropped.
1.3.5 Move/rotate/scale model
Movement/rotation/scaling is actually the operation of the Matrix, in the OSG, the matrix can be added to the root as a special node, and the matrix can be another node, and the added node will be processed by this matrix, such as moving over/rotation over/over/over. The class that controls the matrix in OSG is Osg::matrixtransform.
Ø Mobile
Osg::matrix::translate
Ø rotation
Osg::matrix::rotate
Ø Zoom
Osg::matrix::scale
1.4 Basic geometric elements 1.4.1 Basic drawing method
First of all, look at some of the most basic OSG in the map. If we are going to draw a square, draw a color, not a map. First we have to apply for a osg::geometry, add this Geometry to Geode. In this geometry to set some elements, the most basic is the vertex vertex, color colors, as well as the vertex and the relationship between the normal normal. As shown in 3.3.
Figure 33 Geometry Drawing process
1.4.2 an entity that can be drawn
All the elements that can be drawn include:
Øpoints[Point]
Ølines[Line]
øline_strip[Line Belt]
øline_loop[closed segment]
øtriangles[Triangle]
øtriangle_strip[Triangle Belt]
øtriangle_fan[Triangle Fan]
øquads[Square Block]
øquad_strip[Square block Belt]
øpolygon[Polygon]
Setting the line width in OSG is specifically a function to manage, called linewidth, which itself belongs to the class in the state and attribute category. It's actually derived from there. All set state operations are similar to this.
1.4.3 Built-in geometry type
Like OpenGL, OSG also has a built-in geometry type, all in class Osg::shape, which can be added to the Geode as a draw node and then added to the root in Geode to render. There are nine kinds of shapes, namely: osg::box[box],osg::capsule[capsule-shaped],osg::compositeshape[combination],osg::cone[conical],osg::cylinder[cylindrical],OSG:: heightfield[elevation shape],osg::infiniteplane[finite surface],osg::sphere[spherical],osg::trianglemesh[triangular skin].
The rendering process of the built-in geometry type, shown in 4.5
Figure 34 The process of adding basic geometry elements
It should be noted here that the general shape of the state has specific factors, such as box has a long width, a circle radius, as well as the various drawings of the fineness of the drawing should be specified, these fineness in the shape of the ball is still very significant. In OSG, there is a class that specifies the fineness, named: osg::tessellationhints. Take the ball as an example, you just need to specify that the center, radius and fineness of the ball can be drawn.
1.5 Interactive 1.5.1 Interaction process
The main function of the viewer is to control the scene, which is the core class of the scene, if you can respond to the keyboard to get the viewer, you can also control the entire scene from the keyboard response. There is a method in the viewer, called addEventHandler, which is dedicated to doing this thing. He will join an event handler. So we think, we must write an event handler, it is necessary to understand the format of the event handler, as long as there is an interface to understand its format, this interface is: Osgga::guieventhandler, so we can write a class A from the class to derive from the public, That is: Class A:public Osgga::guieventhandler, in which the various operations are processed and then added to the viewer, namely: Viewer.addeventhadler (there can be parameters), so that you can complete the operation.
If Class A is an event-handling class, then adding Class A can understand this, 3.5:
Figure 35 Event A controls the scene process
1.5.2 Event Type and response
Code value Event Type
None 0 no event.
Push 1 Mouse A key is pressed, in the above code 28 line is useful to.
RELEASE 2 Mouse a key bouncing up.
DOUBLECLICK 4 Mouse A key double-click.
DRAG 8 Mouse A key to drag.
Move 16 mouse movement.
KEYDOWN 32 A key on the keyboard is pressed.
KEYUP 64 A key on the keyboard bounces up.
Frame 128 should be a mouse per frame. No use.
RESIZE 256 the size of the window changes when there are events.
SCROLL 512 mouse wheel scrolling.
Pen_pressure an event of the 1024 tablet?
Pen_proximity_enter an event of the 2048 tablet?
Pen_proximity_leave an event of the 4096 tablet?
Close_windows 8192 Close the window.
Quit_application 16384 exit the program.
User 32768-Defined.
As for why all use 2 of the N-square, mainly because its binary code only one is a, judge the event is very good judgment, as long as the year which is one can.
1.5.3 PICK
Pick mainly by mouse click to pick up some objects, or to determine where the mouse click on the location. The idea of pick implementation is as follows:
Figure 36pick Event Flow
The method for judging the intersection of the ray and the object in the viewer is to emit rays and intersect. There are library functions in OSG, osgviewer::view::computeintersections he has three parameters: the first is X-screen coordinates, the second is the Y-screen coordinate, and the third is the information that holds the intersecting nodes and the intersection of the coordinate nodes.
Judging the intersection node is the node I want: Just to determine if there are any nodes to use in the result set of the intersection Ray intersection.
1.6 Roaming 1.6.1 Matrixmanipulator
The core manager of the scene is the viewer, and roaming must respond to events, such as moving the mouse and moving the scene. The class that responds to the event is Osgga::guieventhandler. We want to derive a new class from the class that responds to the event, which is specifically used to control the viewer based on the response. This class is osgga::matrixmanipulator, this class has some set up the common interface of the matrix, with these interfaces can effectively control the viewer, according to different habits, we will also set different control methods, as the OSG comes with a few operators, Operations are different. Take a look at the main flow of Roaming 6.1:
Figure 371-like scene operator
The operator must derive from Osgga::matrixmanipulator. The Osgga::matrixmanipulator has four important interfaces to control the scene:
1 virtual void Setbymatrix (const Osg::matrixd&matrix) =0
2
3 virtual void Setbyinversematrix (const Osg::matrixd&matrix) =0
4
5 virtual Osg::matrixd Getmatrix () const=0
6
7 Virtual Osg::matrixd Getinversematrix () const=0
8
The four matrix interfaces can effectively pass information about the matrix to the viewer.
1.6.2 Collision Detection
The simplest collision detection is as follows:
Fig. 38 Simple Collision detection schematic diagram
TravelManipulator.dll is used in the principle, the black triangle represents no moving position, the function of the control movement is changeposition (Osg::vec3&delta), the parameter meaning is to move relative to the current point of increment, When the black triangle does not move, the function in the calculation of the first assumption that a point newposition is a moving point, and then through the connection between the two points, and then through the judge and the scene of the model whether there is an intersection to determine if the movement can be executed, there is a large box between the two, so only stay in situ. Even without the box, the moving new Point has an intersection with the ground in some kind of program, which proves that the movement is not feasible. This prevents the user from going through the floor to reach the ground.
1.6.3 Path Roaming
The way to use the path file is as shown in the following example
1 #include <osgDB/ReadFile>
2
3 #include <osgViewer/Viewer>
4
5 #include <osg/Node>
6
7 #include <osgGA/AnimationPathManipulator>
8
9 void Main ()
10
11 {
12
Osgviewer::viewer Viewer;
14
Viewer.setscenedata (Osgdb::readnodefile ("GLIDER.OSG"));
16
17//Apply an operator with the parameter as a path file.
18
Osg::ref_ptr<osgga::animationpathmanipulator>amp=new osgga::animationpathmanipulator ("Glider.path");
20
21//Select Use this operator.
22
Viewer.setcameramanipulator (Amp.get ());
24
Viewer.realize ();
26
Viewer.run ();
28
29}
30
31
We can use the path editor to edit the path file, or you can save the motion trajectory of an object in the control program to a path file.
1.7 Updates & Callbacks
The callback means that you can specify that a function be started when something happens, and that this function may do something. This function is called a callback function, we can use an existing callback function or a custom callback function.
Ø using an existing callback
There are many types of callbacks that are available, and it is generally easy to think of Updatecallback, or eventcallback, etc.
Ø Custom Callback
A custom callback sends its own callback from a callback type, and then has the characteristics of that callback, and so on.
Nodevisitor is a very useful class that can access a sequence of nodes, using a similar approach, nodevisitor the workflow as shown:
Figure 39NodeVisitor Work Flow
After the main node accept, the node data is immediately transmitted to the Nodevisitor, apply the Apply function, you can set the data for some operations, more operations or require hard to make and call.
1.8 Particle System Preliminary
Special particle system tools are available in the OSG, and the namespaces for OSGPARTICLE,OSG do special classes for frequently used particle simulations, such as: Explosioneffect for burst simulations, fireeffect for fire simulations, Explosiondebriseffect is used for particle simulation of scattered particles after explosion and so on.
The use of particle systems in OSG generally takes the following steps:
The first step: determine the intent (including how the particles are moving and so on). Step two: Create a particle template, determine the angle of the particle according to the desired type (the angle is determined, as the particles are used by default billboard so that they stand in any angle is the same), shape (round, polygon, etc.), life cycle and so on. Step three: Build the particle system, set the total properties, fourth step: Set the emitter (emitter shape, number of emitted particles, etc.), step Fifth: Set the operation (rotation, wind, etc.). Sixth step: Join the node, update. Describes how the various parts work in a coordinated way:
Figure 310 The various parts of the particle system are the way to coordinate work
The classes that correspond to each part of the
Fig. 311 The classes corresponding to the parts of the particle system
1.9 Viewport &lod&imposter1.9.1 Multi-viewport
The multi-viewport principle is to create all the cameras yourself, including the main camera, so that we can add the camera at will.
First of all, we have to create a viewport must have the following things, first, understand the whole screen of how much resolution, so as to distinguish the size of the viewport, good separation. Second, context. We have to manually open the settings context ourselves. The data for each viewport is not necessarily the same as the primary viewport. However, matrices are generally synchronous. In other words: there is a building in the main viewport, from the viewport can be a plan or something. Understanding the entire screen resolution can be used in this class: Osg::graphicscontext::windowingsysteminterface means that the system interface can obtain various information about the current environment. There is a method called Getscreenresolution, you can get the resolution. After the context, Osg::graphicscontext inside can set the window size, cache what, most of the things are set here.
1.9.2 LOD
LOD is level of details
LOD than the Pagedlod is not very common, there is a place to use a lot of, that is to put a good model plus a visual moment pressure into a model, this model than the previous view is more than a view of the control of the moment, far out of sight, near can see.
The way to add LOD header nodes to the model is as follows:
1 #include <osgDB/Registry>
2
3 #include <osgDB/ReadFile>
4
5 #include <osgdb/readerwri ter>
6
7 #include <osgdb/wri tefile>
8
9 #include <osg/Node>
10
#include <osgViewer/Viewer>
12
int main ()
14
15 {
16
Osgviewer::viewer Viewer;
18
19//Read model
20
Osg::node*node=osgdb::readnodefile ("FOUNTAIN.OSG");
22
23//Hidden nodes
24
Node->asgroup ()->getchild (0)->setnodemask (0);
26
Viewer.setsceneda ta (node);
28
29//Output junction to Free.os G
30
Osgdb::writenodefile (* (Viewer.getscenedata ()), "FREE.OSG", Osgdb::registry
32
: Instance ()->getoptions ());
34
return 0;
36
37}
38
39
1.9.3 Imposter
Practical techniques for replacing scenes with dynamic images: imposter. It can be used as LOD, except that it
Instead of changing the model to one, instead of replacing it with a picture
The sample code is as follows: Set a visual moment over which the line of sight model becomes a dynamic graph
1 #include <osgViewer/Viewer>
2
3 #include <osgGA/TrackballManipulator>
4
5 #include <osgSim/Impostor>
6
7 #include <osgDB/ReadFile>
8
9 int Main (INTA Rgc,cha r**a rgv)
10
11 {
12
13//Apply Viewer
14
Osgviewer::viewer Viewer;
16
17//Read model
18
Osg::node*node=osgdb::readnodefile ("ceep.ive");
20
21//apply for an I mpos tor node
22
Osgsim::impos tor*sim=new Osgsim::impostor;
24
25//Display the model in the inside, outside the map
26
Sim->addchild (node,0,50000);
28
Sim->setimpostorthreshold (1000);
30
Osg::group*root=new Osg::group;
32
Root->addchild (SIM);
34
Viewer.setscenedata (root);
36
Panax Notoginseng viewer.realize ();
38
Viewer.run ();
40
return 0;
42
43}
44
45
1.10 Text & Model Shadows
1.10.1 HUD
HUD is head up display
Text in a 3D scene tends to go through the following steps: Read the font lattice information, convert to image--anti-aliasing and final image. You can work with a fuzzy effect during anti-aliasing, and you can set how the final image will be placed when it is formed. There is a text class in OSG that provides a way to display a lot of text, such as
1 void SetFont (font*font=0)
2
3//set/Get fonts, such as SetFont ("Fonts/simyou. TTF ");
4
5 void SetFont (const std::string&fontfile)
6
7 Const Font*getfont () const
8
9//set/Get wide height of font display
10
One void setfontresolution (unsigned int width,unsigned int height)
12
unsigned int getfontwidth () const
14
unsigned int getfontheight () const
16
17//set/Get specific content of text
18
And so on, can be very convenient to call
1.10.2 Shadow
OSG support for the shadow is also quite good, can easily write a simple shadow effect, you can refer to the example Osgshadow
OSG has a dedicated shadow class to support shadow effects and provides a number of interfaces, such as:
1 void Setbackdroptype (Backdroptype type)
2
3//Description: Sets the shadow type.
4
5 void Setbackdropoffset (float offset=0.07f)
6
7 void Setbackdropoffset (float horizontal,float vertical)
8
9//Description: Sets the extent and direction of the Shadow's departure
10
one void Setbackdropcolor (const osg::vec4&color)
12
13//Description: Set Shadow Color
14
void Setcolorgradientmode (Colorgradientmode mode)
16
17//Description: Set the color mapping method, you can get the gradient effect
18
Reference book: Freesouth's "qpenscenegraph Program Design"
OSG Development Overview (reprint)