Before:
1. if the camera is not a slave camera
1.1 set the eventState's graphics context to the current context.
2. if the current master view is not the view which has the focus
2.1 set the current master view to be the view which has the focus
2.2 use the new master view's eventState instead of the old one
Now as you can see from this sequence, the graphics context is set on the eventState before switching to the view which has focus (and thus using another eventState). So the new eventState, in the case we need to switch views, will contain an old graphics context, not the correct one.
Just inversing these steps fixes the problem:
1. if the current master view is not the view which has the focus
1.1 set the current master view to be the view which has the focus
1.2 use the new master view's eventState instead of the old one
2. if the camera is not a slave camera
2.1 set the eventState's graphics context to the current context.
Now, the eventState will refer to the correct graphics context in both cases.
Attached is a fixed CompositeViewer.cpp (based on today's SVN) which does this. Note that some other things are done in the 1. and 2. cases, but they have no influence on each other so they can just be swapped without problems.
"
set to off. But could be activated/decativated via CMake as well as system
environment variable. I also modified src\osgViewer\CMakeLists.txt to turn
off this workaround by default as suggested."
parts of their scene graphs. Within these common part some nodes have
event handlers which use the action adapter argument to the event
handler to determinate which view received the event.
Here is the problem, osgViewer::CompositeViewer::eventTraversal sets
the action adapter field in the EventVisitor always to the last view
which received an event, instead of using the view which actually
received the event, so determination of the correct view does not work.
I looked at the code a bit, and moved the code for setting the action
adapter to a IMO better place"
facilitate the subclassing of Image providing interactive behaviours so as
used in the vnc interactive VncImage class.
osgViewer::InteractiveImageHandler provides an event handler that convertes osgGA
mouse and keyboard events into the coordinate frame of an image based on ray intersection with geometry in
the associated subgraph.
Changed the ordering of events processing in Viewer and CompositeViewer to allow
scene graph event handlers to take precidence over viewer event handlers and camera manipulators
The graph is displayed "under" (behind) the normal bar chart you get when you press 's' twice. It doesn't hide the normal stats, you can still read them without any trouble, and that way, it doesn't take any more screen space. It starts from the left, and will scroll left when there is enough data to fill the screen width. The graph lines have the same colors we're used to (except I made the event color a bit bluer, so it's not exactly the same as the update color). A screen shot is attached.
The lines get a bit confused when they're all overlapping at the bottom of the graph, but I think that's the least of our concerns (if they're all at the bottom of the graph - except FPS of course - then great!).
The only thing I'm not very keen about is that to make things simple, I clamp the values to a given maximum. Right now, the maximums I have set are:
* Frame rate: 100 fps (people have 60, 75, 85Hz refresh rates, so there's no one right value, but I think 100 is OK)
* Stats: 0.016 seconds (what you need to get 60Hz minimum)
This could be changed so that the scale of the graph changes according to the maximum value in the last screenful of the graph instead of clamping values. We would then need to display the scale for each value on the side of the graph, because if the scale changes, you need to know what it is at this moment.
I tried to make things easy to change, so for example if you don't like that the graph is in the same space as the normal stats bars, it's easy to move it anywhere else, and make it have other dimensions. The maximums and colors are also easy to change.
The impact on performance should be minimal, since it's one vertex per graph line that's added per frame, and vertices are removed when they scroll off the screen, so you'll never have more than say 1280 * (3 + ncameras) vertices on the screen at one time. No polygons, I used line strips. The scrolling is done with a MatrixTransform."
This code will add two extra statistics options:
-Camera scene statistics, stats for the scene after culling (updated at 10 Hz)
-View scene statistics, stats for the complete scene (updated at 5 Hz)
Each camera and each view will expand the statistics to the right.
I also added the requests and objects to compile of the databasepager to the databasepager statistics.""
> Using QOSGWidget - QWidget + osgViewer creating the graphics context.
>
> Windows Error #2000: [Screen #0] GraphicsWindowWin32::setWindow() - Unable
> to create OpenGL rendering context. Reason: The pixel format is invalid.
>
>
>
> And then the following fate error pops up:
>
>
>
> The instruction at "0x014c7ef1" referenced memory at "0x000000a4", The
> memory could not be "read".
>
> Click on Ok to terminate the program
>
> Click on CANCEL to debug the program
>
>
set.
The optimization is based on the observation that matrix matrix multiplication
with a dense matrix 4x4 is 4^3 Operations whereas multiplication with a
transform, or scale matrix is only 4^2 operations. Which is a gain of a
*FACTOR*4* for these special cases.
The change implements these special cases, provides a unit test for these
implementation and converts uses of the expensiver dense matrix matrix
routine with the specialized versions.
Depending on the transform nodes in the scenegraph this change gives a
noticable improovement.
For example the osgforest code using the MatrixTransform is about 20% slower
than the same codepath using the PositionAttitudeTransform instead of the
MatrixTransform with this patch applied.
If I remember right, the sse type optimizations did *not* provide a factor 4
improovement. Also these changes are totally independent of any cpu or
instruction set architecture. So I would prefer to have this current kind of
change instead of some hand coded and cpu dependent assembly stuff. If we
need that hand tuned stuff, these can go on top of this changes which must
provide than hand optimized additional variants for the specialized versions
to give a even better result in the end.
An other change included here is a change to rotation matrix from quaterion
code. There is a sqrt call which couold be optimized away. Since we divide in
effect by sqrt(length)*sqrt(length) which is just length ...
"
New attribute DatabasePager::_expiryFrames sets number of frames a PagedLOD child is kept in memory. The attribute is set with DatabasePager::setExpiryFrames method or OSG_EXPIRY_FRAMES environmental variable.
New attribute PagedLOD::PerRangeData::_
frameNumber contains frame number of last cull traversal.
Children of PagedLOD are expired when time _AND_ number of frames since last cull traversal exceed OSG_EXPIRY_DELAY _AND_ OSG_EXPIRY_FRAMES respectively. By default OSG_EXPIRY_FRAMES = 1 which means that nodes from last cull/rendering
traversal will not be expired even if last cull time exceeds OSG_EXPIRY_DELAY. Setting OSG_EXPIRY_FRAMES = 0 revokes previous behaviour of PagedLOD.
Setting OSG_EXPIRY_FRAMES > 0 fixes problems of children reloading in lazy rendering applications. Required behaviour is achieved by manipulating OSG_EXPIRY_DELAY and OSG_EXPIRY_FRAMES together.
Two interface changes are made:
DatabasePager::updateSceneGraph(double currentFrameTime) is replaced by DatabasePager::updateSceneGraph(const osg::FrameStamp &frameStamp). The previous method is in #if 0 clause in the header file. Robert, decide if You want to include it.
PagedLOD::removeExpiredChildren(double expiryTime, NodeList &removedChildren) is deprecated (warning is printed), when subclassing use PagedLOD::removeExpiredChildren(double expiryTime, int expiryFrame, NodeList &removedChildren) instead. "
viewer.addEventHandler(new osgViewer::ScreenCaptureHandler(
new osgViewer::WriteToFileCaptureOperation("filename", "jpg")));
and the filename will be what you want. The WriteToFileCaptureOperation will add the context ID and the file number (if in SEQUENTIAL_NUMBER mode) to the file name.
(The attached also clarifies some notify messages, and corrects the comment when adding the handler in osgviewer.cpp)
I also remembered, the current architecture could allow a different CaptureOperation for each context, but currently the API only allows setting one CaptureOperation for all contexts. This could be improved if need be.
"
calling wglMakeCurrent twice.
This bug has been reported to NVidia, confirmed and fixed by NVidia but awaits verifiaction and release if a driver which fixes this bug.
osgViewer::GraphicsWindow::setCursor() the new cursor type is recorded
but not applied until windows sends another WM_SETCURSOR message. This
delays the application of the cursor to the next mouse event.
The attached file fixes this by setting the new cursor with a call to
::SetCursor() immediately.
"
multi-threaded paging, where the Pager manages threads of reading local
and http files via seperate threads. This makes it possible to smoothly
browse large databases where parts of the data are locally cached while
others are on a remote server. Previously with this type of dataset
the pager would stall all paging while http requests were being served,
even when parts of the models are still loadable virtue of being in the
local cache.
Also as part of the refactoring the DatabaseRequest are now stored in the
ProxyNode/PagedLOD nodes to facilitate quite updating in the cull traversal,
with the new code avoiding mutex locks and searches. Previous on big
databases the overhead involved in make database requests could accumulate
to a point where it'd cause the cull traversal to break frame. The overhead
now is negligable.
Finally OSG_FILE_CACHE support has been moved from the curl plugin into
the DatabasePager. Eventually this functionality will be moved out into
osgDB for more general usage.