196 const osg::Quat& orientation)
198 const osg::Matrix masterView(osg::Matrix::translate(-position)
199 * osg::Matrix::rotate(orientation.inverse()));
200 _viewer->getCamera()->setViewMatrix(masterView);
201 const osg::Matrix& masterProj =
_viewer->getCamera()->getProjectionMatrix();
202 double masterZoomFactor = zoomFactor();
205 osg::Matrix view_matrix;
207 view_matrix = osg::Matrix::identity();
209 view_matrix = info->viewOffset;
211 view_matrix = masterView * info->viewOffset;
213 osg::Matrix proj_matrix;
215 const osg::GraphicsContext::Traits *traits =
216 info->compositor->getGraphicsContext()->getTraits();
217 proj_matrix = osg::Matrix::ortho2D(0, traits->width, 0, traits->height);
220 if (info->relativeCameraParent) {
222 osg::Matrix P0 = info->projOffset;
223 osg::Matrix
R = view_matrix;
226 osg::Matrix pP = info->relativeCameraParent->projMatrix;
227 osg::Matrix pR = info->relativeCameraParent->viewMatrix;
231 proj_matrix = relativeProjection(P0,
R, info->thisReference,
232 pP, pR, info->parentReference);
236 proj_matrix = info->projOffset;
237 proj_matrix.postMultScale(osg::Vec3d(masterZoomFactor,
242 proj_matrix = info->projOffset;
245 proj_matrix = masterProj * info->projOffset;
248 osg::Matrix new_proj_matrix = proj_matrix;
252 ProjectionMatrix::clampNearFarPlanes(proj_matrix,
_zNear,
_zFar,
256 info->viewMatrix = view_matrix;
257 info->projMatrix = new_proj_matrix;
258 info->compositor->update(view_matrix, new_proj_matrix);
290 const SGPropertyNode* windowNode = cameraNode->getNode(
"window");
305 ProjectionMatrix::Type proj_type = ProjectionMatrix::STANDARD;
308 if (cameraNode->getBoolValue(
"vr-mirror",
false))
312 const SGPropertyNode* viewNode = cameraNode->getNode(
"view");
314 double heading = viewNode->getDoubleValue(
"heading-deg", 0.0);
315 double pitch = viewNode->getDoubleValue(
"pitch-deg", 0.0);
316 double roll = viewNode->getDoubleValue(
"roll-deg", 0.0);
317 double x = viewNode->getDoubleValue(
"x", 0.0);
318 double y = viewNode->getDoubleValue(
"y", 0.0);
319 double z = viewNode->getDoubleValue(
"z", 0.0);
322 vOff = (Matrix::translate(-x, -y, -z)
323 * Matrix::rotate(-DegreesToRadians(heading),
324 Vec3d(0.0, 1.0, 0.0),
325 -DegreesToRadians(pitch),
326 Vec3d(1.0, 0.0, 0.0),
327 -DegreesToRadians(roll),
328 Vec3d(0.0, 0.0, 1.0)));
329 if (viewNode->getBoolValue(
"absolute",
false))
333 double heading = cameraNode->getDoubleValue(
"heading-deg", 0.0);
334 vOff.makeRotate(DegreesToRadians(heading), osg::Vec3(0, 1, 0));
337 SGPropertyNode* viewportNode = cameraNode->getNode(
"viewport",
true);
338 double physicalWidth = viewportNode->getDoubleValue(
"width", 1024);
339 double physicalHeight = viewportNode->getDoubleValue(
"height", 768);
340 double bezelHeightTop = 0;
341 double bezelHeightBottom = 0;
342 double bezelWidthLeft = 0;
343 double bezelWidthRight = 0;
344 const SGPropertyNode* physicalDimensionsNode = 0;
345 if ((physicalDimensionsNode = cameraNode->getNode(
"physical-dimensions")) != 0) {
346 physicalWidth = physicalDimensionsNode->getDoubleValue(
"width", physicalWidth);
347 physicalHeight = physicalDimensionsNode->getDoubleValue(
"height", physicalHeight);
348 const SGPropertyNode* bezelNode = 0;
349 if ((bezelNode = physicalDimensionsNode->getNode(
"bezel")) != 0) {
350 bezelHeightTop = bezelNode->getDoubleValue(
"top", bezelHeightTop);
351 bezelHeightBottom = bezelNode->getDoubleValue(
"bottom", bezelHeightBottom);
352 bezelWidthLeft = bezelNode->getDoubleValue(
"left", bezelWidthLeft);
353 bezelWidthRight = bezelNode->getDoubleValue(
"right", bezelWidthRight);
358 osg::Vec2d parentReference[2];
359 osg::Vec2d thisReference[2];
360 SGPropertyNode* projectionNode = 0;
361 if ((projectionNode = cameraNode->getNode(
"perspective")) != 0) {
362 double fovy = projectionNode->getDoubleValue(
"fovy-deg", 55.0);
363 double aspectRatio = projectionNode->getDoubleValue(
"aspect-ratio",
365 double zNear = projectionNode->getDoubleValue(
"near", 0.0);
366 double zFar = projectionNode->getDoubleValue(
"far", zNear + 20000);
367 double offsetX = projectionNode->getDoubleValue(
"offset-x", 0.0);
368 double offsetY = projectionNode->getDoubleValue(
"offset-y", 0.0);
369 double tan_fovy = tan(DegreesToRadians(fovy*0.5));
370 double right = tan_fovy * aspectRatio * zNear + offsetX;
371 double left = -tan_fovy * aspectRatio * zNear + offsetX;
372 double top = tan_fovy * zNear + offsetY;
373 double bottom = -tan_fovy * zNear + offsetY;
374 ProjectionMatrix::makeFrustum(pOff,
380 if (projectionNode->getBoolValue(
"fixed-near-far",
true))
382 }
else if ((projectionNode = cameraNode->getNode(
"frustum")) != 0
383 || (projectionNode = cameraNode->getNode(
"ortho")) != 0) {
384 double top = projectionNode->getDoubleValue(
"top", 0.0);
385 double bottom = projectionNode->getDoubleValue(
"bottom", 0.0);
386 double left = projectionNode->getDoubleValue(
"left", 0.0);
387 double right = projectionNode->getDoubleValue(
"right", 0.0);
388 double zNear = projectionNode->getDoubleValue(
"near", 0.0);
389 double zFar = projectionNode->getDoubleValue(
"far", zNear + 20000);
390 if (cameraNode->getNode(
"frustum")) {
391 ProjectionMatrix::makeFrustum(pOff,
398 ProjectionMatrix::makeOrtho(pOff,
405 if (projectionNode->getBoolValue(
"fixed-near-far",
true))
407 }
else if ((projectionNode = cameraNode->getNode(
"master-perspective")) != 0) {
408 double zNear = projectionNode->getDoubleValue(
"eye-distance", 0.4*physicalWidth);
409 double xoff = projectionNode->getDoubleValue(
"x-offset", 0);
410 double yoff = projectionNode->getDoubleValue(
"y-offset", 0);
411 double left = -0.5*physicalWidth - xoff;
412 double right = 0.5*physicalWidth - xoff;
413 double bottom = -0.5*physicalHeight - yoff;
414 double top = 0.5*physicalHeight - yoff;
415 ProjectionMatrix::makeFrustum(pOff,
418 zNear, zNear + 20000.0,
421 }
else if ((projectionNode = cameraNode->getNode(
"right-of-perspective"))
422 || (projectionNode = cameraNode->getNode(
"left-of-perspective"))
423 || (projectionNode = cameraNode->getNode(
"above-perspective"))
424 || (projectionNode = cameraNode->getNode(
"below-perspective"))
425 || (projectionNode = cameraNode->getNode(
"reference-points-perspective"))) {
426 std::string
name = projectionNode->getStringValue(
"parent-camera");
428 [&
name](
const auto &c) { return c->name == name; });
430 SG_LOG(SG_VIEW, SG_ALERT,
"CameraGroup::buildCamera: "
431 "failed to find parent camera for relative camera!");
435 if (projectionNode->getNameString() ==
"right-of-perspective") {
437 parentReference[0] = osg::Vec2d(tmp, -1);
438 parentReference[1] = osg::Vec2d(tmp, 1);
439 tmp = (physicalWidth + 2*bezelWidthLeft)/physicalWidth;
440 thisReference[0] = osg::Vec2d(-tmp, -1);
441 thisReference[1] = osg::Vec2d(-tmp, 1);
442 }
else if (projectionNode->getNameString() ==
"left-of-perspective") {
444 parentReference[0] = osg::Vec2d(-tmp, -1);
445 parentReference[1] = osg::Vec2d(-tmp, 1);
446 tmp = (physicalWidth + 2*bezelWidthRight)/physicalWidth;
447 thisReference[0] = osg::Vec2d(tmp, -1);
448 thisReference[1] = osg::Vec2d(tmp, 1);
449 }
else if (projectionNode->getNameString() ==
"above-perspective") {
451 parentReference[0] = osg::Vec2d(-1, tmp);
452 parentReference[1] = osg::Vec2d(1, tmp);
453 tmp = (physicalHeight + 2*bezelHeightBottom)/physicalHeight;
454 thisReference[0] = osg::Vec2d(-1, -tmp);
455 thisReference[1] = osg::Vec2d(1, -tmp);
456 }
else if (projectionNode->getNameString() ==
"below-perspective") {
458 parentReference[0] = osg::Vec2d(-1, -tmp);
459 parentReference[1] = osg::Vec2d(1, -tmp);
460 tmp = (physicalHeight + 2*bezelHeightTop)/physicalHeight;
461 thisReference[0] = osg::Vec2d(-1, tmp);
462 thisReference[1] = osg::Vec2d(1, tmp);
463 }
else if (projectionNode->getNameString() ==
"reference-points-perspective") {
464 SGPropertyNode* parentNode = projectionNode->getNode(
"parent",
true);
465 SGPropertyNode* thisNode = projectionNode->getNode(
"this",
true);
466 SGPropertyNode* pointNode;
468 pointNode = parentNode->getNode(
"point", 0,
true);
469 parentReference[0][0] = pointNode->getDoubleValue(
"x", 0)*2/parentInfo->
physicalWidth;
470 parentReference[0][1] = pointNode->getDoubleValue(
"y", 0)*2/parentInfo->
physicalHeight;
471 pointNode = parentNode->getNode(
"point", 1,
true);
472 parentReference[1][0] = pointNode->getDoubleValue(
"x", 0)*2/parentInfo->
physicalWidth;
473 parentReference[1][1] = pointNode->getDoubleValue(
"y", 0)*2/parentInfo->
physicalHeight;
475 pointNode = thisNode->getNode(
"point", 0,
true);
476 thisReference[0][0] = pointNode->getDoubleValue(
"x", 0)*2/physicalWidth;
477 thisReference[0][1] = pointNode->getDoubleValue(
"y", 0)*2/physicalHeight;
478 pointNode = thisNode->getNode(
"point", 1,
true);
479 thisReference[1][0] = pointNode->getDoubleValue(
"x", 0)*2/physicalWidth;
480 thisReference[1][1] = pointNode->getDoubleValue(
"y", 0)*2/physicalHeight;
483 ProjectionMatrix::makePerspective(pOff, 45, physicalWidth/physicalHeight,
484 1, 20000, proj_type);
488 double shearx = cameraNode->getDoubleValue(
"shear-x", 0);
489 double sheary = cameraNode->getDoubleValue(
"shear-y", 0);
490 pOff.makeTranslate(-shearx, -sheary, 0);
495 info->
name = cameraNode->getStringValue(
"name");
509 info->
mvr.views = cameraNode->getIntValue(
"mvr-views", 1);
510 info->
mvr.viewIdGlobalStr = cameraNode->getStringValue(
"mvr-view-id-global",
"");
511 info->
mvr.viewIdStr[0] = cameraNode->getStringValue(
"mvr-view-id-vert",
"0");
512 info->
mvr.viewIdStr[1] = cameraNode->getStringValue(
"mvr-view-id-geom",
"0");
513 info->
mvr.viewIdStr[2] = cameraNode->getStringValue(
"mvr-view-id-frag",
"0");
514 info->
mvr.cells = cameraNode->getIntValue(
"mvr-cells", 1);
516 osg::Viewport *viewport =
new osg::Viewport(
517 viewportNode->getDoubleValue(
"x"),
518 viewportNode->getDoubleValue(
"y"),
520 viewportNode->getDoubleValue(
"width", window->
gc->getTraits()->width),
521 viewportNode->getDoubleValue(
"height",window->
gc->getTraits()->height));
523 std::string compositor_path = cameraNode->getStringValue(
"compositor",
"");
524 if (compositor_path.empty()) {
525 compositor_path =
fgGetString(
"/sim/rendering/default-compositor",
526 "Compositor/default");
532 osg::ref_ptr<SGReaderWriterOptions>
options =
533 SGReaderWriterOptions::fromPath(
globals->get_fg_root());
538 Compositor *compositor =
nullptr;
542 compositor = Compositor::create(
_viewer,
552 throw sg_exception(std::string(
"Failed to create Compositor in path '") +
553 compositor_path +
"'");
849 const osg::Vec2d &windowPos,
850 osgUtil::LineSegmentIntersector::Intersections &intersections)
855 const osg::Viewport *viewport = cinfo->
compositor->getViewport();
856 SGRect<double> viewportRect(viewport->x(), viewport->y(),
857 viewport->x() + viewport->width() - 1.0,
858 viewport->y() + viewport->height()- 1.0);
859 double epsilon = 0.5;
860 if (!viewportRect.contains(windowPos.x(), windowPos.y(), epsilon))
863 osg::Vec4d start(windowPos.x(), windowPos.y(), 0.0, 1.0);
864 osg::Vec4d end(windowPos.x(), windowPos.y(), 1.0, 1.0);
865 osg::Matrix windowMat = viewport->computeWindowMatrix();
866 osg::Matrix invViewMat = osg::Matrix::inverse(cinfo->
viewMatrix);
867 osg::Matrix invProjMat = osg::Matrix::inverse(cinfo->
projMatrix * windowMat);
868 start = start * invProjMat;
869 end = end * invProjMat;
872 start = start * invViewMat;
873 end = end * invViewMat;
875 osg::ref_ptr<osgUtil::LineSegmentIntersector> picker =
876 new osgUtil::LineSegmentIntersector(osgUtil::Intersector::MODEL,
877 osg::Vec3d(start.x(), start.y(), start.z()),
878 osg::Vec3d(end.x(), end.y(), end.z()));
879 osgUtil::IntersectionVisitor
iv(picker);
880 iv.setTraversalMask(simgear::PICK_BIT);
882 const_cast<CameraGroup*
>(cgroup)->getView()->getSceneData()->accept(
iv);
883 if (picker->containsIntersections()) {
884 intersections = picker->getIntersections();
1008 SGPropertyNode* renderingNode =
fgGetNode(
"/sim/rendering");
1009 SGPropertyNode* cgroupNode = renderingNode->getNode(
"camera-group",
true);
1010 bool oldSyntax = !cgroupNode->hasChild(
"camera");
1012 for (
int i = 0;
i < renderingNode->nChildren(); ++
i) {
1013 SGPropertyNode* propNode = renderingNode->getChild(
i);
1014 const std::string propName = propNode->getNameString();
1015 if (propName ==
"window" || propName ==
"camera") {
1016 SGPropertyNode* copiedNode
1017 = cgroupNode->getNode(propName, propNode->getIndex(),
true);
1018 copyProperties(propNode, copiedNode);
1023 SGPropertyNode* masterCamera = 0;
1024 SGPropertyNodeVec::const_iterator it;
1025 for (it = cameras.begin(); it != cameras.end(); ++it) {
1026 if ((*it)->getDoubleValue(
"shear-x", 0.0) == 0.0
1027 && (*it)->getDoubleValue(
"shear-y", 0.0) == 0.0) {
1028 masterCamera = it->ptr();
1032 if (!masterCamera) {
1033 masterCamera = cgroupNode->getChild(
"camera", cameras.size(),
true);
1034 setValue(masterCamera->getNode(
"window/name",
true),
1037 setValue(masterCamera->getNode(
"vr-mirror",
true),
true);
1039 SGPropertyNode* nameNode = masterCamera->getNode(
"window/name");
1041 setValue(cgroupNode->getNode(
"gui/window/name",
true),
1042 nameNode->getStringValue());
1045 SGPropertyNode* splashWindowNameNode = cgroupNode->getNode(
"splash/window/name");
1046 if (!splashWindowNameNode) {
1049 for (
auto it = cameras.begin(); it != cameras.end(); ++it) {
1050 SGPropertyNode* nameNode = (*it)->getNode(
"window/name");
1053 setValue(cgroupNode->getNode(
"splash/window/name",
true),
1054 nameNode->getStringValue());