ATLAS Offline Software
Loading...
Searching...
No Matches
VP1QtInventorUtils.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5
7// //
8// Implementation of class VP1QtInventorUtils //
9// //
10// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> //
11// //
12// Initial version: June 2007 //
13// //
15
18#include "VP1Base/VP1Msg.h"
19#include "CxxUtils/byteswap.h"
20
21#include "Inventor/nodes/SoMaterial.h"
22#include <Inventor/nodes/SoPerspectiveCamera.h>
23#include <Inventor/nodes/SoOrthographicCamera.h>
24#include <Inventor/nodes/SoGroup.h>
25#include <Inventor/nodes/SoNurbsCurve.h>
26#include <Inventor/nodes/SoCoordinate4.h>
27
28#include <Inventor/SoPath.h>
29#include <Inventor/SoOffscreenRenderer.h>
30#include "Inventor/Qt/SoQtRenderArea.h"
31#include <Inventor/actions/SoSearchAction.h>
32#include <Inventor/SoDB.h>
33#include <Inventor/actions/SoWriteAction.h>
34
35#include <Inventor/nodes/SoLineSet.h>
36#include <Inventor/nodes/SoVertexProperty.h>
37
38
39#include <Inventor/VRMLnodes/SoVRMLGroup.h>
40#include <Inventor/actions/SoToVRML2Action.h>
41
42#include <QDir>
43#include <QTime>
44#include <QBuffer>
45#include <QTextStream>
46#include <QSlider>
47#include <QGLFormat>
48#include <QtCoreVersion>
49
50#include <iostream>
51#include <bit>
52namespace{
53 unsigned char *
54 ucharAddress(auto * pv){
55 return reinterpret_cast<unsigned char *>(pv);
56 }
57}
58
59//____________________________________________________________________
61public:
62
63 static QImage constructImageWithTransparentBackground(const QImage& im_black_bgd, const QImage& image_white_bgd);
64
65 static void bwtorgba(unsigned char *b,unsigned char *l,int n)
66 {
67 while (n--) {
68 l[0] = *b;
69 l[1] = *b;
70 l[2] = *b;
71 l[3] = 0xff;
72 l += 4; ++b;
73 }
74 }
75
76 static void latorgba(unsigned char *b, unsigned char *a,unsigned char *l,int n)
77 {
78 while (n--) {
79 l[0] = *b;
80 l[1] = *b;
81 l[2] = *b;
82 l[3] = *a;
83 l += 4; ++b; ++a;
84 }
85 }
86
87 static void rgbtorgba(unsigned char *r,unsigned char *g,
88 unsigned char *b,unsigned char *l,int n)
89 {
90 while (n--) {
91 l[0] = r[0];
92 l[1] = g[0];
93 l[2] = b[0];
94 l[3] = 0xff;
95 l += 4; ++r; ++g; ++b;
96 }
97 }
98
99 static void rgbatorgba(unsigned char *r,unsigned char *g,
100 unsigned char *b,unsigned char *a,unsigned char *l,int n)
101 {
102 while (n--) {
103 l[0] = r[0];
104 l[1] = g[0];
105 l[2] = b[0];
106 l[3] = a[0];
107 l += 4; ++r; ++g; ++b; ++a;
108 }
109 }
110
111 typedef struct _ImageRec {
112 unsigned short imagic;
113 unsigned short type;
114 unsigned short dim;
115 unsigned short xsize, ysize, zsize;
116 unsigned int min, max;
117 unsigned int wasteBytes;
118 char name[80];
119 unsigned long colorMap;
120 FILE *file;
121 unsigned char *tmp, *tmpR, *tmpG, *tmpB;
122 unsigned long rleEnd;
123 unsigned int *rowStart;
126
127 static void ConvertLong(unsigned *array, long length)
128 {
129 while (length--) {
130 *array = CxxUtils::byteswap (*array);
131 ++array;
132 }
133 }
134
135 static ImageRec *ImageOpen(const char *fileName)
136 {
137
138 ImageRec *image;
139 const bool swapFlag = std::endian::native == std::endian::little;
140 image = (ImageRec *)malloc(sizeof(ImageRec));
141 if (!image) {
142 fprintf(stderr, "Out of memory!\n");
143 exit(1);
144 }
145 if (!(image->file = fopen(fileName, "rb"))) {
146 perror(fileName);
147 free(image);
148 exit(1);
149 }
150
151 int bytesRead = fread(image, 1, 12, image->file);
152
153 if (bytesRead != 12) {
154 fprintf(stderr, "fread failed!\n");
155 fclose(image->file);
156 free(image);
157 return nullptr;
158 }
159 //what are reasonable limits on x,y,zsize?
160
161
162
163
164 if (swapFlag) {
165 image->imagic = CxxUtils::byteswap (image->imagic);
166 image->type = CxxUtils::byteswap (image->type);
167 image->dim = CxxUtils::byteswap (image->dim);
168 image->xsize = CxxUtils::byteswap (image->xsize);
169 image->ysize = CxxUtils::byteswap (image->ysize);
170 image->zsize = CxxUtils::byteswap (image->zsize);
171 }
172
173
174 const unsigned int colourBuffSize=image->xsize*256u;
175 image->tmp = ucharAddress(malloc(colourBuffSize));
176 image->tmpR = ucharAddress(malloc(colourBuffSize));
177 image->tmpG = ucharAddress(malloc(colourBuffSize));
178 image->tmpB = ucharAddress(malloc(colourBuffSize));
179 if (image->tmp == NULL || image->tmpR == NULL || image->tmpG == NULL ||
180 image->tmpB == NULL) {
181 fprintf(stderr, "Out of memory!\n");
182 exit(1);
183 }
184
185 //should test upper limits on x here...but what is sensible? 1Mb? 100Mb?
186 if ((image->type & 0xFF00) == 0x0100) {
187 size_t x = ((size_t)image->ysize * (size_t)image->zsize) * sizeof(unsigned);
188 //cid 13609 complaining there is no input sanitising
189 //coverity[TAINTED_SCALAR]
190 image->rowStart = (unsigned *)malloc(x);
191 image->rowSize = (int *)malloc(x);
192 if (image->rowStart == NULL || image->rowSize == NULL) {
193 fprintf(stderr, "Out of memory!\n");
194 exit(1);
195 }
196 image->rleEnd = 512 + (2 * x);
197 const int fseekRetVal= fseek(image->file, 512, SEEK_SET);
198 if (fseekRetVal !=0){
199 fprintf(stderr, "Something very wrong with fseek near line 205 of VP1QtInventorUtils.cxx");
200 }
201 size_t bytesRead = 0;
202 bytesRead = fread(image->rowStart, 1, x, image->file);
203 VP1Msg::messageDebug("bytesRead(rowStart): " + QString::number(bytesRead));
204 bytesRead = fread(image->rowSize, 1, x, image->file);
205 VP1Msg::messageDebug("bytesRead(rowSize): " + QString::number(bytesRead));
206
207 if (swapFlag) {
208 ConvertLong(image->rowStart, x/(int)sizeof(unsigned));
209 ConvertLong((unsigned *)image->rowSize, x/(int)sizeof(int));
210 }
211 } else {
212 image->rowStart = NULL;
213 image->rowSize = NULL;
214 }
215 return image;
216 }
217
218 static void ImageClose(ImageRec *image)
219 {
220 fclose(image->file);
221 free(image->tmp);
222 free(image->tmpR);
223 free(image->tmpG);
224 free(image->tmpB);
225 free(image->rowSize);
226 free(image->rowStart);
227 free(image);
228 }
229
230 static void ImageGetRow(ImageRec *image,
231 unsigned char *buf, int y, int z)
232 {
233 unsigned char *iPtr, *oPtr, pixel;
234 int count;
235
236 if (image) {
237 if ((image->type & 0xFF00) == 0x0100) {
238
239 int okseek = fseek(image->file, (long)image->rowStart[y+z*image->ysize], SEEK_SET);
240 int okread = fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize],
241 image->file);
242
243 if (okseek != 0 || okread == 0) VP1Msg::messageDebug("fseek or fread failed!!");
244
245 iPtr = image->tmp;
246 oPtr = buf;
247 for (;;) {
248 pixel = *iPtr++;
249 count = (int)(pixel & 0x7F);
250 if (!count) {
251 return;
252 }
253 if (pixel & 0x80) {
254 while (count--) {
255 *oPtr++ = *iPtr++;
256 }
257 } else {
258 pixel = *iPtr++;
259 while (count--) {
260 *oPtr++ = pixel;
261 }
262 }
263 }
264 } else {
265 const unsigned int yDim(y*image->xsize), zDim(z*image->xsize*image->ysize);
266 int okstatus = fseek(image->file, 512u+yDim+zDim, SEEK_SET);
267 if (okstatus) { VP1Msg::messageDebug("fseek failed!!"); }
268
269 size_t bytesRead = 0;
270 bytesRead = fread(buf, 1, image->xsize, image->file);
271 VP1Msg::messageDebug("bytesRead(buf): " + QString::number(bytesRead));
272
273 }
274 }
275 else {
276 std::cout << "Warning! ImageGetRow() - no 'image'..." << std::endl;
277 }
278 }
279
280 static unsigned *read_texture(const char *name, int *width, int *height, int *components)
281 {
282 unsigned *base, *lptr;
283 unsigned char *rbuf, *gbuf, *bbuf, *abuf;
284 ImageRec *image;
285 int y;
286
287 image = ImageOpen(name);
288
289 if(!image)
290 return nullptr;
291
292 (*width)=image->xsize;
293 (*height)=image->ysize;
294 (*components)=image->zsize;
295 const unsigned int imageWidth = image->xsize;
296 const unsigned int imageHeight = image->ysize;
297 const unsigned int uintSize(sizeof(unsigned)), ucharSize(sizeof(unsigned char));
298 const unsigned int colourBufSize=imageWidth*ucharSize;
299 base = reinterpret_cast<unsigned *>(malloc(imageWidth*imageHeight*uintSize));
300 rbuf = ucharAddress(malloc(colourBufSize));
301 gbuf = ucharAddress(malloc(colourBufSize));
302 bbuf = ucharAddress(malloc(colourBufSize));
303 abuf = ucharAddress(malloc(colourBufSize));
304 if(!base || !rbuf || !gbuf || !bbuf) {
305 ImageClose(image);
306 if (base) free(base);
307 if (rbuf) free(rbuf);
308 if (gbuf) free(gbuf);
309 if (bbuf) free(bbuf);
310 if (abuf) free(abuf);
311 return NULL;
312 }
313 lptr = base;
314 for (y=0; y<image->ysize; ++y) {
315 if (image->zsize>=4) {
316 //cid 13919 complaining that there was no input sanitising
317 //coverity[TAINTED_SCALAR]
318 ImageGetRow(image,rbuf,y,0);
319 ImageGetRow(image,gbuf,y,1);
320 ImageGetRow(image,bbuf,y,2);
321 ImageGetRow(image,abuf,y,3);
322 rgbatorgba(rbuf,gbuf,bbuf,abuf,ucharAddress(lptr),image->xsize);
323 lptr += image->xsize;
324 } else if(image->zsize==3) {
325 ImageGetRow(image,rbuf,y,0);
326 ImageGetRow(image,gbuf,y,1);
327 ImageGetRow(image,bbuf,y,2);
328 rgbtorgba(rbuf,gbuf,bbuf,ucharAddress(lptr),image->xsize);
329 lptr += image->xsize;
330 } else if(image->zsize==2) {
331 ImageGetRow(image,rbuf,y,0);
332 ImageGetRow(image,abuf,y,1);
333 latorgba(rbuf,abuf,ucharAddress(lptr),image->xsize);
334 lptr += image->xsize;
335 } else {
336 ImageGetRow(image,rbuf,y,0);
337 bwtorgba(rbuf,ucharAddress(lptr),image->xsize);
338 lptr += image->xsize;
339 }
340 }
341 ImageClose(image);
342 free(rbuf);
343 free(gbuf);
344 free(bbuf);
345 free(abuf);
346
347 return (unsigned *) base;
348 }
349
350 //read/write scenegraphs:
351 static char * buffer;
352 static size_t buffer_size;
353 static void * buffer_realloc(void * bufptr, size_t size);
354 static QString buffer_writeaction(SoNode * root);
355 static void buffer_vrmlwriteaction(SoNode * root, const QString& filename);
356
358 static double allowedLineWidthMin;
359 static double allowedLineWidthMax;
361 static double allowedPointSizeMin;
362 static double allowedPointSizeMax;
364
365 //Prerender callback:
366 // static void prerendercallback_rendertoimage( void * userdata, class SoGLRenderAction * action );
367
368};
369
377
378//____________________________________________________________________
382
383//____________________________________________________________________
387
388//____________________________________________________________________
389QPixmap VP1QtInventorUtils::pixmapFromRGBFile(const QString& filename)
390{
391 return QPixmap::fromImage(imageFromRGBFile(filename));
392
393}
394
395//____________________________________________________________________
396QImage VP1QtInventorUtils::imageFromRGBFile(const QString& filename)
397{
398 int width = 0;
399 int height = 0;
400 int components = 0;
401 //more realistically, limits are probably 4'096
402 constexpr int maxheight(10'000);
403 constexpr int maxwidth(10'000);
404 auto inbounds = [](int w, int h)->bool{
405 return (w>0 and w<maxwidth) and (h>0 and h<maxheight);
406 };
407 unsigned * imagedata = Imp::read_texture(filename.toStdString().c_str(), &width, &height, &components);
408 if( not inbounds(width, height)){
409 std::cout << "VP1QtInventorUtils::imageFromRGBFile - read_texture failed?" << std::endl;
410 width = std::clamp(width, 0, maxwidth);
411 height = std::clamp(height, 0, maxheight);
412 }
413 unsigned char * data = reinterpret_cast<unsigned char*>(imagedata);
414
415 QImage im(width,height, ( components <= 3 ? QImage::Format_RGB32 : QImage::Format_ARGB32 ) );
416
417 int x{}, y{}, index{};
418 for (; y<height; ++y) {
419 for (x=0; x<width; ++x) {
420 //Fixme: Does this also work for components=1,2 4??
421 im.setPixel ( x, height-y-1, QColor( static_cast<int>(data[index]),static_cast<int>(data[index+1]),static_cast<int>(data[index+2]),static_cast<int>(data[index+3]) ).rgb() );
422 index+=4;
423 }
424 }
425 free(imagedata);
426 return im;
427}
428
429
430//____________________________________________________________________
431//QImage VP1QtInventorUtils::renderToImage(SoQtRenderArea *ra, int pixels_x, int pixels_y,
432QImage VP1QtInventorUtils::renderToImage(VP1ExaminerViewer *ra, int pixels_x, int pixels_y,
433 bool transparent_background, double actualRenderedSizeFact )
434{
435 VP1Msg::messageVerbose("VP1QtInventorUtils::renderToImage()");
436
437 if (!ra)
438 return QImage();
439
440
441 // transp,anti: Render two large, figure out transp, then resize (gives best result)
442 // transp : Render two normal, then figure out transp.
443 // : Render one normal.
444 // anti : Render one large, resize.
445
446 if (actualRenderedSizeFact!=1.0&&!transparent_background) {
447 return renderToImage(ra,
448 static_cast<int>(pixels_x*actualRenderedSizeFact+0.5),
449 static_cast<int>(pixels_y*actualRenderedSizeFact+0.5),
450 false,
451 1.0)
452 .scaled(pixels_x,pixels_y,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
453 }
454
455 if (transparent_background) {
456 //Lets make it transparent. We do this by rendering with both
457 //white and black background, and using the two results to figure
458 //out the final result.
459
460 SbColor save_bgd = ra->getBackgroundColor();
461 SbBool save_redraw = ra->isAutoRedraw();
462
463 ra->setAutoRedraw(false);
464
465
466 QImage im_black_bgd, im_white_bgd;
467 if (actualRenderedSizeFact==1.0) {
468 ra->setBackgroundColor(SbColor(0.0,0.0,0.0));
469 im_black_bgd = renderToImage(ra, pixels_x, pixels_y,false,1.0);
470 ra->setBackgroundColor(SbColor(1.0,1.0,1.0));
471 im_white_bgd = renderToImage(ra, pixels_x, pixels_y,false,1.0);
472 } else {
473 ra->setBackgroundColor(SbColor(0.0,0.0,0.0));
474 im_black_bgd = renderToImage(ra, static_cast<int>(pixels_x*actualRenderedSizeFact+0.5), static_cast<int>(pixels_y*actualRenderedSizeFact+0.5),false,1.0);
475 ra->setBackgroundColor(SbColor(1.0,1.0,1.0));
476 im_white_bgd = renderToImage(ra, static_cast<int>(pixels_x*actualRenderedSizeFact+0.5), static_cast<int>(pixels_y*actualRenderedSizeFact+0.5),false,1.0);
477 }
478
479 ra->setBackgroundColor(save_bgd);
480 ra->setAutoRedraw(save_redraw);
481
482 if (actualRenderedSizeFact==1.0)
483 return Imp::constructImageWithTransparentBackground(im_black_bgd, im_white_bgd);
484 else
485 return Imp::constructImageWithTransparentBackground(im_black_bgd, im_white_bgd)
486 .scaled(pixels_x,pixels_y,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
487 }
488
489 // DEFAULT CALL
490
491 //debug
492 int off = ra->getStereoOffsetSlot();
493 int typeSt = ra->getStereoTypeSlot();
494 VP1Msg::messageVerbose("off: " + QString::number( off ) + " - type: " + QString::number( typeSt ) );
495
496 // get the scenegraph
497 SoNode *root = ra->getSceneManager()->getSceneGraph();
498 VP1Msg::messageVerbose("got the scenegraph");
499 //std::cout << "root: " << root << std::endl;
500
501 // get the overlay scenegraph
502// SoNode *rootOverlay = ra->getOverlaySceneManager()->getSceneGraph();
503 SoNode *rootOverlay = ra->getOverlaySceneGraph();
504 VP1Msg::messageVerbose("got the overlay scenegraph");
505 //std::cout << "overlay root: " << rootOverlay << std::endl;
506
507 // set a new viewport to the preferred size
508 SbViewportRegion myViewport;
509 myViewport.setWindowSize(SbVec2s(pixels_x,pixels_y));
510
511 QString tmppath(QDir::tempPath());
512 if (!tmppath.endsWith(QDir::separator()))
513 tmppath+=QDir::separator();
514 tmppath += "vp1tmpfileXXXXXX.rgb";
515 std::string stmppath = tmppath.toStdString();
516 int tmpfd = mkstemps (stmppath.data(), 4);
517 FILE* tmpf = fdopen (tmpfd, "w");
518 QString tmpfile (stmppath.c_str());
519
520 // declare a new renderer with the viewport created above
521 SoOffscreenRenderer *myRenderer = new SoOffscreenRenderer(myViewport);
522
523 //Copy settings from the render area:
524 myRenderer->setBackgroundColor(ra->getBackgroundColor());
525
526
527 myRenderer->setComponents(SoOffscreenRenderer::RGB_TRANSPARENCY);
528 myRenderer->getGLRenderAction()->setTransparencyType(ra->getTransparencyType());
529 // myRenderer->getGLRenderAction()->addPreRenderCallback( VP1QtInventorUtils::Imp::prerendercallback_rendertoimage, 0/*userdata*/ );
530
531 // Anti-Aliasing
532 SbBool smoothing; int numPasses;
533 ra->getAntialiasing (smoothing, numPasses);
534 myRenderer->getGLRenderAction()->setSmoothing (smoothing);
535 myRenderer->getGLRenderAction()->setNumPasses(numPasses);
536
537 //Other things we could set:
538 // Overlay scenegraph.
539
540 // render the scenegraph
541 // if fails, delete the renderer and return an empty image
542 if (!myRenderer->render(root)) {
543 delete myRenderer;
544 fclose (tmpf);
545 return QImage();
546 }
547 VP1Msg::messageVerbose("rendered the scenegraph");
548
549 // render the overlay scenegraph
550 // if fails, delete the renderer and return an empty image
551 if (rootOverlay) {
552 bool okOver = myRenderer->render(rootOverlay);
553 if ( !okOver) {
554 delete myRenderer;
555 fclose (tmpf);
556 return QImage();
557 }
558 else {
559 VP1Msg::messageVerbose("rendered the overlay scenegraph");
560 }
561 }
562
563 // write the rendered image to the temp file
564 // if fails, remove the temp file and return an empty image
565 if (!myRenderer->writeToRGB(tmpf)) {
566 fclose (tmpf);
567 if (QFile::exists(tmpfile))
568 QFile(tmpfile).remove();
569 delete myRenderer;
570 return QImage();
571 }
572
573 fclose (tmpf);
574
575 // delete the renderer
576 delete myRenderer;
577
578 // get the rendered image from the temp file as a Qt QImage instance
579 QImage im(imageFromRGBFile(tmpfile));
580
581 // delete the temp file
582 if (QFile::exists(tmpfile))
583 QFile(tmpfile).remove();
584
585 // return the rendered image
586 return im;
587}
588
589//____________________________________________________________________
590//QPixmap VP1QtInventorUtils::renderToPixmap(SoQtRenderArea *ra, int pixels_x, int pixels_y,
591QPixmap VP1QtInventorUtils::renderToPixmap(VP1ExaminerViewer *ra, int pixels_x, int pixels_y,
592 bool transparent_background, double actualRenderedSizeFact )
593{
594 return QPixmap::fromImage(renderToImage(ra, pixels_x, pixels_y, transparent_background, actualRenderedSizeFact));
595}
596
597//____________________________________________________________________
598QImage VP1QtInventorUtils::Imp::constructImageWithTransparentBackground(const QImage& im_black_bgd, const QImage& im_white_bgd)
599{
600 if (im_black_bgd.isNull()||im_white_bgd.isNull()||im_black_bgd.size()!=im_white_bgd.size())
601 return QImage();
602
603 QImage im(im_black_bgd.size(),QImage::Format_ARGB32);
604
605 int width = im.width();
606 int height = im.height();
607 QRgb white = qRgba(255,255,255,255);
608 QRgb black = qRgba(0,0,0,255);
609
610 for (int x = 0; x < width; ++x)
611 for (int y = 0; y < height; ++y) {
612 if (im_black_bgd.pixel(x,y)==im_white_bgd.pixel(x,y)) {
613 im.setPixel(x,y,im_white_bgd.pixel(x,y));
614 } else if (im_black_bgd.pixel(x,y)==black&&im_white_bgd.pixel(x,y)==white) {
615 im.setPixel(x,y,Qt::transparent);
616 } else {
617 //Calculate ...
618 QColor pix_b = QColor(im_black_bgd.pixel(x,y));
619 QColor pix_w = QColor(im_white_bgd.pixel(x,y));
620 qreal alpha = 1.0 - pix_w.redF() + pix_b.redF();
621 if (alpha==0) {
622 im.setPixel(x,y,Qt::transparent);
623 } else {
624 im.setPixel(x,y,qRgba(static_cast<int>(pix_b.redF()/alpha*255+0.5),
625 static_cast<int>(pix_b.greenF()/alpha*255+0.5),
626 static_cast<int>(pix_b.blueF()/alpha*255+0.5),
627 static_cast<int>(alpha*255+0.5)));
628 }
629 }
630 }
631
632 return im;
633}
634
635
636//____________________________________________________________________
637SoGLRenderAction::TransparencyType VP1QtInventorUtils::getDefaultVP1TransparencyType()
638{
639 return SoGLRenderAction::DELAYED_BLEND;
640}
641
642//____________________________________________________________________
643QList<SoGLRenderAction::TransparencyType> VP1QtInventorUtils::getAllTransparencyTypes()
644{
645 QList<SoGLRenderAction::TransparencyType> l;
646 l << SoGLRenderAction::NONE
647 << SoGLRenderAction::SCREEN_DOOR
648 << SoGLRenderAction::ADD
649 << SoGLRenderAction::DELAYED_ADD
650 << SoGLRenderAction::SORTED_OBJECT_ADD
651 << SoGLRenderAction::BLEND
652 << SoGLRenderAction::DELAYED_BLEND
653 << SoGLRenderAction::SORTED_OBJECT_BLEND
654 << SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_ADD
655 << SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND
656 << SoGLRenderAction::SORTED_LAYERS_BLEND;
657 return l;
658}
659
660//____________________________________________________________________
661int VP1QtInventorUtils::transparencyTypeToInt( SoGLRenderAction::TransparencyType tt )
662{
663 switch (tt) {
664 case SoGLRenderAction::SCREEN_DOOR: return 0;
665 case SoGLRenderAction::ADD: return 1;
666 case SoGLRenderAction::DELAYED_ADD: return 2;
667 case SoGLRenderAction::SORTED_OBJECT_ADD: return 3;
668 case SoGLRenderAction::BLEND: return 4;
669 case SoGLRenderAction::DELAYED_BLEND: return 5;
670 case SoGLRenderAction::SORTED_OBJECT_BLEND: return 6;
671 case SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_ADD: return 7;
672 case SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND: return 8;
673 case SoGLRenderAction::NONE: return 9;
674 case SoGLRenderAction::SORTED_LAYERS_BLEND: return 10;
675 default:
676 VP1Msg::messageDebug("VP1QtInventorUtils::transparencyTypeToInt ERROR: Unknown transparency type");
677 return -1;
678 }
679}
680//____________________________________________________________________
681SoGLRenderAction::TransparencyType VP1QtInventorUtils::intToTransparencyType( int i )
682{
683 switch (i) {
684 case 0: return SoGLRenderAction::SCREEN_DOOR;
685 case 1: return SoGLRenderAction::ADD;
686 case 2: return SoGLRenderAction::DELAYED_ADD;
687 case 3: return SoGLRenderAction::SORTED_OBJECT_ADD;
688 case 4: return SoGLRenderAction::BLEND;
689 case 5: return SoGLRenderAction::DELAYED_BLEND;
690 case 6: return SoGLRenderAction::SORTED_OBJECT_BLEND;
691 case 7: return SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_ADD;
692 case 8: return SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND;
693 case 9: return SoGLRenderAction::NONE;
694 case 10: return SoGLRenderAction::SORTED_LAYERS_BLEND;
695 default:
696 VP1Msg::messageDebug("VP1QtInventorUtils::intToTransparencyType ERROR: int out of range "+VP1Msg::str(i));
697 return SoGLRenderAction::DELAYED_BLEND;
698 }
699}
700
701
702//____________________________________________________________________
703QString VP1QtInventorUtils::transparencyType2PrettyString( SoGLRenderAction::TransparencyType tt )
704{
705 switch (tt) {
706 case SoGLRenderAction::DELAYED_BLEND: return "Delayed blend"; break;
707 case SoGLRenderAction::SCREEN_DOOR: return "Screen door"; break;
708 case SoGLRenderAction::ADD: return "Add"; break;
709 case SoGLRenderAction::DELAYED_ADD: return "Delayed add"; break;
710 case SoGLRenderAction::SORTED_OBJECT_ADD: return "Sorted object add"; break;
711 case SoGLRenderAction::BLEND: return "Blend (Best for Geo volumes)"; break;
712 case SoGLRenderAction::SORTED_OBJECT_BLEND: return "Sorted object blend (Best for physics objects: jets, tracks, ...)"; break;
713 case SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_ADD: return "Sorted object sorted triangle add"; break;
714 case SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND: return "Sorted object sorted triangle blend"; break;
715 case SoGLRenderAction::NONE: return "None"; break;
716 case SoGLRenderAction::SORTED_LAYERS_BLEND: return "Sorted layers blend"; break;
717 default: return "";
718 }
719
720}
721
722//____________________________________________________________________
723QByteArray VP1QtInventorUtils::serialize( const SbRotation& rot )
724{
725
726 // ===> Setup stream writing to a byteArray:
727 QByteArray byteArray;
728 QBuffer buffer(&byteArray);
729 buffer.open(QIODevice::WriteOnly);
730 QDataStream out(&buffer);
731
732 //Write data:
733
734 float q0,q1,q2,q3;//quarternion components
735 rot.getValue (q0,q1,q2,q3);
736
737 out<<(double)q0;
738 out<<(double)q1;
739 out<<(double)q2;
740 out<<(double)q3;
741
742 if (VP1Msg::verbose()) {
743 //Fixme: check for nan's.
744 VP1Msg::messageVerbose("VP1QtInventorUtils::serialize SbRotation(q0,q1,q2,q3) = ("
745 +QString::number(q0)+", "+QString::number(q1)+", "
746 +QString::number(q2)+", "+QString::number(q3)+")");
747 }
748
749 // ===> Finish up:
750 buffer.close();
751 return byteArray;
752}
753
754//____________________________________________________________________
755bool VP1QtInventorUtils::deserialize( QByteArray& ba, SbRotation& rot )
756{
757 // ===> Setup stream for getting the contents of the byteArray:
758 QBuffer buffer(&ba);
759 buffer.open(QIODevice::ReadOnly);
760 QDataStream state(&buffer);
762 if(ba.size()==16) {
763 // Single precision
764 state.setFloatingPointPrecision(QDataStream::SinglePrecision);
765 float q0,q1,q2,q3;//quarternion components
766
767 state >> q0;
768 state >> q1;
769 state >> q2;
770 state >> q3;
771
772 rot.setValue (q0,q1,q2,q3);
773
774 if (VP1Msg::verbose()) {
775 //Fixme: check for nan's.
776 VP1Msg::messageVerbose("VP1QtInventorUtils::deserialize SbRotation(q0,q1,q2,q3) = ("
777 +QString::number(q0)+", "+QString::number(q1)+", "
778 +QString::number(q2)+", "+QString::number(q3)+")");
779 }
780 }
781 else {
782 // Double precision
783 double q0,q1,q2,q3;//quarternion components
784
785 state >> q0;
786 state >> q1;
787 state >> q2;
788 state >> q3;
789
790 rot.setValue (q0,q1,q2,q3);
791
792 if (VP1Msg::verbose()) {
793 //Fixme: check for nan's.
794 VP1Msg::messageVerbose("VP1QtInventorUtils::deserialize SbRotation(q0,q1,q2,q3) = ("
795 +QString::number(q0)+", "+QString::number(q1)+", "
796 +QString::number(q2)+", "+QString::number(q3)+")");
797 }
798 }
799
800 // ===> Finish up:
801 buffer.close();
802
803 return true;//Fixme: How to check for errors? - at least check for nan's and determinant?
804}
805
806//____________________________________________________________________
807QByteArray VP1QtInventorUtils::serialize( const SbVec3f& vec )
808{
809 // ===> Setup stream writing to a byteArray:
810 QByteArray byteArray;
811 QBuffer buffer(&byteArray);
812 buffer.open(QIODevice::WriteOnly);
813 QDataStream out(&buffer);
814
815 //Write data:
816 float x,y,z;
817 vec.getValue(x,y,z);
818 out << (double)x;
819 out << (double)y;
820 out << (double)z;
821
822 if (VP1Msg::verbose()) {
823 //Fixme: check for nan's.
824 VP1Msg::messageVerbose("VP1QtInventorUtils::serialize SbVec3f(x,y,z) = ("
825 +QString::number(x)+", "+QString::number(y)+", "+QString::number(z)+")");
826 }
827
828 // ===> Finish up:
829 buffer.close();
830 return byteArray;
831}
832
833//____________________________________________________________________
834bool VP1QtInventorUtils::deserialize( QByteArray& ba, SbVec3f& vec )
835{
836 // ===> Setup stream for getting the contents of the byteArray:
837 QBuffer buffer(&ba);
838 buffer.open(QIODevice::ReadOnly);
839 QDataStream state(&buffer);
841 if(ba.size()==12) {
842 // Single precision
843 state.setFloatingPointPrecision(QDataStream::SinglePrecision);
844 float x,y,z;
845
846 state >> x;
847 state >> y;
848 state >> z;
849
850 vec.setValue (x,y,z);
851
852 if (VP1Msg::verbose()) {
853 //Fixme: check for nan's.
854 VP1Msg::messageVerbose("VP1QtInventorUtils::deserialize SbVec3f(x,y,z) = ("
855 +QString::number(x)+", "+QString::number(y)+", "+QString::number(z)+")");
856 }
857 }
858 else {
859 double x,y,z;
860
861 state >> x;
862 state >> y;
863 state >> z;
864
865 vec.setValue (x,y,z);
866
867 if (VP1Msg::verbose()) {
868 //Fixme: check for nan's.
869 VP1Msg::messageVerbose("VP1QtInventorUtils::deserialize SbVec3f(x,y,z) = ("
870 +QString::number(x)+", "+QString::number(y)+", "+QString::number(z)+")");
871 }
872 }
873
874 // ===> Finish up:
875 buffer.close();
876
877 return true;//Fixme: How to check for errors? - at least check for nan's
878
879}
880
881//____________________________________________________________________
882QByteArray VP1QtInventorUtils::serializeSoCameraParameters( const SoCamera& cam ) {
883
884 VP1Msg::messageVerbose("VP1QtInventorUtils::serializeSoCameraParameters start");
885
886 // ===> Setup stream writing to a byteArray:
887 QByteArray byteArray;
888 QBuffer buffer(&byteArray);
889 buffer.open(QIODevice::WriteOnly);
890 QDataStream out(&buffer);
891
892 cam.ref();
893 //Write data:
894 SbRotation camrot = cam.orientation.getValue();
895 out << serialize(camrot);
896 SbVec3f campos = cam.position.getValue();
897 out << serialize(campos);
898 float f_aspectRatio(cam.aspectRatio.getValue());
899 float f_nearDistance(cam.nearDistance.getValue());
900 float f_farDistance(cam.farDistance.getValue());
901 float f_focalDistance(cam.focalDistance.getValue());
902 out << (double)f_aspectRatio;
903 out << (double)f_nearDistance;
904 out << (double)f_farDistance;
905 out << (double)f_focalDistance;
906
907 int viewportmap(-1);
908 switch (cam.viewportMapping.getValue()) {
909 case SoCamera::CROP_VIEWPORT_FILL_FRAME: viewportmap = 0;break;
910 case SoCamera::CROP_VIEWPORT_LINE_FRAME: viewportmap = 1;break;
911 case SoCamera::CROP_VIEWPORT_NO_FRAME: viewportmap = 2;break;
912 case SoCamera::ADJUST_CAMERA: viewportmap = 3;break;
913 case SoCamera::LEAVE_ALONE: viewportmap = 4;break;
914 }
915 out << viewportmap;
916
917 //Camera type and specialised info:
918 int camtype (-1);
919 if (cam.getTypeId().isDerivedFrom(SoPerspectiveCamera::getClassTypeId()))
920 camtype = 0;
921 else if (cam.getTypeId().isDerivedFrom(SoOrthographicCamera::getClassTypeId()))
922 camtype = 1;
923
924 out <<camtype;
925 if (camtype==0) {
926 out << (double)static_cast<const SoPerspectiveCamera*>(&cam)->heightAngle.getValue();
927 } else if (camtype==1) {
928 out << (double)static_cast<const SoOrthographicCamera*>(&cam)->height.getValue();
929 }
930
931 cam.unrefNoDelete();
932
933 // ===> Finish up:
934 buffer.close();
935
936 if (VP1Msg::verbose()) {
937 VP1Msg::messageVerbose("VP1QtInventorUtils::serializeSoCameraParameters aspectRatio = "+QString::number(f_aspectRatio));
938 VP1Msg::messageVerbose("VP1QtInventorUtils::serializeSoCameraParameters nearDistance = "+QString::number(f_nearDistance));
939 VP1Msg::messageVerbose("VP1QtInventorUtils::serializeSoCameraParameters farDistance = "+QString::number(f_farDistance));
940 VP1Msg::messageVerbose("VP1QtInventorUtils::serializeSoCameraParameters focalDistance = "+QString::number(f_focalDistance));
941 VP1Msg::messageVerbose("VP1QtInventorUtils::serializeSoCameraParameters viewportmap = "+QString::number(viewportmap));
942 VP1Msg::messageVerbose("VP1QtInventorUtils::serializeSoCameraParameters camtype = "
943 +QString(camtype==0?"perspective":(camtype==1?"orthographic":"unknown")));
944 if (camtype==0)
945 VP1Msg::messageVerbose("VP1QtInventorUtils::serializeSoCameraParameters (persp) heightAngle = "
946 +QString::number(static_cast<const SoPerspectiveCamera*>(&cam)->heightAngle.getValue()));
947 if (camtype==1)
948 VP1Msg::messageVerbose("VP1QtInventorUtils::serializeSoCameraParameters (ortho) height = "
949 +QString::number(static_cast<const SoOrthographicCamera*>(&cam)->height.getValue()));
950 VP1Msg::messageVerbose("VP1QtInventorUtils::serializeSoCameraParameters end");
951 }
952
953 return byteArray;
954}
955
956//____________________________________________________________________
957bool VP1QtInventorUtils::deserializeSoCameraParameters( QByteArray& ba, SoCamera& cam )
958{
959 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters start");
960 if (ba==QByteArray())
961 return false;
962
963 // ===> Setup stream for getting the contents of the byteArray:
964 QBuffer buffer(&ba);
965 buffer.open(QIODevice::ReadOnly);
966 QDataStream state(&buffer);
968 if(ba.size()==64) {
969 // Single precision
970 state.setFloatingPointPrecision(QDataStream::SinglePrecision);
971
972 //Orientation:
973 SbRotation rot; QByteArray ba_rot; state >> ba_rot;
974 if (!deserialize(ba_rot,rot)) return false;
975 //position:
976 SbVec3f pos; QByteArray ba_pos; state >> ba_pos;
977 if (!deserialize(ba_pos,pos)) return false;
978
979 bool save = cam.enableNotify(false);
980 cam.ref();
981 cam.orientation.setValue(rot);
982 cam.position.setValue(pos);
983 //Misc:
984 float f_aspectRatio, f_nearDistance, f_farDistance, f_focalDistance;
985
986 state >> f_aspectRatio; cam.aspectRatio.setValue(f_aspectRatio);
987 state >> f_nearDistance; cam.nearDistance.setValue(f_nearDistance);
988 state >> f_farDistance; cam.farDistance.setValue(f_farDistance);
989 state >> f_focalDistance; cam.focalDistance.setValue(f_focalDistance);
990 //viewport mapping:
991 int viewportmap;
992 state>>viewportmap;
993 switch (viewportmap) {
994 case 0: cam.viewportMapping.setValue(SoCamera::CROP_VIEWPORT_FILL_FRAME); break;
995 case 1: cam.viewportMapping.setValue(SoCamera::CROP_VIEWPORT_LINE_FRAME);break;
996 case 2: cam.viewportMapping.setValue(SoCamera::CROP_VIEWPORT_NO_FRAME);break;
997 case 3: cam.viewportMapping.setValue(SoCamera::ADJUST_CAMERA);break;
998 case 4: cam.viewportMapping.setValue(SoCamera::LEAVE_ALONE);break;
999 //ERROR
1000 }
1001
1002 bool passedcameraisperspective = cam.getTypeId().isDerivedFrom(SoPerspectiveCamera::getClassTypeId());
1003
1004 //Camera type and specialised info:
1005 int camtype;
1006 state>>camtype;
1007 float f_orthopersp_heightpar(-999);
1008 if (camtype==0) {
1009 //perspective
1010 if (!passedcameraisperspective)
1011 return false;
1012 state >> f_orthopersp_heightpar;
1013 static_cast<SoPerspectiveCamera*>(&cam)->heightAngle.setValue(f_orthopersp_heightpar);
1014 } else if (camtype==1) {
1015 //ortho
1016 if (passedcameraisperspective)
1017 return false;
1018 state >> f_orthopersp_heightpar;
1019 static_cast<SoOrthographicCamera*>(&cam)->height.setValue(f_orthopersp_heightpar);
1020 }
1021
1022 if (save) {
1023 cam.enableNotify(true);
1024 cam.touch();
1025 }
1026
1027 // ===> Finish up:
1028 buffer.close();
1029
1030 if (VP1Msg::verbose()) {
1031 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters aspectRatio = "+QString::number(f_aspectRatio));
1032 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters nearDistance = "+QString::number(f_nearDistance));
1033 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters farDistance = "+QString::number(f_farDistance));
1034 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters focalDistance = "+QString::number(f_focalDistance));
1035 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters viewportmap = "+QString::number(viewportmap));
1036 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters camtype = "
1037 +QString(camtype==0?"perspective":(camtype==1?"orthographic":"unknown")));
1038 if (camtype==0)
1039 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters (persp) heightAngle = "
1040 +QString::number(f_orthopersp_heightpar));
1041 if (camtype==1)
1042 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters (ortho) height = "
1043 +QString::number(f_orthopersp_heightpar));
1044
1045 }
1046 }
1047 else {
1048 // Double precision
1049
1050 //Orientation:
1051 SbRotation rot; QByteArray ba_rot; state >> ba_rot;
1052 if (!deserialize(ba_rot,rot)) return false;
1053 //position:
1054 SbVec3f pos; QByteArray ba_pos; state >> ba_pos;
1055 if (!deserialize(ba_pos,pos)) return false;
1056
1057 bool save = cam.enableNotify(false);
1058 cam.ref();
1059 cam.orientation.setValue(rot);
1060 cam.position.setValue(pos);
1061 //Misc:
1062 double f_aspectRatio, f_nearDistance, f_farDistance, f_focalDistance;
1063
1064 state >> f_aspectRatio; cam.aspectRatio.setValue(f_aspectRatio);
1065 state >> f_nearDistance; cam.nearDistance.setValue(f_nearDistance);
1066 state >> f_farDistance; cam.farDistance.setValue(f_farDistance);
1067 state >> f_focalDistance; cam.focalDistance.setValue(f_focalDistance);
1068 //viewport mapping:
1069 int viewportmap;
1070 state>>viewportmap;
1071 switch (viewportmap) {
1072 case 0: cam.viewportMapping.setValue(SoCamera::CROP_VIEWPORT_FILL_FRAME); break;
1073 case 1: cam.viewportMapping.setValue(SoCamera::CROP_VIEWPORT_LINE_FRAME);break;
1074 case 2: cam.viewportMapping.setValue(SoCamera::CROP_VIEWPORT_NO_FRAME);break;
1075 case 3: cam.viewportMapping.setValue(SoCamera::ADJUST_CAMERA);break;
1076 case 4: cam.viewportMapping.setValue(SoCamera::LEAVE_ALONE);break;
1077 //ERROR
1078 }
1079
1080 bool passedcameraisperspective = cam.getTypeId().isDerivedFrom(SoPerspectiveCamera::getClassTypeId());
1081
1082 //Camera type and specialised info:
1083 int camtype;
1084 state>>camtype;
1085 double f_orthopersp_heightpar(-999);
1086 if (camtype==0) {
1087 //perspective
1088 if (!passedcameraisperspective)
1089 return false;
1090 state >> f_orthopersp_heightpar;
1091 static_cast<SoPerspectiveCamera*>(&cam)->heightAngle.setValue(f_orthopersp_heightpar);
1092 } else if (camtype==1) {
1093 //ortho
1094 if (passedcameraisperspective)
1095 return false;
1096 state >> f_orthopersp_heightpar;
1097 static_cast<SoOrthographicCamera*>(&cam)->height.setValue(f_orthopersp_heightpar);
1098 }
1099
1100 if (save) {
1101 cam.enableNotify(true);
1102 cam.touch();
1103 }
1104
1105 // ===> Finish up:
1106 buffer.close();
1107
1108 if (VP1Msg::verbose()) {
1109 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters aspectRatio = "+QString::number(f_aspectRatio));
1110 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters nearDistance = "+QString::number(f_nearDistance));
1111 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters farDistance = "+QString::number(f_farDistance));
1112 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters focalDistance = "+QString::number(f_focalDistance));
1113 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters viewportmap = "+QString::number(viewportmap));
1114 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters camtype = "
1115 +QString(camtype==0?"perspective":(camtype==1?"orthographic":"unknown")));
1116 if (camtype==0)
1117 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters (persp) heightAngle = "
1118 +QString::number(f_orthopersp_heightpar));
1119 if (camtype==1)
1120 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters (ortho) height = "
1121 +QString::number(f_orthopersp_heightpar));
1122
1123 }
1124 }
1125
1126 cam.unrefNoDelete();
1127 VP1Msg::messageVerbose("VP1QtInventorUtils::deserializeSoCameraParameters end");
1128 return true;
1129}
1130
1131//____________________________________________________________________
1132SbColor VP1QtInventorUtils::qcol2sbcol(const QColor& col)
1133{
1134 return SbColor( col.red()/255.0, col.green()/255.0, col.blue()/255.0 );
1135}
1136
1137//____________________________________________________________________
1138QColor VP1QtInventorUtils::sbcol2qcol(const SbColor& col)
1139{
1140 float r,g,b;
1141 col.getValue(r,g,b);
1142 return QColor::fromRgbF( r,g,b );
1143}
1144
1145//____________________________________________________________________
1147{
1148 if (!m||m->ambientColor.getNum()!=1
1149 ||m->diffuseColor.getNum()!=1
1150 ||m->specularColor.getNum()!=1
1151 ||m->emissiveColor.getNum()!=1
1152 ||m->transparency.getNum()!=1
1153 ||m->shininess.getNum()!=1) {
1154 VP1Msg::message("VP1QtInventorUtils::serialiseSoMaterial Error: "
1155 "Passed material must have exactly one value in each of the 6 fields!!");
1156 return QByteArray();
1157 }
1158
1159
1160 // ===> Setup stream writing to a byteArray:
1161 QByteArray byteArray;
1162 QBuffer buffer(&byteArray);
1163 buffer.open(QIODevice::WriteOnly);
1164 QDataStream out(&buffer);
1165
1166 //Write data:
1167 out << QString("somat_v1_begin");
1168 out << sbcol2qcol(m->ambientColor[0]);
1169 out << sbcol2qcol(m->diffuseColor[0]);
1170 out << sbcol2qcol(m->specularColor[0]);
1171 out << sbcol2qcol(m->emissiveColor[0]);
1172 out << (double)m->shininess[0];
1173 out << (double)m->transparency[0];
1174 out << QString("somat_end");
1175
1176 // ===> Finish up:
1177 buffer.close();
1178
1179 return byteArray;
1180
1181}
1182
1183//____________________________________________________________________
1184bool VP1QtInventorUtils::deserialiseSoMaterial(QByteArray&ba,SoMaterial *&m)
1185{
1186 if (!m||m->ambientColor.getNum()!=1
1187 ||m->diffuseColor.getNum()!=1
1188 ||m->specularColor.getNum()!=1
1189 ||m->emissiveColor.getNum()!=1
1190 ||m->transparency.getNum()!=1
1191 ||m->shininess.getNum()!=1) {
1192 VP1Msg::message("VP1QtInventorUtils::deserialiseSoMaterial Error: "
1193 "Passed material must have exactly one value in each of the 6 fields!!");
1194 return false;
1195 }
1196
1197 // ===> Setup stream for getting the contents of the byteArray:
1198 QBuffer buffer(&ba);
1199 buffer.open(QIODevice::ReadOnly);
1200 QDataStream stream(&buffer);
1201 if(ba.size()==106)
1202 stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
1203
1204 //Read contents while checking for validity
1205 QString str; stream >> str;
1206 if (str!="somat_v1_begin")
1207 return false;
1208
1209 QColor ambientcol; stream >> ambientcol;
1210 if (!ambientcol.isValid())
1211 return false;
1212
1213 QColor diffusecol; stream >> diffusecol;
1214 if (!diffusecol.isValid())
1215 return false;
1216
1217 QColor specularcol; stream >> specularcol;
1218 if (!specularcol.isValid())
1219 return false;
1220
1221 QColor emissivecol; stream >> emissivecol;
1222 if (!emissivecol.isValid())
1223 return false;
1224
1225 if(ba.size()==106) {
1226 // Single precision
1227 float shininess; stream >> shininess;
1228 if (shininess<0.0f||shininess>1.0f)
1229 return false;
1230
1231 float transparency; stream >> transparency;
1232 if (transparency<0.0f||transparency>1.0f)
1233 return false;
1234
1235 stream >> str;
1236 if (str!="somat_end")
1237 return false;
1238
1239 buffer.close();
1240
1241 //Apply values:
1242 m->ambientColor.setValue(qcol2sbcol(ambientcol));
1243 m->diffuseColor.setValue(qcol2sbcol(diffusecol));
1244 m->specularColor.setValue(qcol2sbcol(specularcol));
1245 m->emissiveColor.setValue(qcol2sbcol(emissivecol));
1246 m->shininess.setValue(shininess);
1247 m->transparency.setValue(transparency);
1248 }
1249 else {
1250 // Double precision
1251 double shininess; stream >> shininess;
1252 if (shininess<0.0||shininess>1.0)
1253 return false;
1254
1255 double transparency; stream >> transparency;
1256 if (transparency<0.0||transparency>1.0)
1257 return false;
1258
1259 stream >> str;
1260 if (str!="somat_end")
1261 return false;
1262
1263 buffer.close();
1264
1265 //Apply values:
1266 m->ambientColor.setValue(qcol2sbcol(ambientcol));
1267 m->diffuseColor.setValue(qcol2sbcol(diffusecol));
1268 m->specularColor.setValue(qcol2sbcol(specularcol));
1269 m->emissiveColor.setValue(qcol2sbcol(emissivecol));
1270 m->shininess.setValue(shininess);
1271 m->transparency.setValue(transparency);
1272 }
1273
1274 return true;
1275}
1276
1277//____________________________________________________________________
1278SoNode * VP1QtInventorUtils::createCircle( const double& radius )
1279{
1280 SoGroup* grp = new SoGroup;
1281 grp->ref();
1282
1283 SoCoordinate4 * coord = new SoCoordinate4;
1284 const double invsqrttwo=0.707106781186547;
1285
1286 int icoord(0);
1287 coord->point.set1Value(icoord++,SbVec4f(1*radius,0,0,1));
1288 coord->point.set1Value(icoord++,SbVec4f(invsqrttwo*radius,invsqrttwo*radius,0,invsqrttwo));
1289 coord->point.set1Value(icoord++,SbVec4f(0,1*radius,0,1));
1290 coord->point.set1Value(icoord++,SbVec4f(-invsqrttwo*radius,invsqrttwo*radius,0,invsqrttwo));
1291 coord->point.set1Value(icoord++,SbVec4f(-1*radius,0,0,1));
1292 coord->point.set1Value(icoord++,SbVec4f(-invsqrttwo*radius,-invsqrttwo*radius,0,invsqrttwo));
1293 coord->point.set1Value(icoord++,SbVec4f(0,-1*radius,0,1));
1294 coord->point.set1Value(icoord++,SbVec4f(invsqrttwo*radius,-invsqrttwo*radius,0,invsqrttwo));
1295 coord->point.set1Value(icoord++,SbVec4f(1*radius,0,0,1));
1296
1297 SoNurbsCurve * curve = new SoNurbsCurve;
1298 curve->numControlPoints = icoord;
1299
1300 int iknot(0);
1301
1302 curve->knotVector.set1Value(iknot++,0);
1303 curve->knotVector.set1Value(iknot++,0);
1304 curve->knotVector.set1Value(iknot++,0);
1305 curve->knotVector.set1Value(iknot++,1);
1306 curve->knotVector.set1Value(iknot++,1);
1307 curve->knotVector.set1Value(iknot++,2);
1308 curve->knotVector.set1Value(iknot++,2);
1309 curve->knotVector.set1Value(iknot++,3);
1310 curve->knotVector.set1Value(iknot++,3);
1311 curve->knotVector.set1Value(iknot++,4);
1312 curve->knotVector.set1Value(iknot++,4);
1313 curve->knotVector.set1Value(iknot++,4);
1314 grp->addChild(coord);
1315 grp->addChild(curve);
1316
1317 grp->unrefNoDelete();
1318 return grp;
1319}
1320
1321//____________________________________________________________________
1322SoNode * VP1QtInventorUtils::createEllipse( const double& radiusX, const double& radiusY, const int& numnodes )
1323{
1324 SoVertexProperty *vertices = new SoVertexProperty();
1325
1326 int iver(0);
1327 vertices->vertex.set1Value(iver++,radiusX,0.0,0.0);
1328 for (int i = 1; i < numnodes; i++)
1329 {
1330 vertices->vertex.set1Value(iver++,
1331 cos(2.0*static_cast<double>(i)*M_PI/static_cast<double>(numnodes))*radiusX,
1332 sin(2.0*static_cast<double>(i)*M_PI/static_cast<double>(numnodes))*radiusY,0.0);
1333 }
1334 vertices->vertex.set1Value(iver++,radiusX,0.0,0.0);
1335
1336 SoLineSet * ellipse = new SoLineSet();
1337 ellipse->numVertices = iver;
1338 ellipse->vertexProperty = vertices;
1339
1340 return ellipse;
1341}
1342
1343//_____________________________________________________________________________________
1344bool VP1QtInventorUtils::changePathTail(SoPath*path,SoNode*commonBranchPoint,SoNode*newtail)
1345{
1346 if (!path||!commonBranchPoint||!newtail)
1347 return false;
1348
1349 SoSearchAction sa;
1350 sa.setInterest(SoSearchAction::FIRST);
1351 sa.setNode(newtail);
1352 sa.apply(commonBranchPoint);
1353 //First truncate pickedPath at d->sceneroot, then append
1354 //newpath to pickedPath:
1355 SoPath * newpath = sa.getPath();
1356 if (!newpath)
1357 return false;
1358 bool found(false);
1359 for (int i=0;i<path->getLength();++i) {
1360 if (path->getNode(i)==commonBranchPoint) {
1361 found = true;
1362 path->truncate(i+1);
1363 break;
1364 }
1365 }
1366 if (found)
1367 path->append(newpath);
1368 return found;
1369}
1370
1371
1372//_____________________________________________________________________________________
1375
1376//_____________________________________________________________________________________
1378{
1379 buffer = (char *)realloc(bufptr, size);
1380 buffer_size = size;
1381 return buffer;
1382}
1383
1384//_____________________________________________________________________________________
1386{
1387 SoOutput out;
1388 buffer = (char *)malloc(1024);
1389 buffer_size = 1024;
1390 out.setBuffer(buffer, buffer_size, buffer_realloc);
1391
1392 SoWriteAction wa(&out);
1393 wa.apply(root);
1394
1395 QString s(buffer);
1396 free(buffer);
1397 return s;
1398}
1399
1400//_____________________________________________________________________________________
1401void VP1QtInventorUtils::Imp::buffer_vrmlwriteaction(SoNode * root, const QString& filename)
1402{
1403 SoToVRML2Action vwa;
1404
1405 vwa.apply(root);
1406 SoVRMLGroup * newroot = vwa.getVRML2SceneGraph();
1407
1408 SoOutput out;
1409 out.openFile(qPrintable(filename));
1410 out.setHeaderString("#VRML V2.0 utf8");
1411 SoWriteAction wra(&out);
1412 wra.apply(newroot);
1413 out.closeFile();
1414 newroot->unref();
1415 return;
1416}
1417
1418//_____________________________________________________________________________________
1419bool VP1QtInventorUtils::writeGraphToFile(SoNode*root, const QString& filename)
1420{
1421 if (!root)
1422 return false;
1423
1424 root->ref();
1425 QString s = Imp::buffer_writeaction(root);
1426 root->unrefNoDelete();
1427
1428 QFile data(filename);
1429 if (data.open(QFile::WriteOnly | QFile::Truncate)) {
1430 QTextStream out(&data);
1431#if QTCORE_VERSION >= 0x050E00
1432 out << s << Qt::endl;
1433#else
1434 out << s << endl;
1435#endif
1436 return true;
1437 } else {
1438 return false;
1439 }
1440}
1441
1442//_____________________________________________________________________________________
1443SoSeparator* VP1QtInventorUtils::readGraphFromFile(const QString& filename)
1444{
1445 // SoDB::init();
1446 SoInput in;
1447 if (!in.openFile(filename.toStdString().c_str()))
1448 return 0;
1449 return SoDB::readAll(&in);
1450}
1451
1452
1453//_____________________________________________________________________________________
1454bool VP1QtInventorUtils::writeGraphToVRMLFile(SoNode*root, const QString& filename)
1455{
1456 if (!root)
1457 return false;
1458
1459 root->ref();
1460 Imp::buffer_vrmlwriteaction(root, filename);
1461 root->unrefNoDelete();
1462
1463 // QFile data(filename);
1464 // if (data.open(QFile::WriteOnly | QFile::Truncate)) {
1465 // QTextStream out(&data);
1466 // out << s << endl;
1467 // return true;
1468 // } else {
1469 // return false;
1470 // }
1471 return true;
1472}
1473
1474
1477//_____________________________________________________________________________________
1478void VP1QtInventorUtils::setMatColor( SoMaterial * m, const double& r, const double& g, const double& b,
1479 const double& brightness, const double& transp )
1480{
1481 if (m)
1482 VP1MaterialButton::setMaterialParameters( m, r,g,b,brightness,transp );
1483}
1484
1485//_____________________________________________________________________________________
1486void VP1QtInventorUtils::setMatColor( SoMaterial * m, const QColor& col,
1487 const double& brightness, const double& transp )
1488{
1489 setMatColor( m, col.redF(), col.greenF(), col.blueF(), brightness, transp);
1490}
1491
1492
1493//_____________________________________________________________________________________
1502
1503//_____________________________________________________________________________________
1512
1513//_____________________________________________________________________________________
1515{
1517 return;
1519 QWidget * w(0);
1520 if (!ra) {
1521 VP1Msg::messageVerbose("VP1QtInventorUtils WARNING: Have to create temporary renderarea for the sole "
1522 "purpose of getting supported line widths and point sizes!");
1523 w = new QWidget(0);
1524 ra = new VP1ExaminerViewer(w);
1525 }
1526 SbVec2f range; float granularity;
1527 ra->getLineWidthLimits(range, granularity);
1528 float a,b;
1529 range.getValue(a,b);
1533 VP1Msg::messageVerbose("VP1QtInventorUtils Determined line widths supported by hardware (min,max,granularity) = ("
1534 +VP1Msg::str(a)+", "+VP1Msg::str(b)+", "+VP1Msg::str(granularity)+")");
1535 ra->getPointSizeLimits(range, granularity);
1536 range.getValue(a,b);
1540 VP1Msg::messageVerbose("VP1QtInventorUtils Determined point sizes supported by hardware (min,max,granularity) = ("
1541 +VP1Msg::str(a)+", "+VP1Msg::str(b)+", "+VP1Msg::str(granularity)+")");
1542 if (w) {
1543 delete ra;
1544 delete w;
1545 }
1546 //We clip to get a more consistent behaviour across hardware (and to limit ourselves to reasonable values:
1547
1554 if (Imp::allowedPointSizeMax>12.0)
1556}
1557
1558//_____________________________________________________________________________________
1560{
1561 if (!slider)
1562 return;
1565 int nsteps = std::min(1000,std::max<int>(0,static_cast<int>((Imp::allowedLineWidthMax-Imp::allowedLineWidthMin)/Imp::allowedLineWidthGranularity)));
1566 int stepsPerUnit = std::min(nsteps,std::max<int>(1,static_cast<int>(1.0/Imp::allowedLineWidthGranularity)));
1567 slider->setRange(0,nsteps);
1568 slider->setSingleStep(1);
1569 slider->setPageStep(stepsPerUnit);
1570}
1571
1572//_____________________________________________________________________________________
1574{
1575 if (!slider)
1576 return;
1579 int nsteps = std::min(1000,std::max<int>(0,
1581 int stepsPerUnit = std::min(nsteps,std::max<int>(1,
1582 static_cast<int>(0.5+1.0/Imp::allowedPointSizeGranularity)));
1583 slider->setRange(0,nsteps);
1584 slider->setSingleStep(1);
1585 slider->setPageStep(stepsPerUnit);
1586}
1587
1588//_____________________________________________________________________________________
1589void VP1QtInventorUtils::setValueLineWidthSlider(QSlider * slider, const double& value)
1590{
1591 if (!slider)
1592 return;
1595 int itarget = std::min(slider->maximum(),std::max<int>(slider->minimum(),
1596 static_cast<int>(0.5+(value-Imp::allowedLineWidthMin)/Imp::allowedLineWidthGranularity)));
1597 if (slider->value()!=itarget)
1598 slider->setValue(itarget);
1599}
1600
1601//_____________________________________________________________________________________
1602void VP1QtInventorUtils::setValuePointSizeSlider(QSlider * slider, const double& value)
1603{
1604 if (!slider)
1605 return;
1608 int itarget = std::min(slider->maximum(),std::max<int>(slider->minimum(),
1609 static_cast<int>(0.5+(value-Imp::allowedPointSizeMin)/Imp::allowedPointSizeGranularity)));
1610 if (slider->value()!=itarget)
1611 slider->setValue(itarget);
1612}
1613
1614//_____________________________________________________________________________________
1616{
1617 if (!slider)
1618 return 1.0;
1621 return std::max(Imp::allowedLineWidthMin,std::min(Imp::allowedLineWidthMax,
1623}
1624
1625//_____________________________________________________________________________________
1627{
1628 if (!slider)
1629 return 1.0;
1632 return std::max(Imp::allowedPointSizeMin,std::min(Imp::allowedPointSizeMax,
1634}
#define M_PI
std::vector< size_t > vec
double length(const pvec &v)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
double coord
Type of coordination system.
static Double_t a
size_t size() const
Number of registered mappings.
const double width
#define y
#define x
#define z
C++23-compatible byteswap().
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
Header file for AthHistogramAlgorithm.
SoQtViewer::StereoType getStereoTypeSlot(void) const
virtual SoNode * getSceneGraph()
static void setMaterialParameters(SoMaterial *m, const QColor &, const double &brightness=0.0, const double &transp=0.0)
static void messageVerbose(const QString &)
Definition VP1Msg.cxx:84
static bool verbose()
Definition VP1Msg.h:31
static void messageDebug(const QString &)
Definition VP1Msg.cxx:39
static void message(const QString &, IVP1System *sys=0)
Definition VP1Msg.cxx:30
static void buffer_vrmlwriteaction(SoNode *root, const QString &filename)
static QString buffer_writeaction(SoNode *root)
static unsigned * read_texture(const char *name, int *width, int *height, int *components)
static void * buffer_realloc(void *bufptr, size_t size)
static void rgbatorgba(unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a, unsigned char *l, int n)
static double allowedPointSizeGranularity
static double allowedLineWidthGranularity
static void ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z)
static void latorgba(unsigned char *b, unsigned char *a, unsigned char *l, int n)
static void rgbtorgba(unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *l, int n)
struct VP1QtInventorUtils::Imp::_ImageRec ImageRec
static QImage constructImageWithTransparentBackground(const QImage &im_black_bgd, const QImage &image_white_bgd)
static void ImageClose(ImageRec *image)
static void bwtorgba(unsigned char *b, unsigned char *l, int n)
static void ConvertLong(unsigned *array, long length)
static ImageRec * ImageOpen(const char *fileName)
static bool writeGraphToVRMLFile(SoNode *root, const QString &filename)
static bool deserialiseSoMaterial(QByteArray &, SoMaterial *&)
static void ensureInitLineWidthAndPointSize(SoQtRenderArea *)
static QByteArray serialiseSoMaterial(SoMaterial *)
static double getValueLineWidthSlider(const QSlider *)
static QList< SoGLRenderAction::TransparencyType > getAllTransparencyTypes()
static QByteArray serialize(const SbRotation &)
static void setLimitsLineWidthSlider(QSlider *)
static void setMatColor(SoMaterial *, const double &r, const double &g, const double &b, const double &brightness=0.0, const double &transp=0.0)
static QImage imageFromRGBFile(const QString &filename)
static QPixmap renderToPixmap(VP1ExaminerViewer *ra, int pixels_x, int pixels_y, bool transparent_background=false, double actualRenderedSizeFact=1.0)
static SoGLRenderAction::TransparencyType intToTransparencyType(int)
static void getLineWidthRanges(double &min, double &max, double &granularity)
static double getValuePointSizeSlider(const QSlider *)
static QColor sbcol2qcol(const SbColor &)
static void setValuePointSizeSlider(QSlider *, const double &value)
static QByteArray serializeSoCameraParameters(const SoCamera &)
static bool writeGraphToFile(SoNode *root, const QString &filename)
static SoNode * createCircle(const double &radius)
static bool deserialize(QByteArray &, SbRotation &)
static SbColor qcol2sbcol(const QColor &)
static bool changePathTail(SoPath *path, SoNode *commonBranchPoint, SoNode *newtail)
static QString transparencyType2PrettyString(SoGLRenderAction::TransparencyType)
static void setLimitsPointSizeSlider(QSlider *)
static SoNode * createEllipse(const double &radiusX, const double &radiusY, const int &numnodes=12)
static bool deserializeSoCameraParameters(QByteArray &, SoCamera &)
static void getPointSizeRanges(double &min, double &max, double &granularity)
static void setValueLineWidthSlider(QSlider *, const double &value)
static QImage renderToImage(VP1ExaminerViewer *ra, int pixels_x, int pixels_y, bool transparent_background=false, double actualRenderedSizeFact=1.0)
static SoSeparator * readGraphFromFile(const QString &filename)
static int transparencyTypeToInt(SoGLRenderAction::TransparencyType)
static SoGLRenderAction::TransparencyType getDefaultVP1TransparencyType()
static QPixmap pixmapFromRGBFile(const QString &filename)
static QString str(const QString &s)
Definition VP1String.h:49
int r
Definition globals.cxx:22
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:148
std::string base
Definition hcg.cxx:83
constexpr T byteswap(T value) noexcept
Reverse the bytes in n.
Definition byteswap.h:42
Definition index.py:1