00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041
00042 #include <OSGConfig.h>
00043 #include <OSGLog.h>
00044 #include <OSGImage.h>
00045 #include <OSGBaseFunctions.h>
00046
00047 #include "OSGImageFunctions.h"
00048
00049
00050 OSG_USING_NAMESPACE
00051
00052 #if defined(OSG_WIN32_ICL) && !defined(OSG_CHECK_FIELDSETARG)
00053 #pragma warning(disable : 383)
00054 #endif
00055 #ifdef __sgi
00056 #pragma set woff 1209
00057 #endif
00058
00059
00060
00061
00062
00063
00066 OSG_SYSTEMLIB_DLLMAPPING
00067 bool OSG::createComposedImage ( std::vector<ImagePtr> imageVec,
00068 ImagePtr image,
00069 SliceDataType sliceDataType )
00070 {
00071 UInt32 dataSize, i, n = imageVec.size();
00072 Int32 w = 0, h = 0;
00073 UInt8 *destData, *srcData;
00074 Image::PixelFormat pf = Image::OSG_INVALID_PF;
00075 Image::Type dt = Image::OSG_INVALID_IMAGEDATATYPE;
00076 bool needColor = false, needAlpha = false, needCopy = false;
00077 ImagePtr copy = Image::create();
00078 UInt32 depth, frameCount, sideCount;
00079
00080 if (n) {
00081 for (i = 0; i < n; i++) {
00082 if ( i == 0 ) {
00083 pf = Image::PixelFormat(imageVec[0]->getPixelFormat());
00084 dt = Image::Type(imageVec[0]->getDataType());
00085 w = imageVec[0]->getWidth();
00086 h = imageVec[0]->getHeight();
00087 needAlpha = imageVec[0]->hasAlphaChannel();
00088 needColor = imageVec[0]->hasColorChannel();
00089 }
00090 else {
00091 needAlpha |= imageVec[i]->hasAlphaChannel();
00092 needColor |= imageVec[i]->hasColorChannel();
00093 if (Image::PixelFormat(imageVec[i]->getPixelFormat()) != pf) {
00094 needCopy = true;
00095 FWARNING (( "Image has different PF while composing\n" ));
00096 pf = Image::OSG_INVALID_PF;
00097 }
00098 if (Image::Type(imageVec[i]->getDataType()) != dt) {
00099 needCopy = true;
00100 FWARNING (( "Image has different DT while composing\n" ));
00101 dt = Image::OSG_INVALID_IMAGEDATATYPE;
00102 }
00103 if (imageVec[i]->getWidth() != w) {
00104 needCopy = true;
00105 FWARNING (( "Image has different width while composing\n" ));
00106 w = osgMax ( w, imageVec[i]->getWidth());
00107 }
00108 if (imageVec[i]->getHeight() != h) {
00109 needCopy = true;
00110 FWARNING (( "Image has different height while composing\n" ));
00111 h = osgMax ( h, imageVec[i]->getHeight());
00112 }
00113 }
00114 }
00115
00116 if (pf == Image::OSG_INVALID_PF) {
00117 if (needColor)
00118 if (needAlpha)
00119 pf = OSG::Image::OSG_RGBA_PF;
00120 else
00121 pf = OSG::Image::OSG_RGB_PF;
00122 else
00123 if (needAlpha)
00124 pf = OSG::Image::OSG_LA_PF;
00125 else
00126 pf = OSG::Image::OSG_L_PF;
00127 }
00128
00129 if (dt == Image::OSG_INVALID_IMAGEDATATYPE)
00130 dt = Image::OSG_UINT8_IMAGEDATA;
00131
00132 depth = frameCount = sideCount = 1;
00133 switch (sliceDataType) {
00134 case FRAME_SDT:
00135 frameCount = n;
00136 break;
00137 case SIDE_SDT:
00138 sideCount = n;
00139 break;
00140 case INVALID_SDT:
00141 case DEPTH_SDT:
00142 default:
00143 depth = n;
00144 break;
00145 }
00146
00147 image->set( pf, w, h, depth, 1, frameCount, 0.0,
00148 0, dt, true, sideCount );
00149
00150 destData = image->getData();
00151 dataSize = image->getSize() / n;
00152
00153 if (needCopy) {
00154 FLOG (("Image data/type/size missmatch while composing\n"));
00155 }
00156
00157 for (i = 0; i < n; i++) {
00158 if (needCopy) {
00159 copy->set(imageVec[i]);
00160 if ( Image::PixelFormat(copy->getPixelFormat()) != pf )
00161 copy->reformat(pf);
00162 if ( Image::Type(copy->getDataType()) != dt )
00163 copy->convertDataTypeTo(dt);
00164 if ( (w != copy->getWidth()) || (h != copy->getHeight()))
00165 copy->scale(w,h,copy->getDepth());
00166 srcData = copy->getData();
00167 }
00168 else
00169 srcData = imageVec[i]->getData();
00170
00171 memcpy ( destData, srcData, dataSize );
00172 destData += dataSize;
00173 }
00174 }
00175
00176 subRefCP(copy);
00177
00178 imageVec[0]->dump();
00179 image->dump();
00180
00181 return true;
00182 }
00183
00184
00187 OSG_SYSTEMLIB_DLLMAPPING
00188 bool OSG::createNormalMapFromBump ( ImagePtr image,
00189 ImagePtr dst,
00190 Vec3f normalMapScale)
00191 {
00192 if (image == NullFC || image->getDepth() > 1 ||
00193 image->getPixelFormat() != Image::OSG_L_PF)
00194 {
00195 FFATAL(("No valid Normalmap given!\n"));
00196 return false;
00197 }
00198
00199 bool cpImg = false;
00200
00201 if (dst == NullFC)
00202 {
00203 dst = Image::create();
00204 cpImg = true;
00205 }
00206
00207 Int32 w = image->getWidth();
00208 Int32 h = image->getHeight();
00209
00210 unsigned char *srcData = image->getData();
00211
00212 beginEditCP(dst);
00213
00214 dst->set(Image::OSG_RGB_PF, w, h);
00215
00216 unsigned char *dstData = dst->getData();
00217
00218 Vec3f scale(normalMapScale);
00219
00220 if (scale[0] == 0.0f || scale[1] == 0.0f || scale[2] == 0.0f)
00221 {
00222 Real32 a = Real32(w) / Real32(h);
00223
00224 if(a < 1.0f)
00225 {
00226 scale[0] = 1.0f;
00227 scale[1] = 1.0f / a;
00228 }
00229 else
00230 {
00231 scale[0] = a;
00232 scale[1] = 1.0f;
00233 }
00234 scale[2] = 1.0f;
00235 }
00236
00237 Int32 i, j;
00238
00239 for (i=1; i<w-1; i++)
00240 {
00241 for (j=1; j<h-1; j++)
00242 {
00243 Vec3f dfdi(2.0f, 0.0f, (Real32)(srcData[(i+1) + j*w] - srcData[(i-1) + j*w]) / 255.0f);
00244 Vec3f dfdj(0.0f, 2.0f, (Real32)(srcData[ i + (j+1)*w] - srcData[ i + (j-1)*w]) / 255.0f);
00245 Vec3f n = dfdi.cross(dfdj);
00246
00247 n[0] *= scale[0];
00248 n[1] *= scale[1];
00249 n[2] *= scale[2];
00250 n.normalize();
00251
00252 dstData[(j*w+i)*3+0] = (unsigned char)((n[0]+1)*127.5);
00253 dstData[(j*w+i)*3+1] = (unsigned char)((n[1]+1)*127.5);
00254 dstData[(j*w+i)*3+2] = (unsigned char)((n[2]+1)*127.5);
00255 }
00256 }
00257
00258
00259 for (i=0; i<w; i++)
00260 {
00261 dstData[i*3+0] = dstData[(w+i)*3+0];
00262 dstData[i*3+1] = dstData[(w+i)*3+1];
00263 dstData[i*3+2] = dstData[(w+i)*3+2];
00264
00265 dstData[((h-1)*w+i)*3+0] = dstData[((h-2)*w+1)*3+0];
00266 dstData[((h-1)*w+i)*3+1] = dstData[((h-2)*w+1)*3+1];
00267 dstData[((h-1)*w+i)*3+2] = dstData[((h-2)*w+1)*3+2];
00268 }
00269
00270 for (j=0; j<h; j++)
00271 {
00272 dstData[(j*w)*3+0] = dstData[(j*w+1)*3+0];
00273 dstData[(j*w)*3+1] = dstData[(j*w+1)*3+1];
00274 dstData[(j*w)*3+2] = dstData[(j*w+1)*3+2];
00275
00276 dstData[(j*w+(w-1))*3+0] = dstData[(j*w+(w-2))*3+0];
00277 dstData[(j*w+(w-1))*3+1] = dstData[(j*w+(w-2))*3+1];
00278 dstData[(j*w+(w-1))*3+2] = dstData[(j*w+(w-2))*3+2];
00279 }
00280
00281 endEditCP(dst);
00282
00283 if (cpImg)
00284 {
00285 beginEditCP(image);
00286 image->set(dst);
00287 endEditCP(image);
00288 }
00289
00290
00291
00292 return true;
00293 }
00294
00295
00296
00299 OSG_SYSTEMLIB_DLLMAPPING
00300 bool OSG::createNormalVolume ( ImagePtr inImage,
00301 ImagePtr outImage,
00302 const std::string &outputFormat )
00303 {
00304 const Real32 gMax = 441.67295593, gF = 255.0/gMax;
00305 const osg::Real32 TwoPi = 2 * osg::Pi;
00306
00307 enum DataIndex { SCALAR_DI,
00308 SCALAR_NULLEDGE_DI,
00309 X_DI, Y_DI, Z_DI,
00310 GRADIENT_DI,
00311 THETA_DI, PHI_DI,
00312
00313 END_DI
00314 };
00315
00316 UInt8 *data = 0, *ds, dc;
00317 osg::Real32 minU = osg::Inf, maxU = -osg::Inf;
00318 osg::Real32 minV = osg::Inf, maxV = -osg::Inf;
00319 Int32 w, h, d, x, y, z, md, ld, hd, xs, ys, zs, ps, ls, ss, os;
00320 Int32 i,voxelSize ,g,t,p;
00321 std::vector<UInt32> dataIndex;
00322 Real32 u, v, length;
00323 Vec3f normal;
00324 ImagePtr copy;
00325 Image::PixelFormat pf;
00326 bool calcGradient = false, calcThetaPhi = false;
00327 char validFormat[END_DI];
00328 UInt8 voxelData[sizeof(validFormat)];
00329 char *formatP;
00330 bool isEdge;
00331
00332
00333 validFormat[SCALAR_DI] = 's';
00334 validFormat[SCALAR_NULLEDGE_DI] = 'S';
00335 validFormat[X_DI] = 'x';
00336 validFormat[Y_DI] = 'y';
00337 validFormat[Z_DI] = 'z';
00338 validFormat[GRADIENT_DI] = 'g';
00339 validFormat[THETA_DI] = 't';
00340 validFormat[PHI_DI] = 'p';
00341
00342
00343 if ( inImage->getBpp() != 1 ) {
00344
00345 copy = Image::create();
00346 FLOG (("Create copy to reformat/convert Image\n"));
00347
00348 if ( (inImage->getPixelFormat() == Image::OSG_L_PF) ||
00349 (inImage->getPixelFormat() == Image::OSG_L_PF) )
00350 copy->set(inImage);
00351 else
00352 inImage->reformat(Image::OSG_L_PF,copy);
00353 inImage = copy;
00354
00355 if (inImage->getDataType() != Image::OSG_UINT8_IMAGEDATA)
00356 inImage->convertDataTypeTo(Image::OSG_UINT8_IMAGEDATA);
00357 }
00358
00359 switch (outputFormat.size()) {
00360 case 1:
00361 pf = Image::OSG_L_PF;
00362 break;
00363 case 2:
00364 pf = Image::OSG_LA_PF;
00365 break;
00366 case 3:
00367 pf = Image::OSG_RGB_PF;
00368 break;
00369 case 4:
00370 pf = Image::OSG_RGBA_PF;
00371 break;
00372 default:
00373 FFATAL (( "Invalid outputFormat length in createNormalVolume: %d\n",
00374 outputFormat.size() ));
00375 return false;
00376 }
00377
00378
00379 w = inImage->getWidth();
00380 h = inImage->getHeight();
00381 d = inImage->getDepth();
00382 data = inImage->getData();
00383 ps = inImage->getBpp();
00384 ls = ps * w;
00385 ss = ls * h;
00386 os = 0;
00387
00388
00389 voxelSize = outputFormat.size();
00390 dataIndex.resize(voxelSize);
00391 for (i = 0; i < voxelSize; i++) {
00392 if ((formatP = strchr(validFormat, outputFormat[i]))) {
00393 dataIndex[i] = (formatP - validFormat);
00394 switch (dataIndex[i]) {
00395 case GRADIENT_DI:
00396 calcGradient = true;
00397 break;
00398 case THETA_DI:
00399 case PHI_DI:
00400 calcThetaPhi = true;
00401 break;
00402 }
00403 FDEBUG (( "dataIndex[%d]: %d\n", i, dataIndex[i] ));
00404 }
00405 else {
00406 FFATAL (( "Invalid outputFormat element %c, valid: \n",
00407 char(outputFormat[i]), validFormat ));
00408 return false;
00409 }
00410 }
00411
00412 beginEditCP(outImage);
00413
00414
00415 outImage->set( pf, w, h, d );
00416
00417 ds = outImage->getData();
00418
00419
00420 for (z = 0; z < d; z++) {
00421 for (y = 0; y < h; y++) {
00422 for (x = 0; x < w; x++) {
00423 isEdge = false;
00424
00425 md = data[(x*ps) + (y*ls) + (z*ss) + os];
00426
00427
00428 if (x > 0)
00429 ld = data[((x-1)*ps) + (y*ls) + (z*ss) + os];
00430 else {
00431 isEdge |= true;
00432 ld = 0;
00433 }
00434 if (x < (w-1))
00435 hd = data[((x+1)*ps) + (y*ls) + (z*ss) + os];
00436 else {
00437 isEdge |= true;
00438 hd = 0;
00439 }
00440 xs = (ld - hd);
00441
00442
00443 if (y > 0)
00444 ld = data[(x*ps) + ((y-1)*ls) + (z*ss) + os];
00445 else {
00446 isEdge |= true;
00447 ld = 0;
00448 }
00449 if (y < (h-1))
00450 hd = data[(x*ps) + ((y+1)*ls) + (z*ss) + os];
00451 else {
00452 isEdge |= true;
00453 hd = 0;
00454 }
00455 ys = (ld - hd);
00456
00457
00458 if (z > 0)
00459 ld = data[(x*ps) + (y*ls) + ((z-1)*ss) + os];
00460 else {
00461 isEdge |= true;
00462 ld = 0;
00463 }
00464 if (z < (d-1))
00465 hd = data[(x*ps) + (y*ls) + ((z+1)*ss) + os];
00466 else {
00467 isEdge |= true;
00468 hd = 0;
00469 }
00470 zs = (ld - hd);
00471
00472
00473 voxelData[SCALAR_DI] = md;
00474 voxelData[SCALAR_NULLEDGE_DI] = isEdge ? 0 : md;
00475 voxelData[X_DI] = xs / 2 + 127;
00476 voxelData[Y_DI] = ys / 2 + 127;
00477 voxelData[Z_DI] = zs / 2 + 127;
00478
00479
00480 if (calcGradient || calcThetaPhi) {
00481 normal.setValues (xs,ys,zs);
00482 length = normal.length();
00483 normal.normalize();
00484 }
00485
00486
00487 if (calcGradient) {
00488 voxelData[GRADIENT_DI] = osgMax ( int (length * gF), 255 );
00489 }
00490
00491
00492 if (calcThetaPhi) {
00493 v = osg::osgacos(normal[2]) / osg::Pi;
00494 u = osg::osgsqrt(normal[0]*normal[0] + normal[1]*normal[1]);
00495
00496 if (u) u = normal[0] / u;
00497 u = osg::osgacos(u);
00498 if (normal[1]<0) u = TwoPi - u;
00499 u /= TwoPi;
00500
00501 if (u<minU) minU=u;
00502 if (u>maxU) maxU=u;
00503 if (v<minV) minV=v;
00504 if (v>maxV) maxV=v;
00505
00506 voxelData[THETA_DI] = (osg::UInt8)(v * 255.f);
00507 voxelData[PHI_DI] = (osg::UInt8)(u * 255.f);
00508 }
00509
00510
00511 for (i = 0; i < voxelSize; i++)
00512 *ds++ = voxelData[dataIndex[i]];
00513
00514 }
00515 }
00516 }
00517
00518 endEditCP(outImage);
00519
00520 if (copy != osg::NullFC)
00521 subRefCP(copy);
00522
00523 return true;
00524 }
00525
00526
00527
00533 OSG_SYSTEMLIB_DLLMAPPING
00534 bool OSG::create2DPreIntegrationLUT ( ImagePtr dst,
00535 ImagePtr src,
00536 Real32 thickness)
00537 {
00538 if (src == NullFC || dst == NullFC ||
00539 src->getHeight() > 1 || src->getDepth() > 1 ||
00540 src->getPixelFormat() != Image::OSG_RGBA_PF)
00541 {
00542 FFATAL(("No appropriate image given!\n"));
00543 return false;
00544 }
00545
00546 unsigned char *dataSrc = src->getData();
00547 UInt32 width = src->getWidth();
00548
00549 beginEditCP( dst );
00550 {
00551 dst->set(Image::OSG_RGBA_PF, width, width);
00552
00553 unsigned char *dataDst = dst->getData();
00554
00555 for (Int32 x = 0; x < (Int32)width; x++)
00556 {
00557 for (Int32 y = 0; y < (Int32)width; y++)
00558 {
00559 Int32 n = 10 + 2 * abs(x-y);
00560 Real64 step = thickness / n;
00561
00562 Real64 dr = 0.0,
00563 dg = 0.0,
00564 db = 0.0,
00565 dtau = 0.0;
00566
00567 for (Int32 i = 0; i < n; i++)
00568 {
00569 Real64 w = x + (y-x) * (Real64)i/n;
00570
00571 if ((Int32)(w + 1) >= (Int32)width)
00572 w = (Real64)(width - 1) - 0.5/n;
00573
00574 Int32 pos = ((Int32)w) * 4;
00575
00576 Real64 e = exp(-dtau), scale = step * (1.0 / 255.0),
00577 f = w - floor(w), invF = 1 - f;
00578
00579 Real64 tau = scale * (dataSrc[pos + 3] * f + dataSrc[pos+4 + 3] * invF);
00580 Real64 r = e * scale * (dataSrc[pos + 0] * f + dataSrc[pos+4 + 0] * invF);
00581 Real64 g = e * scale * (dataSrc[pos + 1] * f + dataSrc[pos+4 + 1] * invF);
00582 Real64 b = e * scale * (dataSrc[pos + 2] * f + dataSrc[pos+4 + 2] * invF);
00583
00584 dr += r;
00585 dg += g;
00586 db += b;
00587 dtau += tau;
00588 }
00589
00590 dataDst[(x*width+y)*4+0] = (unsigned char)((dr > 1.0 ? 1.0 : dr)*255);
00591 dataDst[(x*width+y)*4+1] = (unsigned char)((dg > 1.0 ? 1.0 : dg)*255);
00592 dataDst[(x*width+y)*4+2] = (unsigned char)((db > 1.0 ? 1.0 : db)*255);
00593 dataDst[(x*width+y)*4+3] = (unsigned char)((1.0 - exp(-dtau))*255);
00594 }
00595 }
00596 }
00597 endEditCP( dst );
00598
00599
00600
00601 return true;
00602 }
00603
00604
00605
00608 OSG_SYSTEMLIB_DLLMAPPING
00609 bool OSG::splitRGBA(ImagePtr rgba,
00610 ImagePtr rgb,
00611 ImagePtr alpha)
00612 {
00613 if (rgba == NullFC || rgba->getDepth() > 1 ||
00614 rgba->getPixelFormat() != Image::OSG_RGBA_PF)
00615 {
00616 FFATAL(("No appropriate image given!\n"));
00617 return false;
00618 }
00619
00620 if (rgb == NullFC)
00621 rgb = Image::create();
00622 if (alpha == NullFC)
00623 alpha = Image::create();
00624
00625 Int32 w = rgba->getWidth();
00626 Int32 h = rgba->getHeight();
00627
00628 beginEditCP( rgb );
00629 beginEditCP( alpha );
00630 {
00631 rgb->set(Image::OSG_RGB_PF, w, h);
00632 alpha->set(Image::OSG_L_PF, w, h);
00633
00634 unsigned char *data = rgb->getData();
00635 unsigned char *dataRgba = rgba->getData();
00636 unsigned char *dataAlpha = alpha->getData();
00637
00638 for (Int32 i=0; i<(w * h); i++)
00639 {
00640 data[0] = dataRgba[0];
00641 data[1] = dataRgba[1];
00642 data[2] = dataRgba[2];
00643 dataAlpha[0] = dataRgba[3];
00644
00645 data += 3;
00646 dataRgba += 4;
00647 dataAlpha++;
00648 }
00649 }
00650 endEditCP( alpha );
00651 endEditCP( rgb );
00652
00653
00654
00655
00656 return true;
00657 }
00658
00659
00662 OSG_SYSTEMLIB_DLLMAPPING
00663 bool OSG::mergeRGBA(ImagePtr rgb,
00664 ImagePtr alpha,
00665 ImagePtr rgba)
00666 {
00667 if (rgb == NullFC || alpha == NullFC ||
00668 rgb->getDepth() > 1 || alpha->getDepth() > 1 ||
00669 rgb->getPixelFormat() != Image::OSG_RGB_PF ||
00670 alpha->getPixelFormat() != Image::OSG_L_PF)
00671 {
00672 FFATAL(("No appropriate images given!\n"));
00673 return false;
00674 }
00675
00676 Int32 w = rgb->getWidth();
00677 Int32 h = rgb->getHeight();
00678
00679 if (w != alpha->getWidth() || h != alpha->getHeight())
00680 {
00681 FFATAL(("Colour and Alpha Images must be of same size!\n"));
00682 return false;
00683 }
00684
00685 if (rgba == NullFC)
00686 rgba = Image::create();
00687
00688 beginEditCP( rgba );
00689 {
00690 rgba->set(Image::OSG_RGBA_PF, w, h);
00691
00692 unsigned char *data = rgba->getData();
00693 unsigned char *dataRgb = rgb->getData();
00694 unsigned char *dataAlpha = alpha->getData();
00695
00696 for (Int32 i=0; i<(w * h); i++)
00697 {
00698 data[0] = dataRgb[0];
00699 data[1] = dataRgb[1];
00700 data[2] = dataRgb[2];
00701 data[3] = *dataAlpha;
00702 data += 4;
00703 dataRgb += 3;
00704 dataAlpha++;
00705 }
00706 }
00707 endEditCP( rgba );
00708
00709
00710
00711 return true;
00712 }
00713
00714
00717 OSG_SYSTEMLIB_DLLMAPPING
00718 bool OSG::blendImage ( ImagePtr canvas,
00719 ImagePtr brush,
00720 Vec3f position,
00721 Color4f color,
00722 Real32 alphaScale,
00723 Real32 paintZ )
00724 {
00725 int x,y,z;
00726 int red = 0, green = 0, blue = 0, grey = 0;
00727 int alpha = 0;
00728 osg::UChar8 *s = 0, *d = 0;
00729
00730 osg::beginEditCP(canvas);
00731
00732 osg::UChar8 *src = brush->getData();
00733 osg::UChar8 *dest = canvas->getData();
00734
00735 const float cred = color.red();
00736 const float cgreen = color.green();
00737 const float cblue = color.blue();
00738 const float calpha = color.alpha();
00739 const float talpha = alphaScale;
00740
00741 const int cPF = canvas->getPixelFormat();
00742 const int bPF = brush->getPixelFormat();
00743
00744 const int cBpp = canvas->getBpp();
00745 const int bBpp = brush->getBpp();
00746
00747 const int bW = brush->getWidth();
00748 const int bH = brush->getHeight();
00749 const int bD = brush->getDepth();
00750
00751 const int cW = canvas->getWidth();
00752 const int cH = canvas->getHeight();
00753 const int cD = canvas->getDepth();
00754
00755 const int xcOff = int(position.x());
00756 const int ycOff = int(position.y());
00757 const int zcOff = int(position.z());
00758
00759
00760
00761 const int xcMin = osg::osgMax(0, xcOff);
00762 const int ycMin = osg::osgMax(0, ycOff);
00763 const int zcMin = osg::osgMax(0, zcOff);
00764
00765 const int xcMax = osg::osgMin(cW, xcOff + bW);
00766 const int ycMax = osg::osgMin(cH, ycOff + bH);
00767 const int zcMax = osg::osgMin(cD, zcOff + bD);
00768
00769 const int width = (xcMax - xcMin);
00770 const int height = (ycMax - ycMin);
00771 const int depth = (zcMax - zcMin);
00772
00773 int xbMin = xcOff < 0 ? -xcOff : 0;
00774 int ybMin = ycOff < 0 ? -ycOff : 0;
00775 int zbMin = zcOff < 0 ? -zcOff : 0;
00776
00777
00778 if ((bD > 1) && (depth == 1)) {
00779 z = int(osg::osgabs(paintZ) * (bD - 1)) % bD;
00780 src += bW * bH * bBpp * z;
00781 zbMin = 0;
00782 }
00783
00784 for (z = 0; z < depth; z++) {
00785 for (y = 0; y < height; y++){
00786 d = dest + ( ((z+zcMin) * cH + (y+ycMin)) * cW + xcMin) * cBpp;
00787 s = src + ( ((z+zbMin) * bH + (y+ybMin)) * bW + xbMin) * bBpp;
00788 for (x = 0; x < width; x++) {
00789 switch ( bPF ) {
00790 case OSG::Image::OSG_A_PF:
00791 case OSG::Image::OSG_I_PF:
00792 grey = *s++;
00793 red = int(cred * grey);
00794 green = int(cgreen * grey);
00795 blue = int(cblue * grey);
00796 alpha = int(calpha * grey);
00797 break;
00798 case osg::Image::OSG_L_PF:
00799 grey = *s++;
00800 red = int(cred * grey);
00801 green = int(cgreen * grey);
00802 blue = int(cblue * grey);
00803 alpha = int(calpha * 255);
00804 break;
00805 case osg::Image::OSG_LA_PF:
00806 grey = *s++;
00807 red = int(cred * grey);
00808 green = int(cgreen * grey);
00809 blue = int(cblue * grey);
00810 alpha = int(calpha * *s++);
00811 break;
00812 case osg::Image::OSG_RGB_PF:
00813 red = *s++;
00814 green = *s++;
00815 blue = *s++;
00816 grey = green;
00817 alpha = 255;
00818 break;
00819 case osg::Image::OSG_RGBA_PF:
00820 red = *s++;
00821 green = *s++;
00822 blue = *s++;
00823 grey = green;
00824 alpha = *s++;
00825 break;
00826 default:
00827 FFATAL (("Invalid Brush PixelFormat\n"));
00828 brush->dump();
00829 return false;
00830 }
00831 alpha = int(talpha * alpha);
00832 switch ( cPF ) {
00833 case osg::Image::OSG_I_PF:
00834 *d++ = int(*d * (alpha - 255) + grey * alpha) / 255;
00835 break;
00836 case osg::Image::OSG_L_PF:
00837 *d++ = int(*d * (alpha - 255) + grey * alpha) / 255;
00838 break;
00839 case osg::Image::OSG_LA_PF:
00840 *d++ = int(*d * (alpha - 255) + grey * alpha) / 255;
00841 d++;
00842 break;
00843 case osg::Image::OSG_RGB_PF:
00844 *d++ = int(*d * (255 - alpha) + red * alpha) / 255;
00845 *d++ = int(*d * (255 - alpha) + green * alpha) / 255;
00846 *d++ = int(*d * (255 - alpha) + blue * alpha) / 255;
00847 break;
00848 case osg::Image::OSG_RGBA_PF:
00849 *d++ = int(*d * (255 - alpha) + red * alpha) / 255;
00850 *d++ = int(*d * (255 - alpha) + green * alpha) / 255;
00851 *d++ = int(*d * (255 - alpha) + blue * alpha) / 255;
00852 d++;
00853 break;
00854 default:
00855 FFATAL (("Invalid Canvas PixelFormat\n"));
00856 canvas->dump();
00857 return false;
00858 }
00859 }
00860 }
00861 }
00862 osg::endEditCP(canvas);
00863
00864 return true;
00865 }
00866
00867
00870 OSG_SYSTEMLIB_DLLMAPPING
00871 bool OSG::createPhongTexture(ImagePtr image,
00872 UInt32 size,
00873 Real32 specular_exponent,
00874 Real32 ka,
00875 Real32 kd,
00876 Real32 ks)
00877 {
00878 if (image == NullFC)
00879 image = Image::create();
00880
00881 beginEditCP( image );
00882 {
00883 image->set(Image::OSG_L_PF, size, size);
00884 unsigned char *textureMap = image->getData();
00885
00886 UInt32 i, j, index = 0;
00887 Real32 x = 0, y = 0;
00888
00889 Real32 specular_factor, diffuse_factor;
00890 Real32 textureRadius = 0.95f;
00891 Real32 textureStep = (2.0 * textureRadius) / Real32(size-1);
00892
00893 y = - textureRadius;
00894 for (j=0; j<size; j++)
00895 {
00896 x = -textureRadius;
00897 for (i=0; i<size; i++)
00898 {
00899 diffuse_factor = sqrt(1.0 - x * x);
00900 specular_factor = pow( diffuse_factor * sqrt (1.0f - y * y) - x * y,
00901 specular_exponent );
00902 textureMap[index++] = (unsigned char)((ka + kd * diffuse_factor + ks * specular_factor) * 255);
00903 x += textureStep;
00904 }
00905 y += textureStep;
00906 }
00907 }
00908 endEditCP( image );
00909
00910
00911
00912 return true;
00913 }
00914
00915
00918 bool createPhongVolume ( ImagePtr image,
00919 Color3f diffuseColor,
00920 Color3f specularColor,
00921 UInt32 lutSize,
00922 UInt32 lutScalar,
00923 Real32 lutIncr )
00924 {
00925 const osg::Int32 lutFSize = lutSize / lutScalar;
00926 osg::Real32 theta1, theta2, dPhi, incr = lutScalar * lutIncr;
00927 osg::Real32 Const = 0.2f, Shi = 40, NdotL;
00928 osg::Vec3f color;
00929 osg::Vec3f diffuse (diffuseColor[0],diffuseColor[1],diffuseColor[2]);
00930 osg::Vec3f specular (specularColor[0],specularColor[1],specularColor[2]);
00931 osg::UInt8 *ds;
00932 osg::Real32 min = osg::Inf, max = -osg::Inf;
00933
00934 osg::beginEditCP(image);
00935
00936 image->set( osg::Image::OSG_RGB_PF, lutFSize, lutFSize, lutFSize );
00937
00938 ds = image->getData();
00939
00940 FDEBUG (("calc phong map START\n"));
00941
00942 for (dPhi=0; dPhi<360; dPhi+=incr) {
00943 for (theta1=0; theta1<180; theta1+=incr) {
00944 for (theta2=0; theta2<180; theta2+=incr) {
00945 osg::Real32 t1 = osg::osgdegree2rad(theta1),
00946 t2 = osg::osgdegree2rad(theta2),
00947 dp = osg::osgdegree2rad(dPhi);
00948 NdotL = osg::osgsin(t1)*osg::osgsin(t2)*osg::osgcos(dp) +
00949 osg::osgcos(t1)*osg::osgcos(t2);
00950 NdotL = (NdotL >= 0) ? NdotL : 0;
00951 color = diffuse * (NdotL + Const) +
00952 specular * osg::osgpow(NdotL, Shi);
00953
00954 for (int i=0; i<3; i++) {
00955 if (min>color[i]) min=color[i];
00956 if (max<color[i]) max=color[i];
00957
00958 color[i] = osg::osgClamp(0.f, (color[i]), 1.f);
00959 *ds++ = (osg::UInt8)(color[i]*255);
00960 }
00961 }
00962 }
00963 }
00964
00965 osg::endEditCP(image);
00966
00967 FDEBUG (( "calc phong map FINISH: clamped from [%f,%f] to [0,1]\n",
00968 min, max));
00969
00970 return true;
00971 }
00972
00973
00974
00977 OSG_SYSTEMLIB_DLLMAPPING
00978 bool OSG::createNormalizationCubeMap(std::vector<ImagePtr> imageVec,
00979 UInt32 size)
00980 {
00981 int i, j;
00982
00983 if (imageVec.size() < 6)
00984 {
00985 FFATAL(("Only %d images given - need six\n", imageVec.size()));
00986 return false;
00987 }
00988
00989 for (i=0; i<6; i++)
00990 {
00991 if (imageVec[i] == NullFC)
00992 {
00993 FFATAL(("Image[%d] is Null\n", i));
00994 return false;
00995 }
00996 }
00997
00998 unsigned char *data = NULL;
00999 Vec3f n;
01000
01001 size = osgnextpower2(size);
01002
01003 float size2 = size / 2.0f;
01004 float offset = 0.5f;
01005
01006 ImagePtr imagePosX = imageVec[0];
01007
01008
01009 beginEditCP( imagePosX );
01010 imagePosX->set(Image::OSG_RGB_PF, size, size);
01011 data = imagePosX->getData();
01012
01013 for (j=0; j<size; j++) {
01014 for (i=0; i<size; i++) {
01015
01016 n[0] = size2;
01017 n[1] = -((float)j + offset - size2);
01018 n[2] = -((float)i + offset - size2);
01019 n.normalize();
01020
01021 data[0] = (UInt8)(((n.x() + 1.f) / 2.f) * 255.f);
01022 data[1] = (UInt8)(((n.y() + 1.f) / 2.f) * 255.f);
01023 data[2] = (UInt8)(((n.z() + 1.f) / 2.f) * 255.f);
01024 data += 3;
01025 }
01026 }
01027 endEditCP( imagePosX );
01028
01029 ImagePtr imageNegX = imageVec[1];
01030
01031
01032 beginEditCP( imageNegX );
01033 imageNegX->set(Image::OSG_RGB_PF, size, size);
01034 data = imageNegX->getData();
01035
01036 for (j=0; j<size; j++) {
01037 for (i=0; i<size; i++) {
01038
01039 n[0] = -size2;
01040 n[1] = -((float)j + offset - size2);
01041 n[2] = ((float)i + offset - size2);
01042 n.normalize();
01043
01044 data[0]= (UInt8)(((n.x() + 1.f) / 2.f) * 255.f);
01045 data[1]= (UInt8)(((n.y() + 1.f) / 2.f) * 255.f);
01046 data[2]= (UInt8)(((n.z() + 1.f) / 2.f) * 255.f);
01047 data += 3;
01048 }
01049 }
01050 endEditCP( imageNegX );
01051
01052 ImagePtr imagePosY = imageVec[2];
01053
01054
01055 beginEditCP( imagePosY );
01056 imagePosY->set(Image::OSG_RGB_PF, size, size);
01057 data = imagePosY->getData();
01058
01059 for (j=0; j<size; j++) {
01060 for (i=0; i<size; i++) {
01061
01062 n[0] = ((float)i + offset - size2);
01063 n[1] = size2;
01064 n[2] = ((float)j + offset - size2);
01065 n.normalize();
01066
01067 data[0]= (UInt8)(((n.x() + 1.f) / 2.f) * 255.f);
01068 data[1]= (UInt8)(((n.y() + 1.f) / 2.f) * 255.f);
01069 data[2]= (UInt8)(((n.z() + 1.f) / 2.f) * 255.f);
01070 data += 3;
01071 }
01072 }
01073 endEditCP( imagePosY );
01074
01075 ImagePtr imageNegY = imageVec[3];
01076
01077
01078 beginEditCP( imageNegY );
01079 imageNegY->set(Image::OSG_RGB_PF, size, size);
01080 data = imageNegY->getData();
01081
01082 for (j=0; j<size; j++) {
01083 for (i=0; i<size; i++) {
01084
01085 n[0]= ((float)i + offset - size2);
01086 n[1]= -size2;
01087 n[2]= -((float)j + offset - size2);
01088 n.normalize();
01089
01090 data[0] = (UInt8)(((n.x() + 1.f) / 2.f) * 255.f);
01091 data[1] = (UInt8)(((n.y() + 1.f) / 2.f) * 255.f);
01092 data[2] = (UInt8)(((n.z() + 1.f) / 2.f) * 255.f);
01093 data += 3;
01094 }
01095 }
01096 endEditCP( imageNegY );
01097
01098 ImagePtr imagePosZ = imageVec[4];
01099
01100
01101 beginEditCP( imagePosZ );
01102 imagePosZ->set(Image::OSG_RGB_PF, size, size);
01103 data = imagePosZ->getData();
01104
01105 for (j=0; j<size; j++) {
01106 for (i=0; i<size; i++) {
01107
01108 n[0] = ((float)i + offset - size2);
01109 n[1] = -((float)j + offset - size2);
01110 n[2] = size2;
01111 n.normalize();
01112
01113 data[0] = (UInt8)(((n.x() + 1.f) / 2.f) * 255.f);
01114 data[1] = (UInt8)(((n.y() + 1.f) / 2.f) * 255.f);
01115 data[2] = (UInt8)(((n.z() + 1.f) / 2.f) * 255.f);
01116 data += 3;
01117 }
01118 }
01119 endEditCP( imagePosZ );
01120
01121 ImagePtr imageNegZ = imageVec[5];
01122
01123
01124 beginEditCP( imageNegZ );
01125 imageNegZ->set(Image::OSG_RGB_PF, size, size);
01126 data = imageNegZ->getData();
01127
01128 for (j=0; j<size; j++) {
01129 for (i=0; i<size; i++) {
01130
01131 n[0] = -((float)i + offset - size2);
01132 n[1] = -((float)j + offset - size2);
01133 n[2] = -size2;
01134 n.normalize();
01135
01136 data[0] = (UInt8)(((n.x() + 1.f) / 2.f) * 255.f);
01137 data[1] = (UInt8)(((n.y() + 1.f) / 2.f) * 255.f);
01138 data[2] = (UInt8)(((n.z() + 1.f) / 2.f) * 255.f);
01139 data += 3;
01140 }
01141 }
01142 endEditCP( imageNegZ );
01143
01144 return true;
01145 }
01146
01147
01148
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188 namespace
01189 {
01190
01191
01192 #define MAXB 0x100
01193
01194 Int32 p[MAXB + MAXB + 2];
01195 Real32 g3[MAXB + MAXB + 2][3];
01196 Real32 g2[MAXB + MAXB + 2][2];
01197 Real32 g1[MAXB + MAXB + 2];
01198 Int32 start = 1;
01199 Int32 B = 0x100;
01200 Int32 BM = 0xff;
01201
01202
01203 void setNoiseFrequency(Int32 frequency)
01204 {
01205 start = 1;
01206 B = frequency;
01207 BM = B-1;
01208 }
01209
01210 Real32 lerp(Real32 t, Real32 a, Real32 b)
01211 {
01212 return (1 - t) * a + t * b;
01213 }
01214
01215 Real32 sCurve(Real32 t)
01216 {
01217 return t * t * (3.0f - 2.0f * t);
01218 }
01219
01220 Real32 at2(Real32 *q, Real32 rx, Real32 ry)
01221 {
01222 return rx * q[0] + ry * q[1];
01223 }
01224
01225 Real32 at3(Real32 *q, Real32 rx, Real32 ry, Real32 rz)
01226 {
01227 return rx * q[0] + ry * q[1] + rz * q[2];
01228 }
01229
01230 void setup(Real32 *vec, UInt8 i,
01231 Real32 &t,
01232 Int32 &b0, Int32 &b1,
01233 Real32 &r0, Real32 &r1)
01234 {
01235 t = vec[i] + 0x1000;
01236 b0 = ((Int32)t) & BM;
01237 b1 = (b0 + 1) & BM;
01238 r0 = t - (Int32)t;
01239 r1 = r0 - 1.0f;
01240 }
01241
01242 void normalize2(Real32 v[2])
01243 {
01244 Real32 s = sqrt(v[0] * v[0] + v[1] * v[1]);
01245 v[0] = v[0] / s;
01246 v[1] = v[1] / s;
01247 }
01248
01249 void normalize3(Real32 v[3])
01250 {
01251 Real32 s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
01252 v[0] = v[0] / s;
01253 v[1] = v[1] / s;
01254 v[2] = v[2] / s;
01255 }
01256
01257 void init(void)
01258 {
01259 Int32 i, j, k;
01260
01261 srand(30757);
01262 for (i = 0 ; i < B ; i++)
01263 {
01264 p[i] = i;
01265 g1[i] = (Real32)((rand() % (B + B)) - B) / B;
01266
01267 for (j = 0 ; j < 2 ; j++)
01268 g2[i][j] = (Real32)((rand() % (B + B)) - B) / B;
01269 normalize2(g2[i]);
01270
01271 for (j = 0 ; j < 3 ; j++)
01272 g3[i][j] = (Real32)((rand() % (B + B)) - B) / B;
01273 normalize3(g3[i]);
01274 }
01275
01276 while (--i)
01277 {
01278 k = p[i];
01279 p[i] = p[j = rand() % B];
01280 p[j] = k;
01281 }
01282
01283 for (i = 0 ; i < B + 2 ; i++)
01284 {
01285 p[B + i] = p[i];
01286 g1[B + i] = g1[i];
01287 for (j = 0 ; j < 2 ; j++)
01288 g2[B + i][j] = g2[i][j];
01289 for (j = 0 ; j < 3 ; j++)
01290 g3[B + i][j] = g3[i][j];
01291 }
01292 }
01293
01294 Real32 noise1(Real32 vec[1])
01295 {
01296 Int32 bx0, bx1;
01297 Real32 rx0, rx1, sx, t, u, v;
01298
01299 if (start)
01300 {
01301 start = 0;
01302 init();
01303 }
01304
01305 setup(vec, 0, t, bx0, bx1, rx0, rx1);
01306
01307 sx = sCurve(rx0);
01308
01309 u = rx0 * g1[ p[ bx0 ] ];
01310 v = rx1 * g1[ p[ bx1 ] ];
01311
01312 return lerp(sx, u, v);
01313 }
01314
01315 Real32 noise2(Real32 vec[2])
01316 {
01317 Int32 bx0, bx1, by0, by1, b00, b10, b01, b11;
01318 Real32 rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
01319 Int32 i, j;
01320
01321 if (start)
01322 {
01323 start = 0;
01324 init();
01325 }
01326
01327 setup(vec, 0, t, bx0, bx1, rx0, rx1);
01328 setup(vec, 1, t, by0, by1, ry0, ry1);
01329
01330 i = p[ bx0 ];
01331 j = p[ bx1 ];
01332
01333 b00 = p[ i + by0 ];
01334 b10 = p[ j + by0 ];
01335 b01 = p[ i + by1 ];
01336 b11 = p[ j + by1 ];
01337
01338 sx = sCurve(rx0);
01339 sy = sCurve(ry0);
01340
01341 q = g2[ b00 ] ; u = at2(q, rx0,ry0);
01342 q = g2[ b10 ] ; v = at2(q, rx1,ry0);
01343 a = lerp(sx, u, v);
01344
01345 q = g2[ b01 ] ; u = at2(q, rx0,ry1);
01346 q = g2[ b11 ] ; v = at2(q, rx1,ry1);
01347 b = lerp(sx, u, v);
01348
01349 return lerp(sy, a, b);
01350 }
01351
01352 Real32 noise3(Real32 vec[3])
01353 {
01354 Int32 bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
01355 Real32 rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
01356 Int32 i, j;
01357
01358 if (start)
01359 {
01360 start = 0;
01361 init();
01362 }
01363
01364 setup(vec, 0, t, bx0, bx1, rx0, rx1);
01365 setup(vec, 1, t, by0, by1, ry0, ry1);
01366 setup(vec, 2, t, bz0, bz1, rz0, rz1);
01367
01368 i = p[ bx0 ];
01369 j = p[ bx1 ];
01370
01371 b00 = p[ i + by0 ];
01372 b10 = p[ j + by0 ];
01373 b01 = p[ i + by1 ];
01374 b11 = p[ j + by1 ];
01375
01376 t = sCurve(rx0);
01377 sy = sCurve(ry0);
01378 sz = sCurve(rz0);
01379
01380 q = g3[ b00 + bz0 ] ; u = at3(q, rx0,ry0,rz0);
01381 q = g3[ b10 + bz0 ] ; v = at3(q, rx1,ry0,rz0);
01382 a = lerp(t, u, v);
01383
01384 q = g3[ b01 + bz0 ] ; u = at3(q, rx0,ry1,rz0);
01385 q = g3[ b11 + bz0 ] ; v = at3(q, rx1,ry1,rz0);
01386 b = lerp(t, u, v);
01387
01388 c = lerp(sy, a, b);
01389
01390 q = g3[ b00 + bz1 ] ; u = at3(q, rx0,ry0,rz1);
01391 q = g3[ b10 + bz1 ] ; v = at3(q, rx1,ry0,rz1);
01392 a = lerp(t, u, v);
01393
01394 q = g3[ b01 + bz1 ] ; u = at3(q, rx0,ry1,rz1);
01395 q = g3[ b11 + bz1 ] ; v = at3(q, rx1,ry1,rz1);
01396 b = lerp(t, u, v);
01397
01398 d = lerp(sy, a, b);
01399
01400 return lerp(sz, c, d);
01401 }
01402
01403 Real32 noise(Real32 vec[], Int32 len)
01404 {
01405
01406 switch (len)
01407 {
01408 case 1: return noise1(vec);
01409 case 2: return noise2(vec);
01410 case 3: return noise3(vec);
01411 case 0:
01412 default: return 0.0f;
01413 }
01414 }
01415
01416 };
01417
01418
01423 OSG_SYSTEMLIB_DLLMAPPING
01424 bool OSG::createNoise(ImagePtr image,
01425 Image::PixelFormat pixelformat,
01426 UInt16 numOctaves,
01427 UInt16 size,
01428 UInt8 dim,
01429 bool splitOctaves)
01430 {
01431 Int32 f, i, j, k, c, w, h, mult = 1, frequency = 4;
01432 Real32 ni[3], amp = 0.5, inci, incj, inck;
01433 unsigned char *data, *ptr = NULL;
01434 bool ok = true;
01435
01436 if (image == NullFC)
01437 {
01438 FFATAL (("No output image given\n"));
01439 return false;
01440 }
01441
01442 switch (dim)
01443 {
01444 case 1:
01445 ok = image->set(pixelformat, size);
01446 w = h = 1;
01447 break;
01448 case 2:
01449 ok = image->set(pixelformat, size, size);
01450 w = size;
01451 h = 1;
01452 break;
01453 case 3:
01454 ok = image->set(pixelformat, size, size, size);
01455 w = h = size;
01456 break;
01457 default:
01458 ok = image->set(pixelformat, size, size);
01459 dim = 2;
01460 w = size;
01461 h = 1;
01462 FWARNING(("createNoise: Use [1|2|3] for image dimension (default 2)\n"));
01463 break;
01464 }
01465
01466 if ( ! (ok && (data = image->getData())) )
01467 {
01468 FFATAL(("createNoise: Could not create image\n"));
01469 return false;
01470 }
01471
01472 UInt16 ncomp = image->getComponents();
01473
01474 if(splitOctaves && numOctaves > ncomp)
01475 {
01476 FWARNING(("createNoise: try to split %d octaves, but only have %d"
01477 " components!\n", numOctaves, ncomp ));
01478 numOctaves = ncomp;
01479 }
01480
01481 for (f=0; f<numOctaves; ++f, frequency*=2, amp*=0.5)
01482 {
01483 ptr = data;
01484
01485 setNoiseFrequency(frequency);
01486 ni[0] = ni[1] = ni[2] = 0;
01487 inci = 1.0 / (size / (Real32)frequency);
01488 incj = 1.0 / (size / (Real32)frequency);
01489 inck = 1.0 / (size / (Real32)frequency);
01490
01491 for (i=0; i<size; ++i, ni[0]+=inci)
01492 {
01493 for (j=0; j<w; ++j, ni[1]+=incj)
01494 {
01495 for (k=0; k<h; ++k, ni[2]+=inck)
01496 {
01497
01498 if (splitOctaves)
01499 {
01500 *(ptr+f) = (UInt8)(((noise(ni, dim) + 1) * amp) * 128.0);
01501
01502 ptr+=ncomp;
01503 }
01504 else
01505 {
01506 for(c = 0; c < ncomp; ++c, ++ptr, ni[0] += 1)
01507 (*ptr) += (UInt8)(((noise(ni, dim) + 1) * amp) * 128.0);
01508
01509 ni[0] -= ncomp;
01510 }
01511 }
01512 }
01513 }
01514 FNOTICE(("Generated %dD noise: octave %d/%d...\n", dim, f+1, numOctaves));
01515 }
01516
01517 return true;
01518 }
01519