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