fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Image / OSGImageFunctions.cpp
blob94f12a69e993478e192d74648f1637708960fe70
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
8 * *
9 \*---------------------------------------------------------------------------*/
10 /*---------------------------------------------------------------------------*\
11 * License *
12 * *
13 * This library is free software; you can redistribute it and/or modify it *
14 * under the terms of the GNU Library General Public License as published *
15 * by the Free Software Foundation, version 2. *
16 * *
17 * This library is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
20 * Library General Public License for more details. *
21 * *
22 * You should have received a copy of the GNU Library General Public *
23 * License along with this library; if not, write to the Free Software *
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
25 * *
26 \*---------------------------------------------------------------------------*/
27 /*---------------------------------------------------------------------------*\
28 * Changes *
29 * *
30 * *
31 * *
32 * *
33 * *
34 * *
35 \*---------------------------------------------------------------------------*/
36 //---------------------------------------------------------------------------
37 // Includes
38 //---------------------------------------------------------------------------
40 #if __GNUC__ >= 4 || __GNUC_MINOR__ >=3
41 #pragma GCC diagnostic warning "-Wsign-compare"
42 #endif
44 #ifdef WIN32
45 #pragma warning( disable : 4018 )
46 #endif
48 #include <cstdlib>
49 #include <cstdio>
51 #include "OSGConfig.h"
52 #include "OSGLog.h"
53 #include "OSGImage.h"
54 #include "OSGBaseFunctions.h"
56 #include "OSGImageFunctions.h"
58 OSG_BEGIN_NAMESPACE
60 #if defined(OSG_WIN32_ICL) && !defined(OSG_CHECK_FIELDSETARG)
61 #pragma warning(disable : 383)
62 #endif
63 #ifdef __sgi
64 #pragma set woff 1209
65 #endif
67 /***************************************************************************\
68 * Description *
69 \***************************************************************************/
71 //---------------------------------------------------------------------------//
72 /*! composes multiple images to one */
75 //---------------------------------------------------------------------------//
76 /*! convert bumpmap to normalmap */
78 bool createNormalMapFromBump ( Image *image,
79 Image *dstImg,
80 Vec3f normalMapScale)
82 if (image == NULL || image->getDepth() > 1 ||
83 image->getPixelFormat() != Image::OSG_L_PF)
85 FFATAL(("No valid Normalmap given!\n"));
86 return false;
89 bool cpImg = false;
91 ImageUnrecPtr dst;
93 if(dstImg == NULL)
95 dst = Image::create();
96 cpImg = true;
98 else
100 dst = dstImg;
103 Int32 w = image->getWidth();
104 Int32 h = image->getHeight();
106 const unsigned char *srcData = image->getData();
108 dst->set(Image::OSG_RGB_PF, w, h);
110 unsigned char *dstData = dst->editData();
112 Vec3f scale(normalMapScale);
114 if (scale[0] == 0.0f || scale[1] == 0.0f || scale[2] == 0.0f)
116 Real32 a = Real32(w) / Real32(h);
118 if(a < 1.0f)
120 scale[0] = 1.0f;
121 scale[1] = 1.0f / a;
123 else
125 scale[0] = a;
126 scale[1] = 1.0f;
128 scale[2] = 1.0f;
131 Int32 i, j;
133 for (i=1; i<w-1; i++)
135 for (j=1; j<h-1; j++)
137 Vec3f dfdi(2.0f, 0.0f, Real32(srcData[(i+1) + j*w] - srcData[(i-1) + j*w]) / 255.0f);
138 Vec3f dfdj(0.0f, 2.0f, Real32(srcData[ i + (j+1)*w] - srcData[ i + (j-1)*w]) / 255.0f);
139 Vec3f n = dfdi.cross(dfdj);
141 n[0] *= scale[0];
142 n[1] *= scale[1];
143 n[2] *= scale[2];
144 n.normalize();
146 dstData[(j*w+i)*3+0] = UInt8((n[0]+1)*127.5);
147 dstData[(j*w+i)*3+1] = UInt8((n[1]+1)*127.5);
148 dstData[(j*w+i)*3+2] = UInt8((n[2]+1)*127.5);
152 // handle image border
153 for (i=0; i<w; i++)
155 dstData[i*3+0] = dstData[(w+i)*3+0];
156 dstData[i*3+1] = dstData[(w+i)*3+1];
157 dstData[i*3+2] = dstData[(w+i)*3+2];
159 dstData[((h-1)*w+i)*3+0] = dstData[((h-2)*w+1)*3+0];
160 dstData[((h-1)*w+i)*3+1] = dstData[((h-2)*w+1)*3+1];
161 dstData[((h-1)*w+i)*3+2] = dstData[((h-2)*w+1)*3+2];
164 for (j=0; j<h; j++)
166 dstData[(j*w)*3+0] = dstData[(j*w+1)*3+0];
167 dstData[(j*w)*3+1] = dstData[(j*w+1)*3+1];
168 dstData[(j*w)*3+2] = dstData[(j*w+1)*3+2];
170 dstData[(j*w+(w-1))*3+0] = dstData[(j*w+(w-2))*3+0];
171 dstData[(j*w+(w-1))*3+1] = dstData[(j*w+(w-2))*3+1];
172 dstData[(j*w+(w-1))*3+2] = dstData[(j*w+(w-2))*3+2];
175 if (cpImg)
177 image->set(dst);
180 //dst->dump();
182 return true;
186 //---------------------------------------------------------------------------//
187 /*! creates a Normal Volume from the given data */
189 bool createNormalVolume ( Image *inImage,
190 Image *outImage,
191 const std::string &outputFormat)
193 const Real32 gMax = 441.67295593f, gF = 255.0f/gMax;
194 // const OSG::Real32 TwoPi = 2 * OSG::Pi;
196 enum DataIndex { SCALAR_DI,
197 SCALAR_NULLEDGE_DI,
198 X_DI, Y_DI, Z_DI,
199 GRADIENT_DI,
200 THETA_DI, PHI_DI,
202 END_DI
205 const UInt8 *data = 0;
206 UInt8 *ds;
207 OSG::Real32 minU = OSG::Inf, maxU = -OSG::Inf;
208 OSG::Real32 minV = OSG::Inf, maxV = -OSG::Inf;
209 Int32 w, h, d, x, y, z, md, ld, hd, xs, ys, zs, ps, ls, ss, os;
210 SizeT i,voxelSize;
211 std::vector<UInt32> dataIndex;
212 Real32 u, v, length;
213 Vec3f normal;
214 ImageUnrecPtr copy;
215 Image::PixelFormat pf;
216 bool calcGradient = false, calcThetaPhi = false;
217 char validFormat[END_DI];
218 UInt8 voxelData[sizeof(validFormat)];
219 char *formatP;
220 bool isEdge;
222 // init valid format string
223 validFormat[SCALAR_DI] = 's';
224 validFormat[SCALAR_NULLEDGE_DI] = 'S';
225 validFormat[X_DI] = 'x';
226 validFormat[Y_DI] = 'y';
227 validFormat[Z_DI] = 'z';
228 validFormat[GRADIENT_DI] = 'g';
229 validFormat[THETA_DI] = 't';
230 validFormat[PHI_DI] = 'p';
232 if(inImage == NULL || outImage == NULL)
234 return false;
237 // check if we have a valid input image
238 if ( inImage->getBpp() != 1 ) {
240 copy = Image::create();
241 FLOG (("Create copy to reformat/convert Image\n"));
243 if ( (inImage->getPixelFormat() == Image::OSG_L_PF) ||
244 (inImage->getPixelFormat() == Image::OSG_L_PF) )
245 copy->set(inImage);
246 else
247 inImage->reformat(Image::OSG_L_PF,copy);
248 inImage = copy;
250 if (inImage->getDataType() != Image::OSG_UINT8_IMAGEDATA)
251 inImage->convertDataTypeTo(Image::OSG_UINT8_IMAGEDATA);
254 switch (outputFormat.size()) {
255 case 1:
256 pf = Image::OSG_L_PF;
257 break;
258 case 2:
259 pf = Image::OSG_LA_PF;
260 break;
261 case 3:
262 pf = Image::OSG_RGB_PF;
263 break;
264 case 4:
265 pf = Image::OSG_RGBA_PF;
266 break;
267 default:
268 FFATAL(( "Invalid outputFormat length in createNormalVolume: %"
269 PRISize "\n",
270 outputFormat.size() ));
271 return false;
274 // get image data and parameter
275 w = inImage->getWidth();
276 h = inImage->getHeight();
277 d = inImage->getDepth();
278 data = inImage->getData();
279 ps = inImage->getBpp();
280 ls = ps * w;
281 ss = ls * h;
282 os = 0;
284 // check format string and fill dataIndex
285 voxelSize = outputFormat.size();
286 dataIndex.resize(voxelSize);
287 for (i = 0; i < voxelSize; i++) {
288 if ((formatP = strchr(validFormat, outputFormat[i]))) {
289 dataIndex[i] = (formatP - validFormat);
290 switch (dataIndex[i]) {
291 case GRADIENT_DI:
292 calcGradient = true;
293 break;
294 case THETA_DI:
295 case PHI_DI:
296 calcThetaPhi = true;
297 break;
299 FDEBUG (( "dataIndex[%" PRISize "]: %d\n", i, dataIndex[i] ));
301 else {
302 FFATAL (( "Invalid outputFormat element %c, valid: %s\n",
303 char(outputFormat[i]), validFormat ));
304 return false;
308 // create output image
309 outImage->set( pf, w, h, d );
311 ds = outImage->editData();
313 // fill output image
314 for (z = 0; z < d; z++) {
315 for (y = 0; y < h; y++) {
316 for (x = 0; x < w; x++) {
317 isEdge = false;
319 md = data[(x*ps) + (y*ls) + (z*ss) + os];
321 // calc xs
322 if (x > 0)
323 ld = data[((x-1)*ps) + (y*ls) + (z*ss) + os];
324 else {
325 isEdge |= true;
326 ld = 0;
328 if (x < (w-1))
329 hd = data[((x+1)*ps) + (y*ls) + (z*ss) + os];
330 else {
331 isEdge |= true;
332 hd = 0;
334 xs = (ld - hd);
336 // calc ys
337 if (y > 0)
338 ld = data[(x*ps) + ((y-1)*ls) + (z*ss) + os];
339 else {
340 isEdge |= true;
341 ld = 0;
343 if (y < (h-1))
344 hd = data[(x*ps) + ((y+1)*ls) + (z*ss) + os];
345 else {
346 isEdge |= true;
347 hd = 0;
349 ys = (ld - hd);
351 // cals zs
352 if (z > 0)
353 ld = data[(x*ps) + (y*ls) + ((z-1)*ss) + os];
354 else {
355 isEdge |= true;
356 ld = 0;
358 if (z < (d-1))
359 hd = data[(x*ps) + (y*ls) + ((z+1)*ss) + os];
360 else {
361 isEdge |= true;
362 hd = 0;
364 zs = (ld - hd);
366 // set the voxel data
367 voxelData[SCALAR_DI] = md;
368 voxelData[SCALAR_NULLEDGE_DI] = isEdge ? 0 : md;
369 voxelData[X_DI] = xs / 2 + 127;
370 voxelData[Y_DI] = ys / 2 + 127;
371 voxelData[Z_DI] = zs / 2 + 127;
373 // calc normal
374 if (calcGradient || calcThetaPhi) {
375 normal.setValues (xs,ys,zs);
376 length = normal.length();
377 normal.normalize();
380 // calc gradient
381 if (calcGradient) {
382 voxelData[GRADIENT_DI] = osgMax ( int (length * gF), 255 );
385 // calc ThetaPhi
386 if (calcThetaPhi) {
387 v = OSG::osgACos(normal[2]) / OSG::Pi;
388 u = OSG::osgSqrt(normal[0]*normal[0] + normal[1]*normal[1]);
390 if (u) u = normal[0] / u;
391 u = OSG::osgACos(u);
392 if (normal[1]<0) u = TwoPi - u;
393 u /= TwoPi;
395 if (u<minU) minU=u;
396 if (u>maxU) maxU=u;
397 if (v<minV) minV=v;
398 if (v>maxV) maxV=v;
400 voxelData[THETA_DI] = UInt8(v * 255.f); // theta
401 voxelData[PHI_DI] = UInt8(u * 255.f); // phi
404 // copy voxeldata to image data
405 for (i = 0; i < voxelSize; i++)
406 *ds++ = voxelData[dataIndex[i]];
412 return true;
416 //---------------------------------------------------------------------------//
417 /*! create pre-integrated lookup table
418 code based on the "Truly Volumetric Effects" (Martin Kraus)
419 example in the ShaderX book (www.shaderx.com)
422 bool create2DPreIntegrationLUT ( Image *dst,
423 Image *src,
424 Real32 thickness)
426 if (src == NULL || dst == NULL ||
427 src->getHeight() > 1 || src->getDepth() > 1 ||
428 src->getPixelFormat() != Image::OSG_RGBA_PF)
430 FFATAL(("No appropriate image given!\n"));
431 return false;
434 const unsigned char *dataSrc = src->getData();
435 UInt32 width = src->getWidth();
437 dst->set(Image::OSG_RGBA_PF, width, width);
439 unsigned char *dataDst = dst->editData();
441 for (Int32 x = 0; x < Int32(width); x++)
443 for (Int32 y = 0; y < Int32(width); y++)
445 Int32 n = 10 + 2 * abs(x-y);
446 Real64 step = thickness / n;
448 Real64 dr = 0.0,
449 dg = 0.0,
450 db = 0.0,
451 dtau = 0.0;
453 for (Int32 i = 0; i < n; i++)
455 Real64 w = x + (y-x) * Real64(i)/n;
457 if (Int32(w + 1) >= Int32(width))
458 w = Real64(width - 1) - 0.5/n;
460 Int32 pos = (Int32(w)) * 4;
462 Real64 e = exp(-dtau), scale = step * (1.0 / 255.0),
463 f = w - floor(w), invF = 1 - f;
465 Real64 tau = scale * (dataSrc[pos + 3] * f + dataSrc[pos+4 + 3] * invF);
466 Real64 r = e * scale * (dataSrc[pos + 0] * f + dataSrc[pos+4 + 0] * invF);
467 Real64 g = e * scale * (dataSrc[pos + 1] * f + dataSrc[pos+4 + 1] * invF);
468 Real64 b = e * scale * (dataSrc[pos + 2] * f + dataSrc[pos+4 + 2] * invF);
470 dr += r;
471 dg += g;
472 db += b;
473 dtau += tau;
476 dataDst[(x*width+y)*4+0] = UInt8((dr > 1.0 ? 1.0 : dr)*255);
477 dataDst[(x*width+y)*4+1] = UInt8((dg > 1.0 ? 1.0 : dg)*255);
478 dataDst[(x*width+y)*4+2] = UInt8((db > 1.0 ? 1.0 : db)*255);
479 dataDst[(x*width+y)*4+3] = UInt8((1.0 - exp(-dtau))*255);
483 //dst->dump();
485 return true;
489 //---------------------------------------------------------------------------//
490 /*! split RGBA images into RGB and A */
492 bool splitRGBA(Image *rgba,
493 Image *rgb,
494 Image *alpha)
496 if (rgba == NULL || rgba->getDepth() > 1 ||
497 rgba->getPixelFormat() != Image::OSG_RGBA_PF)
499 FFATAL(("No appropriate image given!\n"));
500 return false;
503 if(rgb == NULL || alpha == NULL)
505 FFATAL(("No appropriate target given!\n"));
506 return false;
509 Int32 w = rgba->getWidth();
510 Int32 h = rgba->getHeight();
512 rgb->set(Image::OSG_RGB_PF, w, h);
513 alpha->set(Image::OSG_L_PF, w, h);
515 unsigned char *data = rgb->editData();
516 const unsigned char *dataRgba = rgba->getData();
517 unsigned char *dataAlpha = alpha->editData();
519 for (Int32 i=0; i<(w * h); i++)
521 data[0] = dataRgba[0];
522 data[1] = dataRgba[1];
523 data[2] = dataRgba[2];
524 dataAlpha[0] = dataRgba[3];
526 data += 3;
527 dataRgba += 4;
528 dataAlpha++;
531 //rgb->dump();
532 //alpha->dump();
534 return true;
537 //---------------------------------------------------------------------------//
538 /*! merge RGB and A images into RGBA */
540 bool mergeRGBA(Image *rgb,
541 Image *alpha,
542 Image *rgba)
544 if (rgb == NULL || alpha == NULL ||
545 rgb->getDepth() > 1 || alpha->getDepth() > 1 ||
546 rgb->getPixelFormat() != Image::OSG_RGB_PF ||
547 alpha->getPixelFormat() != Image::OSG_L_PF)
549 FFATAL(("No appropriate images given!\n"));
550 return false;
553 if(rgba == NULL)
555 FFATAL(("No appropriate target given!\n"));
556 return false;
560 Int32 w = rgb->getWidth();
561 Int32 h = rgb->getHeight();
563 if (w != alpha->getWidth() || h != alpha->getHeight())
565 FFATAL(("Colour and Alpha Images must be of same size!\n"));
566 return false;
569 rgba->set(Image::OSG_RGBA_PF, w, h);
571 unsigned char *data = rgba->editData();
572 const unsigned char *dataRgb = rgb->getData();
573 const unsigned char *dataAlpha = alpha->getData();
575 for (Int32 i=0; i<(w * h); i++)
577 data[0] = dataRgb[0];
578 data[1] = dataRgb[1];
579 data[2] = dataRgb[2];
580 data[3] = *dataAlpha;
581 data += 4;
582 dataRgb += 3;
583 dataAlpha++;
586 //rgba->dump();
588 return true;
591 //---------------------------------------------------------------------------//
592 /*! blend the brush on the canvas image */
594 bool blendImage ( Image *canvas,
595 Image *brush,
596 Vec3f position,
597 Color4f color,
598 Real32 alphaScale,
599 Real32 paintZ )
601 int x,y,z;
602 int red = 0, green = 0, blue = 0, grey = 0;
603 int alpha = 0;
604 const UChar8 *s = 0;
605 UInt8 *d = 0;
607 if(canvas == NULL || brush == NULL)
609 FFATAL(("No appropriate images given!\n"));
610 return false;
613 const OSG::UChar8 *src = brush->getData();
614 OSG::UChar8 *dest = canvas->editData();
616 const float cred = color.red();
617 const float cgreen = color.green();
618 const float cblue = color.blue();
619 const float calpha = color.alpha();
620 const float talpha = alphaScale;
622 const int cPF = canvas->getPixelFormat();
623 const int bPF = brush->getPixelFormat();
625 const int cBpp = canvas->getBpp();
626 const int bBpp = brush->getBpp();
628 const int bW = brush->getWidth();
629 const int bH = brush->getHeight();
630 const int bD = brush->getDepth();
632 const int cW = canvas->getWidth();
633 const int cH = canvas->getHeight();
634 const int cD = canvas->getDepth();
636 const int xcOff = int(position.x());
637 const int ycOff = int(position.y());
638 const int zcOff = int(position.z());
640 // canvas->setSubData (xcOff,ycOff,zcOff,bW,bH,bD,src);
642 const int xcMin = OSG::osgMax(0, xcOff);
643 const int ycMin = OSG::osgMax(0, ycOff);
644 const int zcMin = OSG::osgMax(0, zcOff);
646 const int xcMax = OSG::osgMin(cW, xcOff + bW);
647 const int ycMax = OSG::osgMin(cH, ycOff + bH);
648 const int zcMax = OSG::osgMin(cD, zcOff + bD);
650 const int width = (xcMax - xcMin);
651 const int height = (ycMax - ycMin);
652 const int depth = (zcMax - zcMin);
654 int xbMin = xcOff < 0 ? -xcOff : 0;
655 int ybMin = ycOff < 0 ? -ycOff : 0;
656 int zbMin = zcOff < 0 ? -zcOff : 0;
658 //select slice for volume brush
659 if ((bD > 1) && (depth == 1)) {
660 z = int(OSG::osgAbs(paintZ) * (bD - 1)) % bD;
661 src += bW * bH * bBpp * z;
662 zbMin = 0;
665 for (z = 0; z < depth; z++) {
666 for (y = 0; y < height; y++){
667 d = dest + ( ((z+zcMin) * cH + (y+ycMin)) * cW + xcMin) * cBpp;
668 s = src + ( ((z+zbMin) * bH + (y+ybMin)) * bW + xbMin) * bBpp;
669 for (x = 0; x < width; x++) {
670 switch ( bPF ) {
671 case OSG::Image::OSG_A_PF:
672 case OSG::Image::OSG_I_PF:
673 grey = *s++;
674 red = int(cred * grey);
675 green = int(cgreen * grey);
676 blue = int(cblue * grey);
677 alpha = int(calpha * grey);
678 break;
679 case OSG::Image::OSG_L_PF:
680 grey = *s++;
681 red = int(cred * grey);
682 green = int(cgreen * grey);
683 blue = int(cblue * grey);
684 alpha = int(calpha * 255);
685 break;
686 case OSG::Image::OSG_LA_PF:
687 grey = *s++;
688 red = int(cred * grey);
689 green = int(cgreen * grey);
690 blue = int(cblue * grey);
691 alpha = int(calpha * *s++);
692 break;
693 case OSG::Image::OSG_RGB_PF:
694 red = int(cred * *s++);
695 green = int(cgreen * *s++);
696 blue = int(cblue * *s++);
697 grey = green; // FIXME
698 alpha = 255;
699 break;
700 case OSG::Image::OSG_RGBA_PF:
701 red = int(cred * *s++);
702 green = int(cgreen * *s++);
703 blue = int(cblue * *s++);
704 grey = green; // FIXME
705 alpha = int(calpha * *s++);
706 break;
707 default:
708 FFATAL (("Invalid Brush PixelFormat\n"));
709 brush->dump();
710 return false;
712 alpha = int(talpha * alpha);
713 switch ( cPF ) {
714 case OSG::Image::OSG_I_PF:
715 *d = int(*d * (alpha - 255) + grey * alpha) / 255;
716 ++d;
717 break;
718 case OSG::Image::OSG_L_PF:
719 *d = int(*d * (alpha - 255) + grey * alpha) / 255;
720 ++d;
721 break;
722 case OSG::Image::OSG_LA_PF:
723 *d = int(*d * (alpha - 255) + grey * alpha) / 255;
724 ++d;
725 ++d;
726 break;
727 case OSG::Image::OSG_RGB_PF:
728 *d = int(*d * (255 - alpha) + red * alpha) / 255;
729 ++d;
730 *d = int(*d * (255 - alpha) + green * alpha) / 255;
731 ++d;
732 *d = int(*d * (255 - alpha) + blue * alpha) / 255;
733 ++d;
734 break;
735 case OSG::Image::OSG_RGBA_PF:
736 *d = int(*d * (255 - alpha) + red * alpha) / 255;
737 ++d;
738 *d = int(*d * (255 - alpha) + green * alpha) / 255;
739 ++d;
740 *d = int(*d * (255 - alpha) + blue * alpha) / 255;
741 ++d;
742 ++d;
743 break;
744 default:
745 FFATAL (("Invalid Canvas PixelFormat\n"));
746 canvas->dump();
747 return false;
753 return true;
756 //---------------------------------------------------------------------------//
757 /*! create phong texture */
759 bool createPhongTexture(Image *image,
760 UInt32 size,
761 Real32 specular_exponent,
762 Real32 ka,
763 Real32 kd,
764 Real32 ks)
766 if(image == NULL)
768 FFATAL(("No appropriate target given!\n"));
769 return false;
772 image->set(Image::OSG_L_PF, size, size);
773 unsigned char *textureMap = image->editData();
775 UInt32 i, j, index = 0;
776 Real32 x = 0, y = 0;
778 Real32 specular_factor, diffuse_factor;
779 Real32 textureRadius = 0.95f;
780 Real32 textureStep = (2.0 * textureRadius) / Real32(size-1);
782 y = - textureRadius;
783 for (j=0; j<size; j++)
785 x = -textureRadius;
786 for (i=0; i<size; i++)
788 diffuse_factor = sqrt(1.0 - x * x);
789 specular_factor = pow( diffuse_factor * sqrt (1.0f - y * y) - x * y,
790 specular_exponent );
791 textureMap[index++] = UInt8((ka + kd * diffuse_factor + ks * specular_factor) * 255);
792 x += textureStep;
794 y += textureStep;
797 //image->dump();
799 return true;
802 //---------------------------------------------------------------------------//
803 /*! create phong Volume */
805 bool createPhongVolume ( Image *image,
806 Color3f diffuseColor,
807 Color3f specularColor,
808 UInt32 lutSize,
809 UInt32 lutScalar,
810 Real32 lutIncr )
812 const OSG::Int32 lutFSize = lutSize / lutScalar;
813 OSG::Real32 theta1, theta2, dPhi, incr = lutScalar * lutIncr;
814 OSG::Real32 Const = 0.2f, Shi = 40, NdotL;
815 OSG::Vec3f color;
816 OSG::Vec3f diffuse (diffuseColor[0],diffuseColor[1],diffuseColor[2]);
817 OSG::Vec3f specular (specularColor[0],specularColor[1],specularColor[2]);
818 OSG::UInt8 *ds;
819 OSG::Real32 min = OSG::Inf, max = -OSG::Inf;
821 if(image == NULL)
823 FFATAL(("No appropriate target given!\n"));
824 return false;
827 image->set( OSG::Image::OSG_RGB_PF, lutFSize, lutFSize, lutFSize );
829 ds = image->editData();
831 FDEBUG (("calc phong map START\n"));
833 for (dPhi=0; dPhi<360; dPhi+=incr) {
834 for (theta1=0; theta1<180; theta1+=incr) {
835 for (theta2=0; theta2<180; theta2+=incr) {
836 OSG::Real32 t1 = OSG::osgDegree2Rad(theta1),
837 t2 = OSG::osgDegree2Rad(theta2),
838 dp = OSG::osgDegree2Rad(dPhi);
839 NdotL = OSG::osgSin(t1)*OSG::osgSin(t2)*OSG::osgCos(dp) +
840 OSG::osgCos(t1)*OSG::osgCos(t2);
841 NdotL = (NdotL >= 0) ? NdotL : 0;
842 color = diffuse * (NdotL + Const) +
843 specular * OSG::osgPow(NdotL, Shi);
845 for (int i=0; i<3; i++) {
846 if (min>color[i]) min=color[i];
847 if (max<color[i]) max=color[i];
849 color[i] = OSG::osgClamp(0.f, (color[i]), 1.f);
850 *ds++ = UInt8(color[i]*255);
857 FDEBUG (( "calc phong map FINISH: clamped from [%f,%f] to [0,1]\n",
858 min, max));
860 return true;
864 //---------------------------------------------------------------------------//
865 /*! create normalization cube map */
867 bool createNormalizationCubeMap(std::vector<Image *> imageVec,
868 UInt32 size)
870 UInt32 i, j;
872 if (imageVec.size() < 6)
874 FFATAL(("Only %" PRISize " images given - need six\n",
875 imageVec.size()));
876 return false;
879 for (i=0; i<6; i++)
881 if (imageVec[i] == NULL)
883 FFATAL(("Image[%d] is Null\n", i));
884 return false;
888 unsigned char *data = NULL;
889 Vec3f n;
891 size = osgNextPower2(size);
893 float size2 = size / 2.0f;
894 float offset = 0.5f;
896 Image *imagePosX = imageVec[0];
898 // pos x
899 imagePosX->set(Image::OSG_RGB_PF, size, size);
900 data = imagePosX->editData();
902 for (j=0; j<size; j++) {
903 for (i=0; i<size; i++) {
905 n[0] = size2;
906 n[1] = -(Real32(j) + offset - size2);
907 n[2] = -(Real32(i) + offset - size2);
908 n.normalize();
910 data[0] = UInt8(((n.x() + 1.f) / 2.f) * 255.f);
911 data[1] = UInt8(((n.y() + 1.f) / 2.f) * 255.f);
912 data[2] = UInt8(((n.z() + 1.f) / 2.f) * 255.f);
913 data += 3;
917 Image *imageNegX = imageVec[1];
919 // neg x
920 imageNegX->set(Image::OSG_RGB_PF, size, size);
921 data = imageNegX->editData();
923 for (j=0; j<size; j++) {
924 for (i=0; i<size; i++) {
926 n[0] = -size2;
927 n[1] = -(Real32(j) + offset - size2);
928 n[2] = (Real32(i) + offset - size2);
929 n.normalize();
931 data[0]= UInt8(((n.x() + 1.f) / 2.f) * 255.f);
932 data[1]= UInt8(((n.y() + 1.f) / 2.f) * 255.f);
933 data[2]= UInt8(((n.z() + 1.f) / 2.f) * 255.f);
934 data += 3;
938 Image *imagePosY = imageVec[2];
940 // pos y
941 imagePosY->set(Image::OSG_RGB_PF, size, size);
942 data = imagePosY->editData();
944 for (j=0; j<size; j++) {
945 for (i=0; i<size; i++) {
947 n[0] = (Real32(i) + offset - size2);
948 n[1] = size2;
949 n[2] = (Real32(j) + offset - size2);
950 n.normalize();
952 data[0]= UInt8(((n.x() + 1.f) / 2.f) * 255.f);
953 data[1]= UInt8(((n.y() + 1.f) / 2.f) * 255.f);
954 data[2]= UInt8(((n.z() + 1.f) / 2.f) * 255.f);
955 data += 3;
959 Image *imageNegY = imageVec[3];
961 // neg y
962 imageNegY->set(Image::OSG_RGB_PF, size, size);
963 data = imageNegY->editData();
965 for (j=0; j<size; j++) {
966 for (i=0; i<size; i++) {
968 n[0]= (Real32(i) + offset - size2);
969 n[1]= -size2;
970 n[2]= -(Real32(j) + offset - size2);
971 n.normalize();
973 data[0] = UInt8(((n.x() + 1.f) / 2.f) * 255.f);
974 data[1] = UInt8(((n.y() + 1.f) / 2.f) * 255.f);
975 data[2] = UInt8(((n.z() + 1.f) / 2.f) * 255.f);
976 data += 3;
980 Image *imagePosZ = imageVec[4];
982 // pos z
983 imagePosZ->set(Image::OSG_RGB_PF, size, size);
984 data = imagePosZ->editData();
986 for (j=0; j<size; j++) {
987 for (i=0; i<size; i++) {
989 n[0] = (Real32(i) + offset - size2);
990 n[1] = -(Real32(j) + offset - size2);
991 n[2] = size2;
992 n.normalize();
994 data[0] = UInt8(((n.x() + 1.f) / 2.f) * 255.f);
995 data[1] = UInt8(((n.y() + 1.f) / 2.f) * 255.f);
996 data[2] = UInt8(((n.z() + 1.f) / 2.f) * 255.f);
997 data += 3;
1001 Image *imageNegZ = imageVec[5];
1003 //negz
1004 imageNegZ->set(Image::OSG_RGB_PF, size, size);
1005 data = imageNegZ->editData();
1007 for (j=0; j<size; j++) {
1008 for (i=0; i<size; i++) {
1010 n[0] = -(Real32(i) + offset - size2);
1011 n[1] = -(Real32(j) + offset - size2);
1012 n[2] = -size2;
1013 n.normalize();
1015 data[0] = UInt8(((n.x() + 1.f) / 2.f) * 255.f);
1016 data[1] = UInt8(((n.y() + 1.f) / 2.f) * 255.f);
1017 data[2] = UInt8(((n.z() + 1.f) / 2.f) * 255.f);
1018 data += 3;
1022 return true;
1026 //---------------------------------------------------------------------------//
1027 /*! Noise code; first some helpers */
1029 /************************************************************************
1031 * Copyright (C) 2002-2004 3Dlabs Inc. Ltd. *
1033 * All rights reserved. *
1035 * Redistribution and use in source and binary forms, with or without *
1036 * modification, are permitted provided that the following conditions *
1037 * are met: *
1039 * Redistributions of source code must retain the above copyright *
1040 * notice, this list of conditions and the following disclaimer. *
1042 * Redistributions in binary form must reproduce the above *
1043 * copyright notice, this list of conditions and the following *
1044 * disclaimer in the documentation and/or other materials provided *
1045 * with the distribution. *
1047 * Neither the name of 3Dlabs Inc. Ltd. nor the names of its *
1048 * contributors may be used to endorse or promote products derived *
1049 * from this software without specific prior written permission. *
1051 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
1052 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
1053 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
1054 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
1055 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
1056 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
1057 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *
1058 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *
1059 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *
1060 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
1061 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
1062 * POSSIBILITY OF SUCH DAMAGE. *
1064 ************************************************************************/
1066 namespace
1069 // globals
1070 #define MAXB 0x100
1072 Int32 p[MAXB + MAXB + 2];
1073 Real32 g3[MAXB + MAXB + 2][3];
1074 Real32 g2[MAXB + MAXB + 2][2];
1075 Real32 g1[MAXB + MAXB + 2];
1076 Int32 start = 1;
1077 Int32 B = 0x100;
1078 Int32 BM = 0xff;
1081 void setNoiseFrequency(Int32 frequency)
1083 start = 1;
1084 B = frequency;
1085 BM = B-1;
1088 Real32 lerp(Real32 t, Real32 a, Real32 b)
1090 return (1 - t) * a + t * b;
1093 Real32 sCurve(Real32 t)
1095 return t * t * (3.0f - 2.0f * t);
1098 Real32 at2(Real32 *q, Real32 rx, Real32 ry)
1100 return rx * q[0] + ry * q[1];
1103 Real32 at3(Real32 *q, Real32 rx, Real32 ry, Real32 rz)
1105 return rx * q[0] + ry * q[1] + rz * q[2];
1108 void setup(Real32 *vec, UInt8 i,
1109 Real32 &t,
1110 Int32 &b0, Int32 &b1,
1111 Real32 &r0, Real32 &r1)
1113 t = vec[i] + 0x1000;
1114 b0 = (Int32(t)) & BM;
1115 b1 = (b0 + 1) & BM;
1116 r0 = t - Int32(t);
1117 r1 = r0 - 1.0f;
1120 void normalize2(Real32 v[2])
1122 Real32 s = sqrt(v[0] * v[0] + v[1] * v[1]);
1123 v[0] = v[0] / s;
1124 v[1] = v[1] / s;
1127 void normalize3(Real32 v[3])
1129 Real32 s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
1130 v[0] = v[0] / s;
1131 v[1] = v[1] / s;
1132 v[2] = v[2] / s;
1135 void init(void)
1137 Int32 i, j, k;
1139 srand(30757);
1140 for (i = 0 ; i < B ; i++)
1142 p[i] = i;
1143 g1[i] = Real32((rand() % (B + B)) - B) / B;
1145 for (j = 0 ; j < 2 ; j++)
1146 g2[i][j] = Real32((rand() % (B + B)) - B) / B;
1147 normalize2(g2[i]);
1149 for (j = 0 ; j < 3 ; j++)
1150 g3[i][j] = Real32((rand() % (B + B)) - B) / B;
1151 normalize3(g3[i]);
1154 while (--i)
1156 k = p[i];
1157 p[i] = p[j = rand() % B];
1158 p[j] = k;
1161 for (i = 0 ; i < B + 2 ; i++)
1163 p[B + i] = p[i];
1164 g1[B + i] = g1[i];
1165 for (j = 0 ; j < 2 ; j++)
1166 g2[B + i][j] = g2[i][j];
1167 for (j = 0 ; j < 3 ; j++)
1168 g3[B + i][j] = g3[i][j];
1172 Real32 noise1(Real32 vec[1])
1174 Int32 bx0, bx1;
1175 Real32 rx0, rx1, sx, t, u, v;
1177 if (start)
1179 start = 0;
1180 init();
1183 setup(vec, 0, t, bx0, bx1, rx0, rx1);
1185 sx = sCurve(rx0);
1187 u = rx0 * g1[ p[ bx0 ] ];
1188 v = rx1 * g1[ p[ bx1 ] ];
1190 return lerp(sx, u, v);
1193 Real32 noise2(Real32 vec[2])
1195 Int32 bx0, bx1, by0, by1, b00, b10, b01, b11;
1196 Real32 rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
1197 Int32 i, j;
1199 if (start)
1201 start = 0;
1202 init();
1205 setup(vec, 0, t, bx0, bx1, rx0, rx1);
1206 setup(vec, 1, t, by0, by1, ry0, ry1);
1208 i = p[ bx0 ];
1209 j = p[ bx1 ];
1211 b00 = p[ i + by0 ];
1212 b10 = p[ j + by0 ];
1213 b01 = p[ i + by1 ];
1214 b11 = p[ j + by1 ];
1216 sx = sCurve(rx0);
1217 sy = sCurve(ry0);
1219 q = g2[ b00 ] ; u = at2(q, rx0,ry0);
1220 q = g2[ b10 ] ; v = at2(q, rx1,ry0);
1221 a = lerp(sx, u, v);
1223 q = g2[ b01 ] ; u = at2(q, rx0,ry1);
1224 q = g2[ b11 ] ; v = at2(q, rx1,ry1);
1225 b = lerp(sx, u, v);
1227 return lerp(sy, a, b);
1230 Real32 noise3(Real32 vec[3])
1232 Int32 bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
1233 Real32 rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
1234 Int32 i, j;
1236 if (start)
1238 start = 0;
1239 init();
1242 setup(vec, 0, t, bx0, bx1, rx0, rx1);
1243 setup(vec, 1, t, by0, by1, ry0, ry1);
1244 setup(vec, 2, t, bz0, bz1, rz0, rz1);
1246 i = p[ bx0 ];
1247 j = p[ bx1 ];
1249 b00 = p[ i + by0 ];
1250 b10 = p[ j + by0 ];
1251 b01 = p[ i + by1 ];
1252 b11 = p[ j + by1 ];
1254 t = sCurve(rx0);
1255 sy = sCurve(ry0);
1256 sz = sCurve(rz0);
1258 q = g3[ b00 + bz0 ] ; u = at3(q, rx0,ry0,rz0);
1259 q = g3[ b10 + bz0 ] ; v = at3(q, rx1,ry0,rz0);
1260 a = lerp(t, u, v);
1262 q = g3[ b01 + bz0 ] ; u = at3(q, rx0,ry1,rz0);
1263 q = g3[ b11 + bz0 ] ; v = at3(q, rx1,ry1,rz0);
1264 b = lerp(t, u, v);
1266 c = lerp(sy, a, b);
1268 q = g3[ b00 + bz1 ] ; u = at3(q, rx0,ry0,rz1);
1269 q = g3[ b10 + bz1 ] ; v = at3(q, rx1,ry0,rz1);
1270 a = lerp(t, u, v);
1272 q = g3[ b01 + bz1 ] ; u = at3(q, rx0,ry1,rz1);
1273 q = g3[ b11 + bz1 ] ; v = at3(q, rx1,ry1,rz1);
1274 b = lerp(t, u, v);
1276 d = lerp(sy, a, b);
1278 return lerp(sz, c, d);
1281 Real32 noise(Real32 vec[], Int32 len)
1283 // noise functions over 1, 2, and 3 dimensions
1284 switch (len)
1286 case 1: return noise1(vec);
1287 case 2: return noise2(vec);
1288 case 3: return noise3(vec);
1289 case 0:
1290 default: return 0.0f;
1297 /*! create a noise texture.
1298 Based on code my
1301 bool createNoise(Image *image,
1302 Image::PixelFormat pixelformat,
1303 UInt16 numOctaves,
1304 UInt16 size,
1305 UInt8 dim,
1306 bool splitOctaves)
1308 Int32 f, i, j, k, c, w, h, frequency = 4;
1309 Real32 ni[3], amp = 0.5, inci, incj, inck;
1310 unsigned char *data, *ptr = NULL;
1311 bool ok = true;
1313 if (image == NULL)
1315 FFATAL (("No output image given\n"));
1316 return false;
1319 switch (dim)
1321 case 1:
1322 ok = image->set(pixelformat, size);
1323 w = h = 1;
1324 break;
1325 case 2:
1326 ok = image->set(pixelformat, size, size);
1327 w = size;
1328 h = 1;
1329 break;
1330 case 3:
1331 ok = image->set(pixelformat, size, size, size);
1332 w = h = size;
1333 break;
1334 default:
1335 ok = image->set(pixelformat, size, size);
1336 dim = 2;
1337 w = size;
1338 h = 1;
1339 FWARNING(("createNoise: Use [1|2|3] for image dimension (default 2)\n"));
1340 break;
1343 if ( ! (ok && (data = image->editData())) )
1345 FFATAL(("createNoise: Could not create image\n"));
1346 return false;
1349 UInt16 ncomp = image->getComponents();
1351 if(splitOctaves && numOctaves > ncomp)
1353 FWARNING(("createNoise: try to split %d octaves, but only have %d"
1354 " components!\n", numOctaves, ncomp ));
1355 numOctaves = ncomp;
1358 for (f=0; f<numOctaves; ++f, frequency*=2, amp*=0.5)
1360 ptr = data;
1362 setNoiseFrequency(frequency);
1363 ni[0] = ni[1] = ni[2] = 0;
1364 inci = 1.0 / (size / Real32(frequency));
1365 incj = 1.0 / (size / Real32(frequency));
1366 inck = 1.0 / (size / Real32(frequency));
1368 for (i=0; i<size; ++i, ni[0]+=inci)
1370 for (j=0; j<w; ++j, ni[1]+=incj)
1372 for (k=0; k<h; ++k, ni[2]+=inck)
1374 // calculate numOctaves of noise and scale to range [0;1]
1375 if (splitOctaves)
1377 *(ptr+f) = UInt8(((noise(ni, dim) + 1) * amp) * 128.0);
1379 ptr+=ncomp;
1381 else
1383 for(c = 0; c < ncomp; ++c, ++ptr, ni[0] += 1)
1384 (*ptr) += UInt8(((noise(ni, dim) + 1) * amp) * 128.0);
1386 ni[0] -= ncomp;
1391 FNOTICE(("Generated %dD noise: octave %d/%d...\n", dim, f+1, numOctaves));
1394 return true;
1398 bool createGamma(Image *pImg, UInt32 size, Real32 gamma)
1400 if(pImg == NULL)
1402 FFATAL (("No output image given\n"));
1403 return false;
1406 pImg->set(Image::OSG_L_PF,
1407 size,
1412 0.0,
1414 Image::OSG_FLOAT32_IMAGEDATA);
1416 Real32 *pDst = reinterpret_cast<Real32 *>(pImg->editData());
1418 for(UInt32 i = 0; i < size; i++)
1420 Real32 x = Real32(i) / Real32(size);
1422 pDst[i] = pow(x, gamma);
1425 return true;
1428 bool createVignette(Image *pImg,
1429 UInt32 width,
1430 UInt32 height,
1431 Real32 r0,
1432 Real32 r1 )
1434 if(pImg == NULL)
1436 FFATAL (("No output image given\n"));
1437 return false;
1440 pImg->set(Image::OSG_L_PF,
1441 width,
1442 height,
1446 0.0,
1448 Image::OSG_FLOAT32_IMAGEDATA);
1450 Real32 *pDst = reinterpret_cast<Real32 *>(pImg->editData());
1452 for(UInt32 y = 0; y < height; y++)
1454 for(UInt32 x = 0; x < width; x++)
1456 Real32 radius =
1457 osgSqrt((x - width / 2) * (x - width / 2) +
1458 (y - height / 2) * (y - height / 2));
1460 if(radius > r0)
1462 if(radius < r1)
1464 Real32 t = 1.0 - (radius - r0) / (r1 - r0);
1465 Real32 a = t * 2 - 1;
1466 float reduce =
1467 (0.25 * Pi +
1468 0.5 * osgASin(a) +
1469 0.5 * a * osgSqrt(1 - a * a)) / (0.5 * Pi);
1471 pDst[y * width + x] = reduce;
1473 else
1475 pDst[y * width + x] = 0.0;
1478 else
1480 pDst[y * width + x] = 1.0;
1485 return true;
1488 bool convertCrossToCubeMap(Image const *pIn,
1489 Image *pOut)
1491 if(pIn == NULL || pOut == NULL)
1493 FFATAL (("No appropriate images given\n"));
1494 return false;
1497 OSG::UInt32 face_width = pIn->getWidth() / 3;
1498 OSG::UInt32 face_height = pIn->getHeight() / 4;
1501 pOut->set(pIn->getPixelFormat(),
1502 face_width,
1503 face_height,
1507 0.0,
1508 NULL,
1509 pIn->getDataType(),
1510 true,
1514 Real32 *pDst = reinterpret_cast< Real32 *>(pOut->editData());
1515 const Real32 *pSrc = reinterpret_cast<const Real32 *>(pIn ->getData ());
1517 // - X
1518 for(OSG::UInt32 j = 0; j < face_height; j++)
1520 for(OSG::UInt32 i = 0; i < face_width; i++)
1522 *pDst++ = pSrc[(pIn->getHeight() - (face_height + j + 1)) * (pIn->getWidth() * 3) +
1523 (i * 3) +
1525 *pDst++ = pSrc[(pIn->getHeight() - (face_height + j + 1)) * (pIn->getWidth() * 3) +
1526 (i * 3) +
1528 *pDst++ = pSrc[(pIn->getHeight() - (face_height + j + 1)) * (pIn->getWidth() * 3) +
1529 (i * 3) +
1535 // +X
1536 for (OSG::UInt32 j=0; j < face_height; j++)
1538 for (OSG::UInt32 i = 0; i < face_width; i++)
1540 *pDst++ = pSrc[(pIn->getHeight() - (face_height + j + 1)) * (pIn->getWidth() * 3) +
1541 (2 * face_width + i) * 3 +
1543 *pDst++ = pSrc[(pIn->getHeight() - (face_height + j + 1)) * (pIn->getWidth() * 3) +
1544 (2 * face_width + i) * 3 +
1546 *pDst++ = pSrc[(pIn->getHeight() - (face_height + j + 1)) * (pIn->getWidth() * 3) +
1547 (2 * face_width + i) * 3 +
1552 // +Y
1553 OSG::UInt32 uiBaseY = 3 * face_height;
1554 OSG::UInt32 uiBaseX = face_width;
1556 for(OSG::UInt32 j = 0; j < face_height; ++j)
1558 for(OSG::UInt32 i = 0; i < face_width; ++i)
1560 *pDst++ = pSrc[(uiBaseY + j) * (pIn->getWidth() * 3) +
1561 (pIn->getWidth() - (face_width + i + 1)) * 3 +
1563 *pDst++ = pSrc[(uiBaseY + j) * (pIn->getWidth() * 3) +
1564 (pIn->getWidth() - (face_width + i + 1)) * 3 +
1566 *pDst++ = pSrc[(uiBaseY + j) * (pIn->getWidth() * 3) +
1567 (pIn->getWidth() - (face_width + i + 1)) * 3 +
1572 // -Y
1573 uiBaseY = face_height;
1574 uiBaseX = face_width;
1576 for(OSG::UInt32 j = 0; j < face_height; ++j)
1578 for(OSG::UInt32 i = 0; i < face_width; ++i)
1580 *pDst++ = pSrc[(uiBaseY + j) * (pIn->getWidth() * 3) +
1581 (pIn->getWidth() - (face_width + i + 1)) * 3 +
1584 *pDst++ = pSrc[(uiBaseY + j) * (pIn->getWidth() * 3) +
1585 (pIn->getWidth() - (face_width + i + 1)) * 3 +
1587 *pDst++ = pSrc[(uiBaseY + j) * (pIn->getWidth() * 3) +
1588 (pIn->getWidth() - (face_width + i + 1)) * 3 +
1594 // -Z
1595 uiBaseY = 0;
1596 uiBaseX = face_width;
1598 for(OSG::UInt32 j = 0; j < face_height; ++j)
1600 for(OSG::UInt32 i = 0; i < face_width; ++i)
1602 *pDst++ = pSrc[(j + 1) * (pIn->getWidth() * 3) +
1603 (pIn->getWidth() - (face_width + i + 1)) * 3 +
1605 *pDst++ = pSrc[(j + 1) * (pIn->getWidth() * 3) +
1606 (pIn->getWidth() - (face_width + i + 1)) * 3 +
1608 *pDst++ = pSrc[(j + 1) * (pIn->getWidth() * 3) +
1609 (pIn->getWidth() - (face_width + i + 1)) * 3 +
1614 // +Z
1615 uiBaseY = 2 * face_height;
1616 uiBaseX = face_width;
1618 for(OSG::UInt32 j = 0; j < face_height; ++j)
1620 for(OSG::UInt32 i = 0; i < face_width; ++i)
1622 *pDst++ = pSrc[(pIn->getHeight() - (face_height + j + 1)) * (pIn->getWidth() * 3) +
1623 (i + uiBaseX) * 3 +
1625 *pDst++ = pSrc[(pIn->getHeight() - (face_height + j + 1)) * (pIn->getWidth() * 3) +
1626 (i + uiBaseX) * 3 +
1628 *pDst++ = pSrc[(pIn->getHeight() - (face_height + j + 1)) * (pIn->getWidth() * 3) +
1629 (i + uiBaseX) * 3 +
1634 return true;
1637 ImageTransitPtr createPerlinImage(const Vec2s &vSize,
1638 const Vec2f &vRange,
1639 Real32 fAmplitude,
1640 Real32 fFrequency,
1641 const Vec2f &vPhase,
1642 Real32 fPersistance,
1643 UInt32 uiOctaves,
1644 UInt32 uiInterpolMode,
1645 bool bSmoothing,
1646 Image::PixelFormat pixelformat,
1647 Image::Type type)
1649 ImageUnrecPtr PerlinImage = Image::create();
1651 std::vector<Real32> ImageData(vSize.x() * vSize.y());
1653 bool shouldTranslate = false;
1655 switch(type)
1657 case Image::OSG_UINT8_IMAGEDATA:
1658 case Image::OSG_UINT16_IMAGEDATA:
1659 case Image::OSG_UINT32_IMAGEDATA:
1660 shouldTranslate = true;
1661 break;
1662 default:
1663 shouldTranslate = false;
1664 break;
1667 for(Int32 i = 0; i < vSize.x(); ++i)
1669 for(Int32 j = 0; j < vSize.y(); ++j)
1671 ImageData[i * vSize.x() + j] =
1672 osgClamp(-0.5f,
1673 Perlin::calcPerlinNoise(
1674 Pnt2f(vRange.x() * Real32(i) / Real32(vSize.x()),
1675 vRange.y() * Real32(j) / Real32(vSize.y())),
1676 fAmplitude,
1677 fFrequency,
1678 vPhase,
1679 fPersistance,
1680 uiOctaves,
1681 uiInterpolMode,
1682 bSmoothing),
1683 0.5f);
1685 if(shouldTranslate == true)
1687 ImageData[i * vSize.x() + j] += 0.5f;
1692 if(PerlinImage->set(Image::OSG_I_PF,
1693 vSize.x(),
1694 vSize.y(),
1698 0.0f,
1699 reinterpret_cast<UInt8 *>(&ImageData[0]),
1700 Image::OSG_FLOAT32_IMAGEDATA ) == true)
1702 if(type != Image::OSG_FLOAT32_IMAGEDATA)
1704 if(PerlinImage->convertDataTypeTo(type) == false)
1706 return ImageTransitPtr(NULL);
1710 if(pixelformat != Image::OSG_I_PF)
1712 if(PerlinImage->reformat(pixelformat) == false)
1714 return ImageTransitPtr(NULL);
1718 return ImageTransitPtr(PerlinImage);
1720 else
1722 return ImageTransitPtr(NULL);
1726 ImageTransitPtr createPerlinImage(const Vec3s &vSize,
1727 const Vec3f &vRange,
1728 Real32 fAmplitude,
1729 Real32 fFrequency,
1730 const Vec3f &vPhase,
1731 Real32 fPersistance,
1732 UInt32 uiOctaves,
1733 UInt32 uiInterpolMode,
1734 bool bSmoothing,
1735 Image::PixelFormat pixelformat,
1736 Image::Type type )
1738 ImageUnrecPtr PerlinImage = Image::create();
1740 std::vector<Real32> ImageData(vSize.x() * vSize.y() * vSize.z());
1742 bool shouldTranslate = false;
1744 switch(type)
1746 case Image::OSG_UINT8_IMAGEDATA:
1747 case Image::OSG_UINT16_IMAGEDATA:
1748 case Image::OSG_UINT32_IMAGEDATA:
1749 shouldTranslate = true;
1750 break;
1751 default:
1752 shouldTranslate = false;
1753 break;
1756 for(Int32 i = 0; i < vSize.x() ; ++i)
1758 for(Int32 j = 0; j < vSize.y(); ++j)
1760 for(Int32 k = 0; k < vSize.z(); ++k)
1762 ImageData[i * vSize.x() * vSize.y() + j * vSize.y() + k] =
1763 osgClamp(
1764 -0.5f,
1765 Perlin::calcPerlinNoise(
1766 Pnt3f(vRange.x() * Real32(i) / Real32(vSize.x()),
1767 vRange.y() * Real32(j) / Real32(vSize.y()),
1768 vRange.z() * Real32(k) / Real32(vSize.z())),
1769 fAmplitude,
1770 fFrequency,
1771 vPhase,
1772 fPersistance,
1773 uiOctaves,
1774 uiInterpolMode,
1775 bSmoothing),
1776 0.5f);
1778 if(shouldTranslate)
1780 ImageData[i * vSize.x() * vSize.y() +
1781 j * vSize.y() +
1782 k ] += 0.5f;
1789 if(PerlinImage->set(Image::OSG_I_PF,
1790 vSize.x(),
1791 vSize.y(),
1792 vSize.z(),
1795 0.0f,
1796 reinterpret_cast<UInt8 *>(&ImageData[0]),
1797 Image::OSG_FLOAT32_IMAGEDATA))
1799 if(type != Image::OSG_FLOAT32_IMAGEDATA)
1801 if(PerlinImage->convertDataTypeTo(type) == false)
1803 return ImageTransitPtr(NULL);
1807 if(pixelformat != Image::OSG_I_PF)
1809 if(PerlinImage->reformat(pixelformat) == false)
1811 return ImageTransitPtr(NULL);
1815 return ImageTransitPtr(PerlinImage);
1817 else
1819 return ImageTransitPtr(NULL);
1823 OSG_END_NAMESPACE