Visual Servoing Platform  version 3.6.1 under development (2025-03-16)
vpObjectCentricRenderer.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  */
30 
31 #include <visp3/rbt/vpObjectCentricRenderer.h>
32 
33 #include <visp3/core/vpRect.h>
34 
35 #include "boundingSphere.h"
36 #include "boundingBox.h"
37 #include "graphicsOutput.h"
38 #include "graphicsEngine.h"
39 #include "windowFramework.h"
40 #include "load_prc_file.h"
41 
42 BEGIN_VISP_NAMESPACE
43 
45  : vpPanda3DRendererSet(renderParameters), m_enableCrop(true), m_shouldComputeBBPoints(true)
46 {
47  m_renderParameters = renderParameters;
48 }
49 
51 {
52  if (m_shouldComputeBBPoints) {
54  m_shouldComputeBBPoints = false;
55  }
56  m_bb = computeBoundingBox();
57 
58  double delta = 0.0;
59  m_bb.setTop(std::max(m_bb.getTop() - delta, 0.0));
60  m_bb.setLeft(std::max(m_bb.getLeft() - delta, 0.0));
61  m_bb.setBottom(std::min(m_bb.getBottom() + delta, (double)m_renderParameters.getImageHeight()));
62  m_bb.setRight(std::min(m_bb.getRight() + delta, (double)m_renderParameters.getImageWidth()));
63 
64  if (m_enableCrop) {
66 
67  unsigned width = (unsigned)(m_bb.getWidth());
68  unsigned height = (unsigned)(m_bb.getHeight());
69  subParams.setImageResolution(height, width);
70  subParams.setClippingDistance(subParams.getNearClippingDistance() - 0.1, subParams.getFarClippingDistance());
71  const vpCameraParameters cam = subParams.getCameraIntrinsics();
72  subParams.setCameraIntrinsics(vpCameraParameters(cam.get_px(), cam.get_py(), cam.get_u0() - m_bb.getLeft(), cam.get_v0() - m_bb.getTop()));
73  for (std::shared_ptr<vpPanda3DBaseRenderer> &subrenderer : m_subRenderers) {
74  subrenderer->setRenderParameters(subParams);
75  }
76  }
77 }
78 
80 {
81  if (m_subRenderers.size() == 0) {
82  throw vpException(vpException::fatalError, "Cannot compute bounding box with no subrender");
83  }
84  std::shared_ptr<vpPanda3DBaseRenderer> subrenderer = m_subRenderers[0];
85  NodePath object = subrenderer->getRenderRoot().find(m_focusedObject);
86  if (object.is_empty()) {
87  throw vpException(vpException::badValue, "Focused node %s was not found", m_focusedObject.c_str());
88  }
89  m_bb3DPoints.clear();
90  LPoint3 minP, maxP;
91  object.calc_tight_bounds(minP, maxP);
92  const BoundingBox box(minP, maxP);
93 
94  for (unsigned int i = 0; i < 8; ++i) {
95  const LPoint3 p = box.get_point(i);
96  m_bb3DPoints.push_back(vpColVector({ p.get_x(), -p.get_z(), p.get_y(), 1.0 }));
97  }
98 }
99 
100 void vpObjectCentricRenderer::computeClipping(float &nearV, float &farV)
101 {
102  if (m_subRenderers.size() == 0) {
103  throw vpException(vpException::fatalError, "Cannot compute clpping distances with no subrenderer");
104  }
105  std::shared_ptr<vpPanda3DBaseRenderer> subrenderer = m_subRenderers[0];
106  NodePath object = subrenderer->getRenderRoot().find(m_focusedObject);
107  if (object.is_empty()) {
108  throw vpException(vpException::badValue, "Node %s was not found", m_focusedObject.c_str());
109  }
110  if (m_shouldComputeBBPoints) {
112  m_shouldComputeBBPoints = false;
113  }
114  const vpHomogeneousMatrix wTcam = getCameraPose();
116  const vpHomogeneousMatrix camTobj = wTcam.inverse() * wTobj;
117  float minZ = std::numeric_limits<float>::max(), maxZ = 0.f;
118  for (unsigned int i = 0; i < m_bb3DPoints.size(); ++i) {
119  vpColVector cpV = camTobj * m_bb3DPoints[i];
120  cpV /= cpV[3];
121  float Z = cpV[2];
122  if (Z > maxZ) {
123  maxZ = Z;
124  }
125  if (Z < minZ) {
126  minZ = Z;
127  }
128  }
129 
130  nearV = minZ;
131  farV = maxZ;
132 }
133 
135 {
136  if (m_subRenderers.size() == 0) {
137  throw vpException(vpException::fatalError, "Cannot compute bounding box with no subrenderer");
138  }
139  std::shared_ptr<vpPanda3DBaseRenderer> subrenderer = m_subRenderers[0];
140  NodePath object = subrenderer->getRenderRoot().find(m_focusedObject);
141  if (object.is_empty()) {
142  throw vpException(vpException::badValue, "Node %s was not found", m_focusedObject.c_str());
143  }
144  if (m_shouldComputeBBPoints) {
146  m_shouldComputeBBPoints = false;
147  }
148  const auto pointToPixel = [this](const vpHomogeneousMatrix &camTobj, const vpColVector &point) -> vpImagePoint {
149  vpColVector cpV = camTobj * point;
150  cpV /= cpV[3];
151  double x = cpV[0] / cpV[2];
152  double y = cpV[1] / cpV[2];
153  vpImagePoint ip;
155  ip.set_j(vpMath::clamp(ip.get_j(), 0.0, m_renderParameters.getImageWidth() - 1.0));
157  return ip;
158  };
159 
160  const vpHomogeneousMatrix wTcam = getCameraPose();
162  const vpHomogeneousMatrix camTobj = wTcam.inverse() * wTobj;
163 
164  double minu = m_renderParameters.getImageWidth(), maxu = 0.0, minv = m_renderParameters.getImageHeight(), maxv = 0.0;
165  for (unsigned int i = 0; i < m_bb3DPoints.size(); ++i) {
166  const vpImagePoint ip = pointToPixel(camTobj, m_bb3DPoints[i]);
167  double u = ip.get_u(), v = ip.get_v();
168  if (u < minu) {
169  minu = u;
170  }
171  if (u > maxu) {
172  maxu = u;
173  }
174  if (v < minv) {
175  minv = v;
176  }
177  if (v > maxv) {
178  maxv = v;
179  }
180  }
181  return vpRect(vpImagePoint(minv, minu), vpImagePoint(maxv, maxu));
182 }
183 
184 END_VISP_NAMESPACE
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:73
@ fatalError
Fatal error.
Definition: vpException.h:72
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
void set_j(double jj)
Definition: vpImagePoint.h:309
double get_j() const
Definition: vpImagePoint.h:125
void set_i(double ii)
Definition: vpImagePoint.h:298
double get_u() const
Definition: vpImagePoint.h:136
double get_i() const
Definition: vpImagePoint.h:114
double get_v() const
Definition: vpImagePoint.h:147
static T clamp(const T &v, const T &lower, const T &upper)
Definition: vpMath.h:218
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
void computeClipping(float &nearV, float &farV)
vpObjectCentricRenderer(const vpPanda3DRenderParameters &renderParameters)
void beforeFrameRendered() VP_OVERRIDE
static const vpHomogeneousMatrix PANDA_T_VISP
Homogeneous transformation matrix to convert from the Panda coordinate system (right-handed Z-up) to ...
vpPanda3DRenderParameters m_renderParameters
Pointer to owning window, which can create buffers etc. It is not necessarily visible.
Rendering parameters for a panda3D simulation.
void setClippingDistance(double nearV, double farV)
Set the clipping distance. When a panda camera uses these render parameters, objects that are closer ...
void setCameraIntrinsics(const vpCameraParameters &cam)
set camera intrinsics. Only camera intrinsics for a lens without distortion are supported.
const vpCameraParameters & getCameraIntrinsics() const
Retrieve camera intrinsics.
void setImageResolution(unsigned int height, unsigned int width)
Set the image resolution. When this object is given to a vpPanda3DBaseRenderer, this will be the reso...
Class that renders multiple datatypes, in a single pass. A renderer set contains multiple subrenderer...
std::vector< std::shared_ptr< vpPanda3DBaseRenderer > > m_subRenderers
vpHomogeneousMatrix getCameraPose() VP_OVERRIDE
Retrieve the pose of the camera. As this renderer contains multiple other renderers.
vpHomogeneousMatrix getNodePose(const std::string &name) VP_OVERRIDE
Retrieve the pose of a scene node. The pose is in the world frame, using a ViSP convention.
Defines a rectangle in the plane.
Definition: vpRect.h:79
double getWidth() const
Definition: vpRect.h:227
void setTop(double pos)
Definition: vpRect.h:357
double getLeft() const
Definition: vpRect.h:173
void setLeft(double pos)
Definition: vpRect.h:321
void setRight(double pos)
Definition: vpRect.h:348
double getRight() const
Definition: vpRect.h:179
double getBottom() const
Definition: vpRect.h:97
double getHeight() const
Definition: vpRect.h:166
void setBottom(double pos)
Definition: vpRect.h:288
double getTop() const
Definition: vpRect.h:192