osg hudcamera-GizmoAxis
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
constexpr int NUM_OBJECTS = 10;
constexpr float OBJECT_SPACING = 0.1F;
template
osg::ref_ptr createScene()
{
osg::ref_ptr root = new osg::Group;
for (int m = 0; m < NUM_OBJECTS; ++m)
{
for (int n = 0; n < NUM_OBJECTS; ++n)
{
for (int k = 0; k < NUM_OBJECTS; ++k)
{
osg::ref_ptr geode = new osg::Geode;
osg::ref_ptr shapeDrawable = new osg::ShapeDrawable(new T(osg::Vec3(m + m * OBJECT_SPACING, n + n * OBJECT_SPACING, k + k * OBJECT_SPACING), 1.0F));
geode->addDrawable(shapeDrawable);
root->addChild(geode);
}
}
}
return root;
}
osg::ref_ptr createBoxFromObj(osg::ref_ptr nd)
{
osg::ComputeBoundsVisitor visitor;
nd->accept(visitor);
const auto& bound = visitor.getBoundingBox();
if (!bound.valid())
{
return nullptr;
}
osg::Vec3 center = bound.center();
double half_x = bound.xMax() - bound.xMin();
double half_y = bound.yMax() - bound.yMin();
double half_z = bound.zMax() - bound.zMin();
osg::ref_ptr node = new osg::Geode();
node->addChild(new osg::ShapeDrawable(new osg::Box(center, half_x, half_y, half_z)));
return node;
}
enum GizmoAxis : std::uint8_t
{
X_Axis,
Y_Axis,
Z_Axis
};
osg::ref_ptr createAxis(GizmoAxis axis, const osg::Vec4& color)
{
osg::ref_ptr pos = new osg::PositionAttitudeTransform();
osg::ref_ptr geometry = new osg::Geometry;
constexpr float radius = 0.02F;
constexpr float rr = radius + radius;
constexpr float half_height = 0.8F;
constexpr float top_position = half_height + 0.1F;
osg::ref_ptr const vertices = new osg::Vec3Array;
vertices->push_back(osg::Vec3(-radius, -radius, 0.0F));
vertices->push_back(osg::Vec3(radius, -radius, 0.0F));
vertices->push_back(osg::Vec3(radius, radius, 0.0F));
vertices->push_back(osg::Vec3(-radius, radius, 0.0F));
vertices->push_back(osg::Vec3(-radius, -radius, half_height));
vertices->push_back(osg::Vec3(radius, -radius, half_height));
vertices->push_back(osg::Vec3(radius, radius, half_height));
vertices->push_back(osg::Vec3(-radius, radius, half_height));
vertices->push_back(osg::Vec3(0.0F, 0.0F, top_position));
vertices->push_back(osg::Vec3(-rr, 0.0F, half_height));
vertices->push_back(osg::Vec3(0.0F, rr, half_height));
vertices->push_back(osg::Vec3(rr, 0.0F, half_height));
vertices->push_back(osg::Vec3(0.0F, -rr, half_height));
geometry->setVertexArray(vertices);
osg::ref_ptr const indices = new osg::DrawElementsUInt(GL_TRIANGLES);
indices->push_back(0);
indices->push_back(1);
indices->push_back(2); // 前面
indices->push_back(0);
indices->push_back(2);
indices->push_back(3);
indices->push_back(4);
indices->push_back(5);
indices->push_back(6); // 后面
indices->push_back(4);
indices->push_back(6);
indices->push_back(7);
indices->push_back(0);
indices->push_back(1);
indices->push_back(5); // 底面
indices->push_back(0);
indices->push_back(5);
indices->push_back(4);
indices->push_back(2);
indices->push_back(3);
indices->push_back(7); // 顶面
indices->push_back(2);
indices->push_back(7);
indices->push_back(6);
indices->push_back(0);
indices->push_back(3);
indices->push_back(7); // 左面
indices->push_back(0);
indices->push_back(7);
indices->push_back(4);
indices->push_back(1);
indices->push_back(2);
indices->push_back(6); // 右面
indices->push_back(1);
indices->push_back(6);
indices->push_back(5);
indices->push_back(8);
indices->push_back(9);
indices->push_back(10);
indices->push_back(8);
indices->push_back(10);
indices->push_back(11);
indices->push_back(8);
indices->push_back(11);
indices->push_back(12);
indices->push_back(8);
indices->push_back(12);
indices->push_back(9);
geometry->addPrimitiveSet(indices);
geometry->setUseVertexBufferObjects(true);
osg::ref_ptr const color_array = new osg::Vec4Array;
color_array->push_back(color);
geometry->setColorArray(color_array);
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
osg::Quat quat;
if (axis == GizmoAxis::X_Axis) { // X轴
quat.makeRotate(osg::DegreesToRadians(90.0), osg::Vec3(0.0f, 1.0f, 0.0f));
}
else if (axis == GizmoAxis::Y_Axis) { // Y轴
quat.makeRotate(osg::DegreesToRadians(-90.0), osg::Vec3(1.0f, 0.0f, 0.0f));
}
else { // Z轴 (默认已沿Z轴)
// 不需要旋转
}
pos->setAttitude(quat);
pos->addChild(geometry.get());
return pos.release();
}
// 函数:创建整个Gizmo坐标组
osg::Group* createGizmo()
{
osg::ref_ptr gizmoGroup = new osg::Group();
constexpr float len = 1.0F;
// X轴 (红色)
osg::ref_ptr xAxis = createAxis(GizmoAxis::X_Axis, osg::Vec4(len, 0.0f, 0.0f, len));
gizmoGroup->addChild(xAxis.get());
// Y轴 (绿色)
osg::ref_ptr yAxis = createAxis(GizmoAxis::Y_Axis, osg::Vec4(0.0f, len, 0.0f, len));
gizmoGroup->addChild(yAxis.get());
// Z轴 (蓝色)
osg::ref_ptr zAxis = createAxis(GizmoAxis::Z_Axis, osg::Vec4(0.0f, 0.0f, len, len));
gizmoGroup->addChild(zAxis.get());
gizmoGroup->addChild(new osg::ShapeDrawable(new osg::Sphere({ 0.0F,0.0F,0.0F }, 0.05F)));
return gizmoGroup.release();
}
class GizmoUpdater : public osg::NodeCallback
{
public:
GizmoUpdater(osg::Camera* camera, osg::MatrixTransform* gizmoTransform)
: _camera(camera), _gizmoTransform(gizmoTransform) {
}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (_camera.valid() && _gizmoTransform.valid())
{
// 获取操纵器的视图矩阵
osg::Matrix viewMatrix = _camera->getViewMatrix();
// 提取旋转部分 (去除平移)
osg::Quat rotation = viewMatrix.getRotate();
osg::Vec3 scale;
osg::Quat oldRotation; // 我们要替换这个旧旋转
osg::Vec3 translation;
osg::Quat so; // unused
_gizmoTransform->getMatrix().decompose(translation, oldRotation, scale, so);
osg::Quat cameraRotation = viewMatrix.getRotate();
osg::Matrix newMatrix = osg::Matrix::scale(scale) *
osg::Matrix::rotate(cameraRotation) *
osg::Matrix::translate(translation) ;
_gizmoTransform->setMatrix(newMatrix );
}
// 继续遍历场景图
traverse(node, nv);
}
protected:
osg::observer_ptr _camera;
osg::observer_ptr _gizmoTransform;
};
osg::Camera* createHudCamera(int width, int height, osg::Camera* cam)
{
osg::ref_ptr hudCam = new osg::Camera();
float gizmosize = width / 10.0F;
float padding = gizmosize / 10.0F;
hudCam->setProjectionMatrixAsOrtho2D(0, width, 0, height);
hudCam->setViewMatrix(osg::Matrix::identity());
hudCam->setClearMask(GL_DEPTH_BUFFER_BIT);
hudCam->setRenderOrder(osg::Camera::POST_RENDER);
hudCam->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
hudCam->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
osg::ref_ptr gizmoPlacement = new osg::MatrixTransform();
float gizmoX = width - padding - gizmosize;
float gizmoY = padding + gizmosize;
osg::Matrix transformMatrix =
osg::Matrix::scale(gizmosize, gizmosize, gizmosize) *
osg::Matrix::translate(gizmoX, gizmoY, 0.0F);
gizmoPlacement->setMatrix(transformMatrix );
gizmoPlacement->addChild(createGizmo());
gizmoPlacement->setUpdateCallback(new GizmoUpdater(cam, gizmoPlacement));
hudCam->addChild(gizmoPlacement);
return hudCam.release();
}
int main()
{
osg::DisplaySettings::instance()->setNumMultiSamples(4);
std::puts(\"hello from test_large_render\");
constexpr int width = 1920 >> 1;
constexpr int height = 960 >> 1;
osgViewer::Viewer viewer;
osg::ref_ptr root = new osg::Group();
osg::ref_ptr lodNode = new osg::LOD();
auto highdetail = createScene();
auto lowdetail = createScene();
osg::ref_ptr fardetail = createBoxFromObj(lowdetail);
constexpr float base_size = 50.0F;
lodNode->addChild(highdetail, 0.0F, base_size);
lodNode->addChild(lowdetail, base_size, base_size * 2);
lodNode->addChild(fardetail, base_size * 2, 1000);
root->addChild(lodNode);
root->addChild(createHudCamera(width, height, viewer.getCamera()));
viewer.setSceneData(root);
viewer.addEventHandler(new osgViewer::StatsHandler);
viewer.setUpViewInWindow(100, 100, width, height);
viewer.run();
return 0;
}