OSG's shortest data processing frame

Source: Internet
Author: User


This is the shortest frame. We mainly take data processing as the center and take a look at the general processing process. It is also a very rough understanding. For detailed analysis, please read the longest tutorial, the shortest frame is named as if you want to traverse the path along a shortest path.

We can regard the rendering process of the entire scenario as a product processing process. The first is the raw material, and then the processing machines and processes through which the raw materials are processed. So we also adopt this idea. Let's leave aside the margin to see if the scene data is finally rendered to the screen through intermediate processing. We only need to analyze the links that are most closely related to the data, aside from others, the content will fall in a geometric level, and the process is relatively clear.

Our raw material is a ox. We need to use this ox to process it into a canned beef. Haha, isn't it drool? If you don't talk nonsense, you won't talk about it in the future. Everything is simple, and you can analyze it one by one.

Create a factory, that is, create a viewer. Of course, all the processing equipment has been purchased, but here we will simplify it and combine our title "data-based ", all the analysis will never leave the data half step (never leave the cow), so that we will not be held back and finally confused, so we will not analyze the equipment in it.

Anyone who knows how to buy raw materials (OX), osgdb: readnodefile ("cow. OSG ").

Feed the scene to the viewer, viewer. setscenedata (COW );

Next, let's take a look at how to place the cattle. Directly go to the above function and you can see that this cow directly goes to view: setscenedata (node); let's continue to see that there is a scene member in view, A scene is a scene tree, which is the scene tree corresponding to the master camera of the view. After entering this function, we can see that this ox was first sent to this scene, _ scene-> setscenedata (node); next we can see

View: assignscenedatatocameras (). According to the function name, it is not difficult to see that this is to assign this ox to the camera and enter the function. We find that this is indeed the case, first, it gives the cow to the scene rover, because it needs to use this ox during computing, _ cameramanipulator-> setnode (scenedata); we know, A view has a master camera. One of the most important tasks of this master camera is to implement the view transformation. The view transformation is inseparable from the scenario. Therefore, you need to give this master camera the head, _ camera-> addchild (scenedata); here we can see that the scene object is added to the master camera as a subnode. We know that a camera is also a transformation node, so we can add this ox as a child node under this camera, as long as we change the position and posture of the camera node, it is easy to implement the view transformation of the scene. Don't forget, we can have multiple cameras in one view. In addition to the main camera, there may be several subordinate cameras, and the subordinate camera can have its own scene tree, you can also directly use the scene tree of the primary camera. If you use the scene tree of the primary camera (multiple cameras observe the same scene ), we need to assign the scene to the main camera and all the subordinate cameras, or who will they take? So the next step is to give this ox to all the subordinate cameras (don't forget to make sure these cameras will also take care of this ox ),

For (unsigned I = 0; I <getnumslaves (); ++ I)

{

.....

If (scenedata) slave. _ camera-> addchild (scenedata );

......

}

From the analysis, we have basically understood how materials are put and where they are put.

Next we will look at how to process it.

Or that sentence, we can all go across the ocean to void viewerbase: frame (double simulationtime). What is it here? As we all know, this is the entire processing pipeline. Let's take a look. We will not go to the cleaning work, but we will go directly to the three major steps on the pipeline:

Eventtraversal ();

Updatetraversal ();

Renderingtraversals ();

Those who have read the longest frame should be very familiar with them (maybe they are familiar with all OSG, huh, huh). Here I will simply say, they are event traversal, update traversal, and rendering traversal (nonsense, you can see the name, ^ _ ^ ). We will not go in first. Let's analyze whether or not we want to go in first. First, let's take a look at eventtraversal (). Here we want to use the simplest process to look at Niu's processing, there was no event in the scene on the scene (no matter whether someone moved the ox from the cutting machine to a place and moved it back, or whether someone stole the ox's tail), it was just a rendering, so we don't care about it, but it doesn't mean that it has nothing to do with the oX. We just want to put the process in the most important processing process. It's enough to remember it, if you want to perform any interactive operations on the ox, such as moving the ox from one place to another (by dragging the mouse), we all know that this process is inseparable from the event processor, all their related processing is completed here. Given that the content is relatively messy and not concentrated, we will not analyze it in detail.

Updatetraversal (), the function is closely related to the ox, and it is not complicated, and the operations are relatively concentrated. Let's take a look at it. First, we can see that the most important one is _ scene-> updatescenegraph (* _ updatevisitor). We know that there is our cow in this scene and we can see what it has done, first, we can see that a view has an update access_updatevisitor, and we will see its usage later. The function starts to process operations on the paging database. It has nothing to do with our ox. For the time being, check the ox directly,

If (getscenedata ())

