Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpPanda3DBaseRenderer.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/ar/vpPanda3DBaseRenderer.h>
32
33#if defined(VISP_HAVE_PANDA3D)
34
35#include <visp3/ar/vpPanda3DFrameworkManager.h>
36#include <visp3/core/vpMath.h>
37
38
39#include <antialiasAttrib.h>
40#include "boundingSphere.h"
41#include "boundingBox.h"
42#include "thread.h"
43#include "load_prc_file.h"
44#include "windowFramework.h"
45#include "graphicsOutput.h"
46
49 1.0, 0.0, 0.0, 0.0,
50 0.0, 0.0, -1., 0.0,
51 0.0, 1.0, 0.0, 0.0,
52 0.0, 0.0, 0.0, 1.0
53});
55
57
59
61{
62 // if (m_window != nullptr) {
63 // for (GraphicsOutput *buffer: m_buffers) {
64 // buffer->get_engine()->remove_window(buffer);
65 // }
66 // }
67 // m_buffers.clear();
68 if (m_window != nullptr) {
69 for (GraphicsOutput *buffer: m_buffers) {
70 buffer->set_active(false);
71 buffer->clear_render_textures();
72 }
73 }
74 m_buffers.clear();
75 if (m_isWindowOwner) {
77 frameworkManager.registerDisabledWindow(m_window);
78 }
79}
80
82{
83
85 PandaFramework &framework = frameworkManager.getFramework();
86 frameworkManager.initFramework();
87
88 if (m_renderParameters.getImageHeight() == 0 || m_renderParameters.getImageWidth() == 0) {
90 "Panda3D renderer: Cannot create a window with 0 height or width.");
91 }
92
93 m_isWindowOwner = true;
94
95 WindowProperties winProps;
96 winProps.set_size(LVecBase2i(m_renderParameters.getImageWidth(), m_renderParameters.getImageHeight()));
97 int flags = GraphicsPipe::BF_refuse_window;
98 m_window = framework.open_window(winProps, flags, nullptr, nullptr);
99 // try and reopen with visible window
100 if (m_window == nullptr) {
101 winProps.set_minimized(true);
102 m_window = framework.open_window(winProps, 0, nullptr, nullptr);
103 }
104 if (m_window == nullptr) {
106 "Panda3D renderer: Could not create the requested window when performing initialization.");
107 }
108 m_window->set_background_type(WindowFramework::BackgroundType::BT_black);
109 setupScene();
110 setupCamera();
112 //m_window->get_display_region_3d()->set_camera(m_cameraPath);
113}
114
115void vpPanda3DBaseRenderer::initFromParent(PointerTo<WindowFramework> window)
116{
117 m_isWindowOwner = false;
118 m_window = window;
119 setupScene();
120 setupCamera();
122}
123
129
131{
132 m_renderRoot = m_window->get_render().attach_new_node(m_name);
133 //m_renderRoot.set_antialias(AntialiasAttrib::M_none);
134}
135
137{
138 m_cameraPath = m_window->make_camera();
139 m_camera = (Camera *)m_cameraPath.node();
140 // m_camera = m_window->get_camera(0);
141 m_cameraPath = m_renderRoot.attach_new_node(m_camera);
142 m_renderParameters.setupPandaCamera(m_camera);
143 m_camera->set_scene(m_renderRoot);
144}
145
147{
149 // Disable rendering for all the other renderers
151 m_window->get_graphics_output()->get_engine()->render_frame();
154}
155
157{
158 GraphicsOutput *mainBuffer = getMainOutputBuffer();
159 if (mainBuffer != nullptr) {
160 mainBuffer->get_engine()->extract_texture_data(mainBuffer->get_texture(), mainBuffer->get_gsg());
161 }
162}
163
165{
166 unsigned int previousH = m_renderParameters.getImageHeight(), previousW = m_renderParameters.getImageWidth();
167 bool resize = previousH != params.getImageHeight() || previousW != params.getImageWidth();
168
169 m_renderParameters = params;
170
171 if (resize) {
172 for (GraphicsOutput *buffer: m_buffers) {
173 //buffer->get_type().is_derived_from()
174 GraphicsBuffer *buf = dynamic_cast<GraphicsBuffer *>(buffer);
175 if (buf == nullptr) {
176 throw vpException(vpException::fatalError, "Panda3D: could not cast to GraphicsBuffer when rendering.");
177 }
178 else {
179 buf->set_size(m_renderParameters.getImageWidth(), m_renderParameters.getImageHeight());
180 }
181 }
182 }
183
184 // If renderer is already initialized, modify camera properties
185 if (m_camera != nullptr) {
186 m_renderParameters.setupPandaCamera(m_camera);
187 }
188}
189
191{
192 if (m_camera.is_null() || m_cameraPath.is_empty()) {
193 throw vpException(vpException::notInitialized, "Camera was not initialized before trying to set its pose");
194 }
196}
197
199{
200 if (m_camera.is_null()) {
201 throw vpException(vpException::notInitialized, "Camera was not initialized before trying to get its pose");
202 }
204}
205
206void vpPanda3DBaseRenderer::setNodePose(const std::string &name, const vpHomogeneousMatrix &wTo)
207{
208 NodePath object = m_renderRoot.find(name);
209 setNodePose(object, wTo);
210}
211
213{
214 const vpHomogeneousMatrix wpTo = wTo * VISP_T_PANDA;
217 object.set_pos(t[0], t[1], t[2]);
218 object.set_quat(LQuaternion(q.w(), q.x(), q.y(), q.z()));
219}
220
222{
223 NodePath object = m_renderRoot.find(name);
224 if (object.is_empty()) {
225 throw vpException(vpException::badValue, "Node %s was not found", name.c_str());
226 }
227 return getNodePose(object);
228}
229
231{
232 const LPoint3 pos = object.get_pos();
233 const LQuaternion quat = object.get_quat();
234 const vpTranslationVector t(pos[0], pos[1], pos[2]);
235 const vpQuaternionVector q(quat.get_i(), quat.get_j(), quat.get_k(), quat.get_r());
236 return vpHomogeneousMatrix(t, q) * PANDA_T_VISP;
237}
238
239void vpPanda3DBaseRenderer::computeNearAndFarPlanesFromNode(const std::string &name, float &nearV, float &farV, bool fast)
240{
241 if (m_camera == nullptr) {
242 throw vpException(vpException::notInitialized, "Cannot compute planes when the camera is not initialized");
243 }
244 NodePath object = m_renderRoot.find(name);
245 if (object.is_empty()) {
246 throw vpException(vpException::badValue, "Node %s was not found", name.c_str());
247 }
248 if (!fast) {
249 LPoint3 minP, maxP;
250 object.calc_tight_bounds(minP, maxP);
251 const BoundingBox box(minP, maxP);
252 float minZ = std::numeric_limits<float>::max(), maxZ = 0.f;
253 const vpHomogeneousMatrix wTcam = getCameraPose();
255 const vpHomogeneousMatrix camTobj = wTcam.inverse() * wTobj;
256 for (unsigned int i = 0; i < 8; ++i) {
257 const LPoint3 p = box.get_point(i);
258 const vpColVector pv = vpColVector({ p.get_x(), -p.get_z(), p.get_y(), 1.0 });
259 vpColVector cpV = camTobj * pv;
260 cpV /= cpV[3];
261 float Z = cpV[2];
262 if (Z > maxZ) {
263 maxZ = Z;
264 }
265 if (Z < minZ) {
266 minZ = Z;
267 }
268 }
269
270 nearV = minZ;
271 farV = maxZ;
272 }
273 else {
274 const BoundingVolume *volume = object.node()->get_bounds();
275 if (volume->get_type() == BoundingSphere::get_class_type()) {
276 const BoundingSphere *sphere = (const BoundingSphere *)volume;
277 const LPoint3 center = sphere->get_center();
278 const float distCenter = (center - m_cameraPath.get_pos()).length();
279 nearV = vpMath::maximum<float>(0.f, distCenter - sphere->get_radius());
280 farV = vpMath::maximum<float>(nearV, distCenter + sphere->get_radius());
281 }
282 else if (volume->get_type() == BoundingBox::get_class_type()) {
283 const vpHomogeneousMatrix wTcam = getCameraPose();
285 const vpHomogeneousMatrix camTobj = wTcam.inverse() * wTobj;
286 const BoundingBox *box = (const BoundingBox *)volume;
287 double minZ = std::numeric_limits<double>::max(), maxZ = 0.0;
288
289 for (unsigned int i = 0; i < 8; ++i) {
290 const LPoint3 p = box->get_point(i);
291 vpColVector cp = camTobj * vpColVector({ p.get_x(), -p.get_z(), p.get_y(), 1.0 });
292 double Z = cp[2] / cp[3];
293 if (Z < minZ) {
294 minZ = Z;
295 }
296 if (Z > maxZ) {
297 maxZ = Z;
298 }
299 }
300 nearV = minZ;
301 farV = maxZ;
302 }
303 else {
304 throw vpException(vpException::fatalError, "Unhandled bounding volume %s type returned by Panda3d", volume->get_type().get_name().c_str());
305 }
306 }
307}
308
310{
311 if (isRendering3DScene()) {
312 PointerTo<GraphicsOutput> buffer = getMainOutputBuffer();
313 if (buffer != nullptr) {
314 buffer->set_clear_depth_active(false);
315 if (!buffer->share_depth_buffer(sourceBuffer.getMainOutputBuffer())) {
316 throw vpException(vpException::fatalError, "Could not share depth buffer!");
317 }
318 }
319 }
320}
321
323{
324 int previousOrder = m_renderOrder;
325 m_renderOrder = order;
326 for (GraphicsOutput *buffer: m_buffers) {
327 buffer->set_sort(buffer->get_sort() + (order - previousOrder));
328 }
329}
330
331NodePath vpPanda3DBaseRenderer::loadObject(const std::string &nodeName, const std::string &modelPath)
332{
333 PandaFramework &framework = vpPanda3DFrameworkManager::getInstance().getFramework();
334 NodePath model = m_window->load_model(framework.get_models(), modelPath);
335 if (model.is_empty()) {
336 throw vpException(vpException::ioError, "Could not load model %s", modelPath.c_str());
337 }
338 for (int i = 0; i < model.get_num_children(); ++i) {
339 model.get_child(i).clear_transform();
340 }
341
342 model.detach_node();
343 model.set_name(nodeName);
344 return model;
345}
346
347void vpPanda3DBaseRenderer::addNodeToScene(const NodePath &object)
348{
349 if (m_camera == nullptr) {
350 throw vpException(vpException::notInitialized, "Renderer was not initialized before trying to add a node to the scene");
351 }
352 NodePath objectInScene = object.copy_to(m_renderRoot);
353 objectInScene.set_name(object.get_name());
354 setNodePose(objectInScene, vpHomogeneousMatrix());
355}
356
357void vpPanda3DBaseRenderer::addObjectToScene(const std::string &name, const std::string &path)
358{
359 addNodeToScene(loadObject(name, path));
360}
361
363{
364 if (useVsync) {
365 load_prc_file_data("", "sync-video true");
366 }
367 else {
368 load_prc_file_data("", "sync-video false");
369 }
370}
372{
373 if (abort) {
374 load_prc_file_data("", "assert-abort 1");
375 }
376 else {
377 load_prc_file_data("", "assert-abort 0");
378 }
379}
380
382{
383 load_prc_file_data("", "gl-debug 1");
384 load_prc_file_data("", "notify-level-display spam");
385}
386
388{
389 vpColVector pandaPos = PANDA_T_VISP * point;
390 pandaPos /= pandaPos[3];
391 return pandaPos;
392}
394{
395 vpColVector pandaPos = PANDA_T_VISP.getRotationMatrix() * point;
396 return pandaPos;
397}
398
403
404END_VISP_NAMESPACE
405
406#elif !defined(VISP_BUILD_SHARED_LIBS)
407// Work around to avoid warning: libvisp_ar.a(vpPanda3DBaseRenderer.cpp.o) has no symbols
408void dummy_vpPanda3DBaseRenderer() { }
409
410#endif
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ ioError
I/O error.
Definition vpException.h:67
@ badValue
Used to indicate that a value is not in the allowed range.
Definition vpException.h:73
@ notInitialized
Used to indicate that a parameter is not initialized.
Definition vpException.h:74
@ fatalError
Fatal error.
Definition vpException.h:72
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpRotationMatrix getRotationMatrix() const
vpHomogeneousMatrix inverse() const
vpTranslationVector getTranslationVector() const
static Type maximum(const Type &a, const Type &b)
Definition vpMath.h:257
vpPanda3DBaseRenderer(const std::string &rendererName)
virtual void setupCamera()
Initialize camera. Should be called when the scene root of this render has already been created.
virtual void setupScene()
Initialize the scene for this specific renderer.
virtual vpHomogeneousMatrix getCameraPose()
Retrieve the camera's pose, in the world frame. The pose is specified using the ViSP convention (Y-do...
NodePath m_renderRoot
Rendering parameters.
PointerTo< Camera > m_camera
Node containing all the objects and the camera for this renderer.
virtual bool isRendering3DScene() const
Returns true if this renderer process 3D data and its scene root can be interacted with.
static vpColVector vispPointToPanda(const vpColVector &point)
virtual void initFramework()
Initialize the whole Panda3D framework. Create a new PandaFramework object and a new window.
void setVerticalSyncEnabled(bool useVsync)
set whether vertical sync is enabled. When vertical sync is enabled, render speed will be limited by ...
static const vpHomogeneousMatrix PANDA_T_VISP
Homogeneous transformation matrix to convert from the Panda coordinate system (right-handed Z-up) to ...
std::string m_name
Inverse of VISP_T_PANDA.
virtual void addObjectToScene(const std::string &name, const std::string &path)
Load and and an object to the scene.
bool m_isWindowOwner
Set of buffers that this renderer uses. This storage contains weak refs to those buffers and should n...
virtual void addNodeToScene(const NodePath &object)
Add a node to the scene. Its pose is set as the identity matrix.
void setAbortOnPandaError(bool abort)
Set the behaviour when a Panda3D assertion fails. If abort is true, the program will stop....
static const vpHomogeneousMatrix & pandaToVisp()
static const vpHomogeneousMatrix & vispToPanda()
static const vpHomogeneousMatrix VISP_T_PANDA
std::vector< PointerTo< GraphicsOutput > > m_buffers
NodePath of the camera.
PointerTo< WindowFramework > m_window
Rendering priority for this renderer and its buffers. A lower value will be rendered first....
virtual PointerTo< GraphicsOutput > getMainOutputBuffer()
virtual void enableSharedDepthBuffer(vpPanda3DBaseRenderer &sourceBuffer)
virtual void setupRenderTarget()
Initialize buffers and other objects that are required to save the render.
static vpColVector vispVectorToPanda(const vpColVector &vec)
virtual void setRenderParameters(const vpPanda3DRenderParameters &params)
Set new rendering parameters. If the scene has already been initialized, the renderer camera is updat...
virtual void initFromParent(PointerTo< WindowFramework > window)
NodePath loadObject(const std::string &nodeName, const std::string &modelPath)
Load a 3D object. To load an .obj file, Panda3D must be compiled with assimp support.
int m_renderOrder
name of the renderer
virtual void setNodePose(const std::string &name, const vpHomogeneousMatrix &wTo)
Set the pose of a node. This node can be any Panda object (light, mesh, camera). The pose is specifie...
virtual void setCameraPose(const vpHomogeneousMatrix &wTc)
Set the camera's pose. The pose is specified using the ViSP convention (Y-down right handed).
vpPanda3DRenderParameters m_renderParameters
Pointer to owning window, which can create buffers etc. It is not necessarily visible.
void computeNearAndFarPlanesFromNode(const std::string &name, float &nearV, float &farV, bool fast)
Compute the near and far planes for the camera at the current pose, given a certain node/part of the ...
virtual vpHomogeneousMatrix getNodePose(const std::string &name)
Get the pose of a Panda node, in world frame in the ViSP convention (Y-down right handed).
Base class for a panda3D renderer. This class handles basic functionalities, such as loading object,...
void registerDisabledWindow(PointerTo< WindowFramework > wf)
static vpPanda3DFrameworkManager & getInstance()
void disableAllOtherRenderers(PointerTo< WindowFramework > &active)
Rendering parameters for a panda3D simulation.
Implementation of a rotation vector as quaternion angle minimal representation.
const double & z() const
Returns the z-component of the quaternion.
const double & x() const
Returns the x-component of the quaternion.
const double & y() const
Returns the y-component of the quaternion.
const double & w() const
Returns the w-component of the quaternion.
Class that consider the case of a translation vector.