Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpSimulator.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 * Description:
31 * Simulator based on Coin3d.
32 */
38
39#include <visp3/core/vpConfig.h>
40
41#ifdef VISP_HAVE_COIN3D_AND_GUI
42
43#include <visp3/ar/vpSimulator.h>
44#include <visp3/core/vpDebug.h>
45#include <visp3/core/vpTime.h>
46
47#include <visp3/core/vpImage.h>
48
49#ifdef VISP_HAVE_MODULE_IO
50#include <visp3/io/vpImageIo.h>
51#endif
52
53/* Objets OIV. */
54#include <Inventor/nodes/SoCone.h> /* Objet cone. */
55#include <Inventor/nodes/SoCoordinate3.h> /* Liste de points. */
56#include <Inventor/nodes/SoCylinder.h> /* Objet cylindre. */
57#include <Inventor/nodes/SoIndexedFaceSet.h> /* Liste de face. */
58#include <Inventor/nodes/SoPointLight.h> /* Objet lumiere ponctuelle. */
59#include <Inventor/nodes/SoRotationXYZ.h> /* Transfo rotation simple. */
60#include <Inventor/nodes/SoScale.h> /* Trasnfo mise a l'echelle. */
61#include <Inventor/nodes/SoTranslation.h> /* Trasnfo translation. */
62
63#include <Inventor/actions/SoWriteAction.h>
64#include <Inventor/nodes/SoDirectionalLight.h> /* Objet lumiere directionnelle*/
65#include <Inventor/nodes/SoDrawStyle.h> /* Style de rendu. */
66#include <Inventor/nodes/SoEnvironment.h> /* Eclairage ambiant. */
67#include <Inventor/nodes/SoGroup.h> /* Groupement de noeuds (sans separation)*/
68#include <Inventor/nodes/SoMaterial.h> /* Matiere (couleur) des objets. */
69
71// Positions of all of the vertices:
72//
73static float pyramidVertexes[5][3] = { {0.33f, 0.33f, 0.f},
74 {-0.33f, 0.33f, 0.f},
75 {-0.33f, -0.33f, 0.f},
76 {0.33f, -0.33f, 0.f},
77
78 {0.f, 0.f, -1.0f} };
79
80static int32_t pyramidFaces[] = {
81 0,
82 1,
83 2,
84 3,
85 SO_END_FACE_INDEX, // top face
86
87 0,
88 1,
89 4,
90 SO_END_FACE_INDEX, // 4 faces about top
91 1,
92 2,
93 4,
94 SO_END_FACE_INDEX,
95 2,
96 3,
97 4,
98 SO_END_FACE_INDEX,
99 3,
100 0,
101 4,
102 SO_END_FACE_INDEX,
103};
104
105// Routine to create a scene graph representing a dodecahedron
106SoSeparator *makePyramide()
107{
108 SoSeparator *result = new SoSeparator;
109 result->ref();
110
111 // Define coordinates for vertices
112 SoCoordinate3 *myCoords = new SoCoordinate3;
113 myCoords->point.setValues(0, 5, pyramidVertexes);
114 result->addChild(myCoords);
115
116 // Define the IndexedFaceSet, with indices into the vertices:
117 SoIndexedFaceSet *myFaceSet = new SoIndexedFaceSet;
118 myFaceSet->coordIndex.setValues(0, 21, (const int32_t *)pyramidFaces);
119 result->addChild(myFaceSet);
120
121 result->unrefNoDelete();
122 return result;
123}
124
125/* Cree une fleche composee d'un cylindre et d'un cone.
126 * La fleche a une hauteur total de <longueur>, dont
127 * <proportionFleche>% pour la fleche. Le rayon du cylindre
128 * est <radius>, et celui de la fleche <radius> * 5.
129 * La fleche est oriente selon l'axe Y.
130 */
131static SoSeparator *createArrow(float longueur, float proportionFleche, float radius)
132{
133 SoSeparator *fleche = new SoSeparator;
134 fleche->ref();
135
136 SoTranslation *poseCylindre = new SoTranslation;
137 SoCylinder *line = new SoCylinder;
138 SoTranslation *posePointe = new SoTranslation;
139 SoCone *pointe = new SoCone;
140
141 float l_cylindre = longueur * (1 - proportionFleche);
142 float l_cone = longueur * proportionFleche;
143 float radius_cylindre = radius;
144 float radius_cone = radius * 5;
145
146 line->radius.setValue(radius_cylindre);
147 line->height.setValue(l_cylindre);
148
149 poseCylindre->translation.setValue(0, l_cylindre / 2, 0);
150 posePointe->translation.setValue(0.0, l_cylindre / 2 + l_cone / 2, 0);
151
152 pointe->bottomRadius.setValue(radius_cone);
153 pointe->height.setValue(l_cone);
154
155 fleche->addChild(poseCylindre);
156 fleche->addChild(line);
157 fleche->addChild(posePointe);
158 fleche->addChild(pointe);
159
160 return fleche;
161}
162
163/*
164 Cree un objet repere dans un noeud separator, et le renvoie.
165 \return : code d'erreur, SIMU_CODE_OK si tout s'est bien passe.
166*/
167#define LONGUEUR_FLECHE 1.0f
168#define RAYON_FLECHE 0.002f
169#define PROPORTION_FLECHE 0.1f
170
171SoSeparator *createFrame(float longueurFleche = LONGUEUR_FLECHE, float proportionFleche = PROPORTION_FLECHE,
172 float radiusFleche = RAYON_FLECHE)
173{
174 vpDEBUG_TRACE(15, "# Entree.");
175
176 SoSeparator *frame = new SoSeparator;
177 frame->ref();
178
179 SoRotationXYZ *rotationY_X = new SoRotationXYZ;
180 rotationY_X->axis = SoRotationXYZ::Z;
181 rotationY_X->angle.setValue(static_cast<float>(-M_PI / 2));
182
183 SoRotationXYZ *rotationX_Y = new SoRotationXYZ;
184 rotationX_Y->axis = SoRotationXYZ::Z;
185 rotationX_Y->angle.setValue(static_cast<float>(M_PI / 2));
186
187 SoRotationXYZ *rotationY_Z = new SoRotationXYZ;
188 rotationY_Z->axis = SoRotationXYZ::X;
189 rotationY_Z->angle.setValue(static_cast<float>(M_PI / 2));
190
191 SoMaterial *rouge = new SoMaterial;
192 rouge->diffuseColor.setValue(1.0, 0.0, 0.0);
193 rouge->emissiveColor.setValue(0.5, 0.0, 0.0);
194
195 SoMaterial *vert = new SoMaterial;
196 vert->diffuseColor.setValue(0.0, 1.0, 0.0);
197 vert->emissiveColor.setValue(0.0, 0.5, 0.0);
198
199 SoMaterial *bleu = new SoMaterial;
200 bleu->diffuseColor.setValue(0.0, 0.0, 1.0);
201 bleu->emissiveColor.setValue(0.0, 0.0, 0.5);
202
203 SoSeparator *fleche = createArrow(longueurFleche, proportionFleche, radiusFleche);
204
205 frame->addChild(rouge);
206 frame->addChild(rotationY_X);
207 frame->addChild(fleche);
208 frame->addChild(vert);
209 frame->addChild(rotationX_Y);
210 frame->addChild(fleche);
211 frame->addChild(bleu);
212 frame->addChild(rotationY_Z);
213 frame->addChild(fleche);
214
215 frame->unrefNoDelete();
216
217 vpDEBUG_TRACE(15, "# Sortie.");
218 return frame;
219}
220
221SoSeparator *createCameraObject(float zoomFactor = 1.0)
222{
223 vpDEBUG_TRACE(15, "# Entree.");
224
225 SoSeparator *cam = new SoSeparator;
226 cam->ref();
227
228 SoMaterial *myMaterial = new SoMaterial;
229 myMaterial->diffuseColor.setValue(1.0, 0.0, 0.0);
230 myMaterial->emissiveColor.setValue(0.5, 0.0, 0.0);
231
232 SoScale *taille = new SoScale;
233 {
234 float zoom = 0.1f * zoomFactor;
235 taille->scaleFactor.setValue(zoom, zoom, zoom);
236 }
237
238 SoMaterial *couleurBlanc = new SoMaterial;
239 couleurBlanc->diffuseColor.setValue(1.0, 1.0, 1.0);
240 couleurBlanc->emissiveColor.setValue(1.0, 1.0, 1.0);
241 SoDrawStyle *filDeFer = new SoDrawStyle;
242 filDeFer->style.setValue(SoDrawStyle::LINES);
243 filDeFer->lineWidth.setValue(1);
244
245 SoSeparator *cone = new SoSeparator;
246 cone->ref();
247 cone->addChild(makePyramide());
248 cone->addChild(couleurBlanc);
249 cone->addChild(filDeFer);
250 cone->addChild(makePyramide());
251 cone->unrefNoDelete();
252
253 cam->addChild(myMaterial);
254 cam->addChild(taille);
255 cam->addChild(cone);
256 cam->addChild(createFrame(2.0f, 0.1f, 0.01f));
257
258 // cam->unref() ;
259 vpDEBUG_TRACE(15, "# Sortie.");
260 return cam;
261}
262
263//--------------------------------------------------------------
265{
266 internal_width = 200;
267 internal_height = 200;
268 external_width = 200;
269 external_height = 200;
270
271 mainWindowInitialized = false;
272 internalView = nullptr;
273 externalView = nullptr;
274 image_background = nullptr;
275
276 zoomFactor = 1;
278
279 // write image process
280 realtime = nullptr;
281 offScreenRenderer = nullptr;
282 bufferView = nullptr;
283 get = 1;
285 mainThread = nullptr;
286 scene = nullptr;
287 internalRoot = nullptr;
288 externalRoot = nullptr;
289 internalCamera = nullptr;
290 externalCamera = nullptr;
291 internalCameraPosition = nullptr;
292 extrenalCameraPosition = nullptr;
293 internalCameraObject = nullptr;
294#if defined(VISP_HAVE_SOWIN)
295// mainWindow = ?;
296#elif defined(VISP_HAVE_SOQT)
297 mainWindow = nullptr;
298#elif defined(VISP_HAVE_SOXT)
299// mainWindow = ?;
300#endif
301}
303{
304 if (internalView != nullptr) {
305 delete internalView;
306 internalView = nullptr;
307 }
308 if (externalView != nullptr) {
309 delete externalView;
310 externalView = nullptr;
311 }
312 if (bufferView != nullptr) {
313 delete[] bufferView;
314 bufferView = nullptr;
315 }
316 if (image_background != nullptr) {
317 free(image_background);
318 image_background = nullptr;
319 }
320}
321
323 :
324#if defined(VISP_HAVE_SOWIN)
325 mainWindow(),
326#elif defined(VISP_HAVE_SOQT)
327 mainWindow(nullptr),
328#elif defined(VISP_HAVE_SOXT)
329 mainWindow(),
330#endif
333 scene(nullptr), internalRoot(nullptr), externalRoot(nullptr), internalCamera(nullptr), externalCamera(nullptr),
336 offScreenRenderer(nullptr), bufferView(nullptr), get(0)
337{
339}
340
342
344{
345 mainWindow = vpViewer::init("");
347}
348
350{
351 this->scene = new SoSeparator;
352 this->internalRoot = new SoSeparator;
353 this->externalRoot = new SoSeparator;
354
355 this->scene->ref();
356 this->internalRoot->ref();
357 this->externalRoot->ref();
358
359 // define the camera SoPerspectiveCamera
360 this->internalCamera = new SoPerspectiveCamera;
361 this->externalCamera = new SoPerspectiveCamera;
362
363 this->internalCameraPosition = new SoTransform;
364 this->internalCameraObject = createCameraObject(zoomFactor);
365
366 internalCamera->farDistance.setValue(100);
367 internalCamera->nearDistance.setValue(0.0001f);
368
369 // link between camera and internal root
370 this->internalRoot->addChild(this->internalCamera);
371 this->internalRoot->addChild(this->scene);
372
373 this->externalRoot->addChild(this->externalCamera);
374 this->externalRoot->addChild(this->scene);
375
376 SoSeparator *camera = new SoSeparator;
377 camera->ref();
378 camera->addChild(this->internalCameraPosition);
379 camera->addChild(this->internalCameraObject);
380 this->externalRoot->addChild(camera);
381
382 // this->externalRoot->addChild (internalCameraPosition);
383 // this->externalRoot->addChild (internalCameraObject);
384 SoCube *cube = new SoCube;
385 cube->width = 0.01f;
386 cube->depth = 0.01f;
387 cube->height = 0.01f;
388
389 this->externalRoot->addChild(cube);
390
391 if (realtime == nullptr) {
392
393 SoDB::enableRealTimeSensor(FALSE);
394 SoSceneManager::enableRealTimeUpdate(FALSE);
395 realtime = (SbTime *)SoDB::getGlobalField("realTime");
396 realtime->setValue(0.0);
397 }
398}
399
407{
408 zoomFactor = zoom;
409 static bool firstTime = true;
410 if (firstTime) {
411 SoScale *taille = new SoScale;
412 taille->scaleFactor.setValue(zoomFactor, zoomFactor, zoomFactor);
413 this->scene->addChild(taille);
414 firstTime = false;
415 }
416 else {
417 SoScale *taille = (SoScale *)this->scene->getChild(0);
418 taille->scaleFactor.setValue(zoomFactor, zoomFactor, zoomFactor);
419 }
420}
421
441{
442 SoScale *taille = (SoScale *)this->scene->getChild(index);
443 taille->scaleFactor.setValue(zoomFactor, zoomFactor, zoomFactor);
444 // this->setZoomFactor(zoomFactor);
445}
446
447void vpSimulator::initInternalViewer(unsigned int width, unsigned int height)
448{
449 internal_width = width;
450 internal_height = height;
451
452 if (mainWindowInitialized == false) {
455 }
456
458
459 // set the scene to render from this view
460 internalView->setSceneGraph(internalRoot);
461
462 // set the title
463 internalView->setTitle("Internal camera view");
464
465 // If the view mode is on, user events will be caught and used to influence
466 // the camera position / orientation. in this viewer we do not want that,
467 // we set it to false
468 internalView->setViewing(false);
469
470 // Turn the viewer decorations
471 internalView->setDecoration(false);
472
473 internalView->resize(static_cast<int>(width), static_cast<int>(height), true);
474
475 // open the window
476 internalView->show();
477
478 bufferView = new unsigned char[3 * width * height];
479}
480
481void vpSimulator::initExternalViewer(unsigned int width, unsigned int height)
482{
483
484 external_width = width;
485 external_height = height;
486
487 if (mainWindowInitialized == false) {
490 }
491
493
494 // set the scene to render this view
495 externalView->setSceneGraph(externalRoot);
496
497 // set the title
498 externalView->setTitle("External View");
499 externalView->resize(static_cast<int>(width), static_cast<int>(height), false);
500 // the goal here is to see all the scene and not to determine
501 // a manual viewpoint
502 externalView->viewAll();
503
504 // open the window
505 externalView->show();
506}
507
509{
511
512 float px = static_cast<float>(_cam.get_px());
513 float py = static_cast<float>(_cam.get_py());
514 float v = internal_height / (2.f * py);
515
516 internalCamera->ref();
517 internalCamera->heightAngle = 2 * atan(v);
518 internalCamera->aspectRatio = (internal_width / internal_height) * (px / py);
519 internalCamera->nearDistance = 0.001f;
520
521 internalCamera->farDistance = 1000;
522 internalCamera->unrefNoDelete();
523}
524
526{
527 // SoPerspectiveCamera *camera ;
528 // camera = (SoPerspectiveCamera *)this->externalView->getCamera() ;
530
531 float px = static_cast<float>(_cam.get_px());
532 float py = static_cast<float>(_cam.get_py());
533 float v = external_height / (2 * py);
534
535 externalCamera->ref();
536 externalCamera->heightAngle = 2 * atan(v);
537 externalCamera->aspectRatio = (external_width / external_height) * (px / py);
538 externalCamera->nearDistance = 0.001f;
539 externalCamera->farDistance = 1000;
540 externalCamera->unrefNoDelete();
541}
542
544{
545 /* SoCamera *camera ;
546 camera = this->externalView->getCamera() ;*/
547 SoSFVec3f position = externalCamera->position;
548
549 // get the rotation
550 SoSFRotation orientation = externalCamera->orientation;
551 SbVec3f axis;
552 float angle;
553 orientation.getValue(axis, angle);
554 SbRotation rotation(axis, angle);
555
556 // get the translation
557 SbVec3f t;
558 t = position.getValue();
559
560 SbMatrix matrix;
561 matrix.setRotate(rotation);
562
564 SbMatrix rotX;
565 rotX.setRotate(SbRotation(SbVec3f(1.0f, 0.0f, 0.0f), static_cast<float>(M_PI)));
566 matrix.multLeft(rotX);
567 for (unsigned int i = 0; i < 4; i++) {
568 for (unsigned int j = 0; j < 4; j++) {
569 fMc[j][i] = matrix[static_cast<int>(i)][static_cast<int>(j)];
570 }
571 }
572 fMc[0][3] = t[0];
573 fMc[1][3] = t[1];
574 fMc[2][3] = t[2];
575
576 cMf = fMc.inverse();
577}
578
585{
586
587 SbMatrix matrix;
588 SbRotation rotCam;
589 SbMatrix rotX;
590 rotX.setRotate(SbRotation(SbVec3f(1.0f, 0.0f, 0.0f), static_cast<float>(M_PI)));
591 for (unsigned int i = 0; i < 4; i++)
592 for (unsigned int j = 0; j < 4; j++)
593 matrix[static_cast<int>(j)][static_cast<int>(i)] = static_cast<float>(cMf[i][j]);
594
595 matrix = matrix.inverse();
596 matrix.multLeft(rotX);
597 rotCam.setValue(matrix);
598
599 internalCamera->ref();
600 internalCamera->orientation.setValue(rotCam);
601 internalCamera->position.setValue(matrix[3][0], matrix[3][1], matrix[3][2]);
602 internalCamera->unref();
603
604 rotX.setRotate(SbRotation(SbVec3f(-1.0f, 0.0f, 0.0f), static_cast<float>(M_PI)));
605 matrix.multLeft(rotX);
606 rotCam.setValue(matrix);
608 internalCameraPosition->rotation.setValue(rotCam);
609 internalCameraPosition->translation.setValue(matrix[3][0], matrix[3][1], matrix[3][2]);
610 internalCameraPosition->unref();
611}
612
617{
618
619 // if (this->cameraPositionInitialized==true)
620 {
621 if (this->externalView != nullptr) {
622 this->externalView->render(); // call actualRedraw()
623 // vpHomogeneousMatrix c ;
624 // getExternalCameraPosition(c) ;
625 }
626 if (this->internalView != nullptr) {
627 this->moveInternalCamera(this->cMf);
628 this->internalView->render(); // call actualRedraw()
629 }
630 }
631}
632
633// This function is called 20 times each second.
634static void timerSensorCallback(void *data, SoSensor *)
635{
636 vpSimulator *simulator = (vpSimulator *)data;
637
638 simulator->redraw();
639}
640
642{
643 if (mainWindowInitialized == false) {
644 vpERROR_TRACE("main window is not opened ");
645 }
646
647 vpTime::wait(1000);
648
649 // Timer sensor
650 SoTimerSensor *timer = new SoTimerSensor(timerSensorCallback, (void *)this);
651 timer->setInterval(0.01);
652 timer->schedule();
653 vpViewer::mainLoop();
654}
655
656//-----------------------------------------------------------------
657// scene stuff
658//-----------------------------------------------------------------
659
661void vpSimulator::load(const char *file_name)
662{
663
664 SoInput input;
665 if (!input.openFile(file_name)) {
666 vpERROR_TRACE("Erreur cannot open file %s", file_name);
667 }
668
669 SoSeparator *newscene = SoDB::readAll(&input);
670 newscene->ref();
671 if (newscene == nullptr) {
672 vpERROR_TRACE("Error while reading %s", file_name);
673 }
674
675 SoScale *taille = new SoScale;
676 taille->scaleFactor.setValue(zoomFactor, zoomFactor, zoomFactor);
677
678 // newscene->addChild(taille);
679
680 // std::cout << "this->scene->getNumChildren() = " <<
681 // this->scene->getNumChildren() << std::endl;
682
683 this->scene->addChild(taille);
684 this->scene->addChild(newscene);
685 newscene->unref();
686}
687
688void vpSimulator::save(const char *name, bool binary)
689{
690 // get a pointer to the object "name"
691 SoOutput output;
692 output.openFile(name);
693
694 if (binary == true)
695 output.setBinary(TRUE);
696
697 SoWriteAction writeAction(&output);
698 writeAction.apply(scene);
699 output.closeFile();
700}
701
707void vpSimulator::addFrame(const vpHomogeneousMatrix &fMo, float zoom)
708{
709
710 SoScale *taille = new SoScale;
711 taille->scaleFactor.setValue(zoom, zoom, zoom);
712
713 SoSeparator *frame = new SoSeparator;
714 frame->ref();
715 frame->addChild(taille);
716 frame->addChild(createFrame(LONGUEUR_FLECHE * zoom, PROPORTION_FLECHE * zoom, RAYON_FLECHE * zoom));
717 this->addObject(frame, fMo, externalRoot);
718 // frame->unref();
719}
720
727{
728 scene->addChild(createFrame(LONGUEUR_FLECHE * zoom, PROPORTION_FLECHE * zoom, RAYON_FLECHE * zoom));
729}
730
736void vpSimulator::load(const char *iv_filename, const vpHomogeneousMatrix &fMo)
737{
738
739 SoInput in;
740 SoSeparator *newObject;
741
742 if (!in.openFile(iv_filename)) {
743 vpERROR_TRACE("Erreur lors de la lecture du fichier %s.", iv_filename);
744 }
745
746 newObject = SoDB::readAll(&in);
747 if (nullptr == newObject) {
748 vpERROR_TRACE("Problem reading data for file <%s>.", iv_filename);
749 }
750
751 try {
752 this->addObject(newObject, fMo);
753 }
754 catch (...) {
755 vpERROR_TRACE("Error adding object from file <%s> ", iv_filename);
756 throw;
757 }
758}
759
765void vpSimulator::addObject(SoSeparator *newObject, const vpHomogeneousMatrix &fMo)
766{
767 try {
768 this->addObject(newObject, fMo, scene);
769 }
770 catch (...) {
771 vpERROR_TRACE("Error adding object in scene graph ");
772 throw;
773 }
774}
775
782
783void vpSimulator::addObject(SoSeparator *object, const vpHomogeneousMatrix &fMo, SoSeparator *root)
784{
785
786 bool identity = true;
787 for (unsigned int i = 0; i < 4; i++) {
788 for (unsigned int j = 0; j < 4; j++) {
789 if (i == j) {
790 if (fabs(fMo[i][j] - 1) > 1e-6)
791 identity = false;
792 }
793 else {
794 if (fabs(fMo[i][j]) > 1e-6)
795 identity = false;
796 }
797 }
798 }
799
800 if (identity == true) {
801 root->addChild(object);
802 }
803 else {
804 SbMatrix matrix;
805 SbRotation rotation;
806 for (unsigned int i = 0; i < 4; i++)
807 for (unsigned int j = 0; j < 4; j++)
808 matrix[static_cast<int>(j)][static_cast<int>(i)] = static_cast<float>(fMo[i][j]);
809
810 // matrix= matrix.inverse();
811 rotation.setValue(matrix);
812
813 SoTransform *displacement = new SoTransform;
814 SoSeparator *newNode = new SoSeparator;
815
816 displacement->rotation.setValue(rotation);
817 displacement->translation.setValue(matrix[3][0], matrix[3][1], matrix[3][2]);
818
819 root->addChild(newNode);
820 newNode->addChild(displacement);
821 newNode->addChild(object);
822 }
823}
824
826void vpSimulator::initApplication(void *(*start_routine)(void *))
827{
828 // pthread_create (&mainThread, nullptr, start_routine, (void *)this);
829 mainThread = SbThread::create(start_routine, (void *)this);
830}
831
841void vpSimulator::initApplication(void *(*start_routine)(void *), void *data)
842{
843 mainThread = SbThread::create(start_routine, (void *)data);
844}
845
849{
850 // pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, nullptr );
851 // pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, nullptr);
852 vpTime::wait(1000);
853}
854
857{
858 vpViewer::exitMainLoop();
859 // pthread_exit (nullptr);
860}
861
862/* Initialise le SoOffScreenRenderer si necessaire, puis realise le rendu.
863 * Quand la fonction rend la main, le buffer est pret et n'a plus qu'a etre
864 * enregistre ou passe a l'utilisateur.
865 * INPUT:
866 * - vueInterne est vrai ssi il faut rendre la vue interne, faux ssi
867 * il faut rendre la vue externe.
868 * OUTPUT:
869 * - width : largeur de l'image dans le buffer.
870 * - height : hauteur de l'image dans le buffer.
871 */
872void vpSimulator::offScreenRendering(vpSimulatorViewType view, int *width, int *height)
873{
874
875 SbVec2s size(320, 200);
876 SoNode *thisroot;
877
878 {
879 if (view == vpSimulator::INTERNAL) {
880 size = this->internalView->getViewportRegion().getWindowSize();
881 thisroot = this->internalView->getSceneManager()->getSceneGraph();
882 }
883 else {
884 size = this->externalView->getViewportRegion().getWindowSize();
885 thisroot = this->externalView->getSceneManager()->getSceneGraph();
886 }
887 }
888 SbViewportRegion myViewPort(size);
889
890 // Creation du rendu si necessaire.
891 if (nullptr == this->offScreenRenderer) {
892 // Init du SoOffscreenRenderer
893 this->offScreenRenderer = new SoOffscreenRenderer(myViewPort);
894 }
895 else {
896 // Redefini le view port
897 this->offScreenRenderer->setViewportRegion(myViewPort);
898 }
899
900 // Rendu offscreen
901 if (!this->offScreenRenderer->render(thisroot)) {
902 vpERROR_TRACE("La scene n'a pas pu etre rendue offscreen.");
903 delete this->offScreenRenderer;
904 this->offScreenRenderer = nullptr;
905 }
906 else {
907
908 /*
909 if (view==vpSimulator::INTERNAL)
910 {
911 //Recopie du buffer contenant l'image, dans bufferView
912 int length = 3*size [0]*size[1];
913 delete [] bufferView;
914 bufferView = new unsigned char [length];
915 for(int i=0; i<length; i++)
916 {
917 bufferView[i] = this ->offScreenRenderer->getBuffer()[i];
918 }
919 }*/
920 }
921
922 // exit(1) ;
923 if (nullptr != width) {
924 *width = size[0];
925 }
926 if (nullptr != height) {
927 *height = size[1];
928 }
929}
930
931/* Enregistre l'image de vue interne ou externe dans un fichier RGB.
932 * Effectue le rendu dans un buffer plutot qu'a l'ecran, puis sauvegarde
933 * ce buffer au format PS (copie directe).
934 * INPUT
935 * - fileName: nom du fichier dans lequel placer le resultat.
936 * OUTPUT
937 * - RETURN : Code d'erreur CODE_OK si tout s'est bien passe.
938 */
939
940#ifdef VISP_HAVE_MODULE_IO
941void vpSimulator::write(const char *fileName)
942{
943
944 while (get == 0) {
945 vpTRACE("%d ", get);
946 }
947 get = 2;
948 /* FILE *fp = fopen(fileName, "w");
949 fprintf(fp,"P6 \n %d %d \n 255",internal_width,internal_height) ;
950 fwrite(bufferView, sizeof(unsigned char),
951 internal_width*internal_height*3, fp) ;*/
953
954 for (unsigned int i = 0; i < internal_height; i++)
955 for (unsigned int j = 0; j < internal_width; j++) {
956 unsigned char r, g, b;
957 unsigned int index = 3 * ((internal_height - i - 1) * internal_width + j);
958 r = *(bufferView + index);
959 g = *(bufferView + index + 1);
960 b = *(bufferView + index + 2);
961 I[i][j].R = r;
962 I[i][j].G = g;
963 I[i][j].B = b;
964 }
965 vpImageIo::write(I, fileName);
966 // fclose (fp);
967 get = 1;
968}
969#endif
970
971void vpSimulator::getSizeInternalView(int &width, int &height)
972{
973 SbVec2s size = this->internalView->getViewportRegion().getWindowSize();
974 width = size[0];
975 height = size[1];
976}
977
982
984{
985 // while (get==0) {;}
986 get = 2;
988 vpImageConvert::RGBToRGBa(bufferView, (unsigned char *)I.bitmap, internal_width, internal_height, true);
989 get = 1;
990}
991
997{
998 // while (get==0) {;}
999 get = 2;
1002 get = 1;
1003}
1004END_VISP_NAMESPACE
1005#elif !defined(VISP_BUILD_SHARED_LIBS)
1006// Work around to avoid warning: libvisp_ar.a(vpSimulator.cpp.o) has no symbols
1007void dummy_vpSimulator() { }
1008#endif
Generic class defining intrinsic camera parameters.
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition of the vpImage class member functions.
Definition vpImage.h:131
Implementation of a simulator based on Coin3d (www.coin3d.org).
Definition vpSimulator.h:95
SoPerspectiveCamera * internalCamera
internal camera
void save(const char *name, bool binary=false)
save the scene in an iv file
unsigned int internal_height
GLubyte * image_background
vpCameraParameters internalCameraParameters
internal camera parameters
void load(const char *file_name)
load an iv file
unsigned char * bufferView
image of the internal view
SoTransform * extrenalCameraPosition
external camera position
void addFrame(const vpHomogeneousMatrix &fMo, float zoom=1)
Add the representation of a frame.
void setInternalCameraParameters(vpCameraParameters &cam)
set internal camera parameters
void changeZoomFactor(float zoom, int index)
Change the zoom factor associated to the child given by index. In order to create multiple zoom facto...
void kill()
perform some destruction
float zoomFactor
virtual void mainLoop()
activate the mainloop
unsigned int external_height
void setExternalCameraParameters(vpCameraParameters &cam)
set external camera parameters
unsigned int internal_width
void getInternalImage(vpImage< unsigned char > &I)
get an Image of the internal view
void initMainApplication()
perform some initialization in the main program thread
bool cameraPositionInitialized
void getSizeInternalView(int &width, int &height)
get the size of the internal view
void moveInternalCamera(vpHomogeneousMatrix &cMf)
modify the position of the camera in the scene graph
void initSoApplication()
open the SoGui application
vpImageType typeImage
void getExternalCameraPosition(vpHomogeneousMatrix &cMf)
get the external camera position
void redraw()
display the scene (handle with care)
void initApplication(void *(*start_routine)(void *))
begin the main program
vpViewer * internalView
view from the camera
void init()
perform some initialization
vpHomogeneousMatrix cMf
internal camera position
SoSeparator * internalCameraObject
representation of the camera in the external view
SoSeparator * scene
SbThread * mainThread
thread with the main program
vpViewer * externalView
view from an external camera
void setZoomFactor(float zoom)
set the size of the camera/frame
SoPerspectiveCamera * externalCamera
external camera
void setCameraPosition(vpHomogeneousMatrix &cMf)
set the camera position (from an homogeneous matrix)
HWND mainWindow
main Widget
void offScreenRendering(vpSimulatorViewType view=vpSimulator::EXTERNAL, int *width=nullptr, int *height=nullptr)
void initExternalViewer(unsigned int nlig, unsigned int ncol)
initialize the external view
SoSeparator * externalRoot
root node of the external view
void write(const char *fileName)
virtual ~vpSimulator()
virtual void initInternalViewer(unsigned int nlig, unsigned int ncol)
initialize the camera view
bool mainWindowInitialized
void addObject(SoSeparator *object, const vpHomogeneousMatrix &fMo, SoSeparator *root)
Add a new object in the scene graph ad a given location.
vpCameraParameters externalCameraParameters
internal camera parameters
vpSimulator()
constructor
void initSceneGraph()
initialize the scene graph
SoOffscreenRenderer * offScreenRenderer
SoTransform * internalCameraPosition
internal camera position
SoSeparator * internalRoot
root node of the internal view
void closeMainApplication()
SbTime * realtime
void addAbsoluteFrame(float zoom=1)
Add the representation of the absolute frame.
unsigned int external_width
Viewer used by the simulator.
Definition vpViewer.h:120
@ externalView
Definition vpViewer.h:125
@ internalView
Definition vpViewer.h:125
#define vpTRACE
Definition vpDebug.h:450
#define vpDEBUG_TRACE
Definition vpDebug.h:526
#define vpERROR_TRACE
Definition vpDebug.h:423
VISP_EXPORT int wait(double t0, double t)