preamble
Deeper understanding of the camera viewport, figuring out the camera viewport rotation function, background transparency or opacity.
In this post, a camera viewport with a rotating HUD in the lower left corner and a transparent background is implemented.
Demo
Coordinates of the HUD camera
The heads-up HUD is realized by a projection matrix, see "OSG Development Notes (XX): OSG Using HUD to Display Text" for details.
- Hud wants to create a new camera separately
- Note that the light is turned off and is not affected by the light, so the content is displayed at the same brightness
- Close Depth Test
- The rendering order is set to POST, otherwise it may be overwritten by other graphics in the scene.
- Set reference posting to absolute: setReferenceFrame(osg::Transform:ABSOLUTE_RF)
- Make it unaffected by parent transformations: setMatrix(osg::Matrix::identity())
- The projection matrix is usually set to the screen size size
Camera
Camera (osg::Camera) and Viewport are two core concepts that are crucial for understanding 3D scene rendering in OSG.
Camera is used in OSG to simulate a real-world camera, which is responsible for capturing and rendering a 3D scene. The camera class (osg::Camera) inherits from the osg::Transform and osg::CullSetting classes and is used to manage the model-view matrix in OSG. The management of the camera is mainly realized through various transformations which include:
- Viewpoint Transform: Sets the direction and position of the viewpoint. By default, the viewpoint is positioned at the coordinate origin, pointing in the Y-positive direction. The viewing direction and angle of the camera can be changed by adjusting the position of the viewpoint and the position of the reference point.
- Projection transformations: Since monitors can only display three-dimensional objects with two-dimensional images, they rely on projections to reduce the number of dimensions. The purpose of projection transformation is to define a field of view, so that the extra parts outside the field of view are cropped out, and only the relevant parts inside the field of view are finally entered into the image.OSG supports two types of projection: Perspective Projection and Orthographic Projection. Perspective Projection simulates the visual effect of the human eye, making distant objects appear smaller, while Orthographic Projection keeps the size of an object constant regardless of distance.
- Viewport Transformation: The display of objects projected within the viewport on a two-dimensional viewport plane. That is, after the geometric transformation, projection transformation and cropping transformation of the object displayed in the screen window in the specified area, this area is usually a rectangle, called the viewport.
ViewPort
Specifically, the viewport transformation involves the following parameters:
- Coordinates of the lower-left corner of the screen: defines the lower-left position of the viewport on the screen.
- Screen Width and Height: defines the width and height of the viewport, i.e. the size of the area of the screen where the scene captured by the camera is displayed.
In OSG, you can set the viewport by calling the camera's setViewport method. Example:
pCamera->setViewport(new osg::Viewport(0, 0, width, height));
This line of code creates a new viewport and sets it to the camera's current viewport. Where 0 and 0 are the coordinates of the bottom left corner of the screen, and width and height are the width and height of the viewport.
Relationship between camera and viewport
Cameras and viewports are closely linked in OSG and together they determine how a 3D scene is rendered. The camera is responsible for capturing and rendering the scene, while the viewport defines the position and size of the scene captured by the camera on the screen. By adjusting various transformations of the camera and setting the size and position of the viewport, rich 3D visual effects and interactive experiences can be realized.
Setting the Camera Observation Function
void setViewMatrixAsLookAt(const osg::Vec3d& eye, const osg::Vec3d& center, const osg::Vec3d& up);
- eye: indicates the position of the camera. This is a three-dimensional vector specifying the position of the camera in the world coordinate system.
- center: indicates the center of the camera's view. This is also a 3D vector specifying the center of the object or scene that the camera should focus on.
- up: indicates which direction is positive. This is also a 3D vector, and is usually used to specify the up direction of the camera (e.g., it is usually set to (0,0,1) to indicate that the positive direction of the Y-axis is up).
Setting the Camera Position and Orientation: You can precisely control the position and attitude of the camera by specifying the parameters eye, center, and up. The vector between eye and center represents the camera's viewing direction, while the up vector is used to determine the camera's upward orientation.
Turning Off the Manipulator: Before using the setViewMatrixAsLookAt function, you usually need to turn off the camera's Manipulator. This is because the viewer will automatically update the camera's viewing matrix, thus overriding the parameters you set with setViewMatrixAsLookAt. You can turn off the rover by calling viewer->setCameraManipulator(NULL).
Coordinate system: OSG uses a right-handed coordinate system where the X-axis is to the right, the Y-axis is up, and the Z-axis is forward. Therefore, when setting the eye, center and up parameters, you need to make sure that they conform to the rules of the right-handed coordinate system.
View Matrix: The setViewMatrixAsLookAt function actually realizes camera position and pose adjustment by setting the camera's view matrix. The view matrix is a 4x4 matrix that is used to transform the points in the camera coordinate system to the world coordinate system.
setViewMatrixAsLookAt is a powerful function that allows you to set the position and pose of the camera in an intuitive way. By using this function wisely, you can create a variety of complex and realistic 3D scenes and visual effects.
Demo key source code
Creating a Hud Camera
// Step 1: Create the HUD camera
// osg::ref_ptr<osg::Camera> pCamera = new osg::Camera;
osg::ref_ptr<HudRotateCamera> pCamera = new HudRotateCamera;
pCamera->setMasterCamera(_pViewer->getCamera());
// Step 2: Setting up the projection matrix
// pCamera->setProjectionMatrix(osg::Matrix::ortho2D(0, 1280, 0, 800));
// Step 3: Set up the view matrix and make sure it's not affected by other shapes in the scene, using absolute frame references.
pCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
pCamera->setViewMatrix(osg::Matrix::identity());
// Step 4: Clear the depth cache
pCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
// Step 5: Set the POST rendering order (render last)
// pCamera->setRenderOrder(osg::Camera::PRE_RENDER); // Render not show
// pCamera->setRenderOrder(osg::Camera::NESTED_RENDER);
pCamera->setRenderOrder(osg::Camera::POST_RENDER);
// Step 6: Set it to not receive events and never get focus.
pCamera->setAllowEventFocus(false);
// osg::ref_ptr<osg::Geode> pGeode = new osg::Geode();
// pGeode = new osg::Geode();
osg::ref_ptr<osg::StateSet> pStateSet = pGeode->getOrCreateStateSet();
// Step 7: Turn off the light
pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
// Step 9: Turn off depth testing
pStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
// pGeode->addDrawable(());
pCamera->addChild(pGeode.get());
pGroup->addChild(pCamera.get());
#ifndef HUDROTATECAMERA_H
#define HUDROTATECAMERA_H
#include "osg/Camera"
#include "osg/CopyOp"
class HudRotateCamera : public osg::Camera
{
public:
HudRotateCamera();
HudRotateCamera(const HudRotateCamera& copy, const osg::CopyOp ©Op = osg::CopyOp::SHALLOW_COPY);
META_Node(osg, HudRotateCamera);
public:
void setMasterCamera(Camera* camera);
public:
virtual void traverse(osg::NodeVisitor& nodeVisitor);
protected:
virtual ~HudRotateCamera();
protected:
osg::observer_ptr<Camera> _pMasterCamera; // A new camera has been added, mainly for getting proof of evidence
};
#endif // HUDROTATECAMERA_H
#include ""
HudRotateCamera::HudRotateCamera(): Camera()
{
}
HudRotateCamera::HudRotateCamera(const HudRotateCamera & copy, const osg::CopyOp & copyOp)
: Camera(copy, copyOp),
_pMasterCamera(copy._pMasterCamera)
{
}
HudRotateCamera::~HudRotateCamera()
{
}
void HudRotateCamera::setMasterCamera(osg::Camera *camera)
{
_pMasterCamera = camera;
}
void HudRotateCamera::traverse(osg::NodeVisitor &nodeVisitor)
{
double fovy, aspectRatio, vNear, vFar;
_pMasterCamera->getProjectionMatrixAsPerspective(fovy, aspectRatio, vNear, vFar);
// Set the projection matrix so that zooming doesn't work, and change it to an orthographic projection, which doesn't zoom in and out as the camera gets closer and farther away, so there's no zoom.
// Zooming in and out is based on left, right, up and down distances; the larger the object, the smaller it is; the smaller the object, the larger it is.
this->setProjectionMatrixAsOrtho(-50 * aspectRatio,
50 * aspectRatio,
-50,
50,
vNear,
vFar);
// Make the axes model the bottom left corner of the form.
osg::Vec3 vec3(-40, -40, 0);
if (_pMasterCamera.valid())
{
// Change the view matrix so that the move is fixed.
osg::Matrix matrix = _pMasterCamera->getViewMatrix();
// Make the movement fixed, i.e. always in the bottom-right corner of the form, otherwise the model will move if the left mouse button is held down and the model can be dragged or the model will move if the spacebar is pressed.
matrix.setTrans(vec3);
this->setViewMatrix(matrix);
}
osg::Camera::traverse(nodeVisitor);
}
Engineering Templates v1.35.0
fig. make a career out of it
Pitfall #1: Not displaying full screen right in the center as expected
concern
Would like to display in the middle all the time and be able to rotate and move the center, but the actual result is as follows, squares 100x100, spacing 1.0, test:
attempts
Test by reducing the face square to 10x10 and the line to a smaller size:
Reduced orthogonal projection:
It may have something to do with the camera viewing position, adding information such as camera position and orientation:
Nothing affects it:
Here may be a problem to understand, we need to project the region to the viewport, then a projection of the region of the size of the three-dimensional region, a projection to the desktop 2D his size, here is actually similar to the HUD, by way of HUD, added a few lines of code to set the projection matrix:
After testing, you can skip the camera to adjust the viewport, the center changes and also moves, so he is kind of in its location area.
Then go back to the front and find that it works too, fiddle with it again and find the following features:
So at this point, the aspect is 10, so the window size would be the same if it conformed to the 1:1 (10:10=1:1) ratio, changed to 400, 400 test, or the same:
But adjusting it to 800x800 is fine:
Putting it on max won't intercept less:
So this is a little confused, in short, it is solved, and the projection matrix and orthogonal matrix can be solved, test the projection matrix and orthogonal proof of collection of viewport size impact, but the impact of the specific don't know, as if 800x800 is the smallest (the other didn't test, only test 400x400, 600x600 can not be, look at the ratio of 800x800 is the smallest just full of windows).
It is also suspected that casting over a smaller area, enlarging the area, its position shrinks in turn, so it is not the same as understanding:
- One is to understand that projecting directly over, projecting over the area gets bigger so it gets bigger (it's not);
- One is to project past the region unchanged, then the region becomes larger view area visible spatial extent becomes larger (in practice, but the size of the viewport to the screen remains unchanged);
Combined above, and tested to increase the viewport, but also normal, so suspect that there may be a combination of qt and osg when this place set a minimum value, and may be right, welcome to explore, here to explore the depth of the temporary results, and solved, so do not continue to explore the depth of the.
settle (a dispute)
Modify the camera viewport size to a minimum of 800x800.
follow-up replenishment
Follow-up view of this qtosg compatibility class done, done with its own settings of 800x800, that's why:
Pitfall 2: Camera viewport area is opaque
concern
When used as the top text hud, it is transparent, but after making adjustments here, it is not transparent.
attempts
Modified the statement to be partially transparent, but it's gone.
settle (a dispute)
The camera is a projection matrix, no transparency, but why is the text hud transparent?
Pitfall 3: Built-in geometry is pure white when lighting is turned off
concern
After turning off the light, the geometry white
principle
Light off to set the color, and if you don't want to set the color, give the body a separate light off.
settle (a dispute)
Pitfall 4: Text not visible
concern
The text was not visible, and after rotating it, I realized it was too big.
Larger location.
attempts
Under testing it is expanding the display of the entire coordinate area, then it actually looks like it is shrinking.
settle (a dispute)
Pitfall 5: hud rotation center is not right
concern
Hud's center of rotation is off.
At this point the center of rotation is still not correct, you may need to adjust the center of rotation
principle
Started to go to modify the matrix, found that all wrong, in fact, the middle point has been 0, 0, 0, its is the center, then we set the text of the display point is not from 0, 0 can be.
Below, the corners of the quadrilateral are identified by changing them to 0, 0, 0, and then the center of the text is modified:
settle (a dispute)
Pitfall 6: hud rotation is reversed
concern
The rotation is inverted, then the lighting is inverted, something is wrong with the transformation matrix
principle
Geometric transformations of data are laborious to calculate, and the conclusions of direct tests:
The code is written backwards so that the top and bottom are reversed, it should be -50~50
settle (a dispute)
There is still the light problem left, this is not good how to get it, anyway, turn off the light, or manually add your own light source, with the system may be a bit of a problem.
This is not solved for the time being, the actual use is to use one, you can set up a light source from the length of this camera alone, here because the demand itself does not need to project, do not do the test.