{

......

Getscenedata ()-> Accept (updatevisitor );

}

Here, we need to go to updatevisitor to see what we have done for Niu. This updatevisitor is an osgutil: updatevisitor, which is the _ updatevisitor owned by each view we mentioned earlier, it uses the visitor mode to update and access nodes. Let's take a look.

Virtual void apply (OSG: node & node)

{Handle_callbacks_and_traverse (node );}

Continue

Inline void handle_callbacks_and_traverse (OSG: node & node)

{

Handle_callbacks (node. getstateset ());

 

OSG: nodecallback * callback = node. getupdatecallback ();

If (callback) (* callback) (& node, this );

Elseif (node. getnumchildrenrequiringupdatetraversal ()> 0) traverse (node );

}

It has been quite clear here that it is to execute the callback of all scene nodes. For us, it is the callback of the cow (in fact, we didn't set the callback for the cow, so it will not be executed ). Remember, the node callback we set is executed here. We can see that

If (_ camera. Valid () & _ camera-> getupdatecallback () _ camera-> Accept (* _ updatevisitor );

 

For (unsigned int I = 0; I <getnumslaves (); ++ I)

{

OSG: View: slave & slave = getslave (I );

OSG: Camera * camera = slave. _ camera. Get ();

If (CAMERA & slave. _ usemastersscenedata & camera-> getupdatecallback ())

{

Camera-> Accept (* _ updatevisitor );

}

}

Updatevisitor accesses the master camera and all subordinate cameras and performs camera callback. Here you may ask, is it okay to directly execute an access request to all cameras? The scene is also a child node of the camera. It makes sense that people do not do that. You can see the code. when accessing the scenario and accessing the camera, the traversal mode is different. Accessing the scenario requires access from all nodes, to access the camera, you only need to access the camera itself, and do not need to traverse it. All accesses need to be separated. If I leave Niu, I will immediately return to the topic.

Before leaving this updatetraversal, I have to say that the following

If (_ cameramanipulator. Valid ())

{

......

_ Camera-> setviewmatrix (_ cameramanipulator-> getinversematrix ());

}

We know that scene view transformation, projection transformation, and scene filtering are all implemented by cameras. Now I will tell you that this is the most critical entry to implementation, sets the observation matrix of the master camera. This is where the result of various mouse and keyboard processing in your scenario is used. Without this, you can't see the machine on which your ox is on the production line, and you don't know where to throw the waste (cool, cool, etc) (scene screening, ^ _ ^ ).

Okay. So far, our updatetraversal is over. Remember what is next? Renderingtraversals, you don't have to think about it. Obviously, our journey is not complete yet, and we only have to worry about it, so it is essential. It is also the largest of the three.

In other words, the other mess in the function is not closely related to the canned cattle processing. So let's first look at

Scenes scenes;

Getscenes (Scenes );

 

For (scenes: iteratorsitr = scenes. Begin ();

Sitr! = Scenes. End ();

++ Sitr)

{

........

If (scene-> getscenedata ())

{

Scene-> getscenedata ()-> getbound ();

}

}

First, obtain all scenarios and calculate the sphere surrounded by scene nodes in all scenarios. Next

Cameras cameras;

Getcameras (cameras );

It obtains all the current active cameras.

Next let's take a look

For (Cameras: iterator camitr = cameras. Begin ();

Camitr! = Cameras. End ();

++ Camitr)

{

OSG: Camera * camera = * camitr;

Renderer * Renderer = dynamic_cast <Renderer *> (camera-> getrenderer ());

........

Renderer-> cull ();

........

}

Each camera has a Renderer. We know that invisible, too small, or blocked nodes in the scene must be cropped, that is to say, our Ox hair and Ox Horn cannot be canned and should be thrown away. This is done here, that is, to facilitate all cameras and use their respective camera Renderer objects to filter scenes. A camera corresponds to a Renderer. The Renderer mainly provides the interface for filtering and rendering scenes. Each Renderer generally has two sceneview members, two of which are used to achieve dual Buffering in the rendering background, we will see that the specific scene cropping and rendering are completed through the sceneview object, and the two members will be placed in a usable Scene Graph queue, each time you obtain the first scene chart from the queue, You can screen the scene and upload it to the end of the queue. In this way, one frame and one frame continue to run. Next we will go to the Renderer cull function to see how the specific screening process is completed.

First, as mentioned above, you can get the scenario diagram of the team header from the available scenario diagram queue:

Osgutil: sceneview * sceneview = _ availablequeue. takefront ();

Then, update the global rendering status of the scene chart:

Updatesceneview (sceneview );

Next, use the scenario diagram to filter the scenario:

Sceneview-> cull ();

Let's go in and see how all of them are filtered.

After entering, we will find many very unfamiliar things, such as rendering information, rendering stage, and state chart. We will not explain these things one by one. Although they are very useful, too many explanations will become messy, for more information, see the longest frame with detailed explanations and analysis on these objects. In this way, we can skip the vast majority of code and directly look at the cullstage. This is the core of cropping the entire rendering stage. After entering this function, we can see the cullvisitor-> traverse (* _ camera). A scenario graph contains a cropping accesser object responsible for scenario traversal and cropping, you may almost understand what will happen next. We all know the scenario screening. The most important thing is to judge the relationship between the node-enclosed box and the camera's normal head body, the specific point is whether the node surrounding box is included in the camera's normal head body or part, otherwise it will be filtered out. Well, let's put it short. You must know that we are actually a group node. Let's take a look at the processing of the Group in cullvisitor,

Void cullvisitor: The first row in the apply (Group & node) function is

If (isculled (node) return;

Go in and check out what we may want.

Inline bool isculled (const OSG: node & node)

{

Returnnode. iscullingactive () & getcurrentcullingset (). isculled (node. getbound ());

}

Well, it seems similar to what we want, because node. getbound () appears (). Hurry up and take a look.

Cullingset: isculled (const boundingsphere & BS) finally shows what we finally want, that is, if (! _ Frustum. Contains (BS) return true; As for it, it is purely a geometric problem and we will not pursue it. Well, we can see that if it is cropped, it will be returned directly, and nothing will be done. What if it is not cropped? Next, let's see:

Stateset * node_state = node. getstateset ();

If (node_state) pushstateset (node_state );

 

Handle_cull_callbacks_and_traverse (node );

Get the rendering status of the node, used to build the rendering status tree, and then traverse down.

So far, you must still have doubts that the cropped node is a brain that throws the skins of its meat, the only thing that remains is the rendering State. At best, the ox tendon and Ox blood are left behind. Where does the beef go? Well, you know, drawable is the final model vertex information stored in OSG, and only leaf nodes have them in the scenario tree. Therefore, you should look at the processing of geode by cullvisitor.

Look at Void cullvisitor: Apply (geode & node). The first line is also

If (isculled (node) return;

The next step is different. Pass, pass, and remove a bunch of chaos. We can see adddrawableanddepth (drawable, & matrix, depth );

You should have guessed what this is. Go in and take a look. There is one in the last line.

_ Currentstategraph-> addleaf (createorreuserenderleaf (drawable, _ projectionstack. Back (). Get (), matrix, depth ));

Simply put, this is to create a rendering leaf based on the drawable that has not been cropped, and add a state chart to draw the meat, that is to say, we have proposed beef tendon, beef, blood, beef, and other left-behind beef tendon, and so on. Now, our scenario screening is over.

Although it is also a little tired, but this short frame is not complete yet, at least the meat has not yet done a mature tank. As you can see, there are also _ drawqueue. Add (sceneview); this is to add the filtered scene map to the drawing queue.

To put it bluntly, sceneview-> cull (); now, let's take a look at scene rendering. Scene Rendering is also done through sceneview, that is, sceneview-> draw, where can we see it? In our above rederingtraversals, the following is a scenario filter:

For (itr = contexts. Begin ();

Itr! = Contexts. End ();

++ Itr)

{

If (_ DONE) return;

If (! (* Itr)-> getgraphicsthread () & (* itr)-> valid ())

{

......

(* Itr)-> runoperations ();

}

}

Go to runoperations () and we will see

For (cameravector: iterator itr = camerascopy. Begin ();

Itr! = Camerascopy. End ();

++ Itr)

{

OSG: Camera * camera = * itr;

If (camera-> getrenderer () (* (camera-> getrenderer () (this );

}

This is an operator overload, that is, the Renderer's

Virtual void operator () (OSG: graphicscontext * context );

Go in and check out. We can see draw (). Then, have you seen sceneview-> draw ()?

Well, now we can go to sceneview-> draw () and don't know. We can't see it until we finally find the most weeds and shrubs here. No matter what, look for the most obvious one. I guess it should be

_ Renderstage-> draw (_ renderinfo, previous );

There are also a lot of weeds in this area, and you can find the most conspicuous one:

Drawinner (userenderinfo, previous, docopytexture );

To tell the truth, I really don't want to go in and find anything again. I found that all of them are weeds. It's no longer obvious that I can catch my eye at once. If you are interested, let's see them one by one, it's almost the end of the plot.

This frame is actually very short. It is removed too much. Leave the topic as the topic and write the description later. It is a great pleasure to explore the source code. Believe it or not, I believe it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.