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