00001 // $Id: noise1.cpp 751 2006-03-31 15:43:49Z alex $ 00002 // noise1.cpp 00003 // 00004 // Author : Mike 00005 // Purpose : Implemetation of low level noise function calls. 00006 // It uses a quadratic B-Spline instead of the cubic Hermite interpolant 00007 // implied by Perlin. Also note that DNoise is just the x, y, and z 00008 // derivatives of Noise (which are also B-Splines). 00009 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00010 ================================XARAHEADERSTART=========================== 00011 00012 Xara LX, a vector drawing and manipulation program. 00013 Copyright (C) 1993-2006 Xara Group Ltd. 00014 Copyright on certain contributions may be held in joint with their 00015 respective authors. See AUTHORS file for details. 00016 00017 LICENSE TO USE AND MODIFY SOFTWARE 00018 ---------------------------------- 00019 00020 This file is part of Xara LX. 00021 00022 Xara LX is free software; you can redistribute it and/or modify it 00023 under the terms of the GNU General Public License version 2 as published 00024 by the Free Software Foundation. 00025 00026 Xara LX and its component source files are distributed in the hope 00027 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00028 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00029 See the GNU General Public License for more details. 00030 00031 You should have received a copy of the GNU General Public License along 00032 with Xara LX (see the file GPL in the root directory of the 00033 distribution); if not, write to the Free Software Foundation, Inc., 51 00034 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00035 00036 00037 ADDITIONAL RIGHTS 00038 ----------------- 00039 00040 Conditional upon your continuing compliance with the GNU General Public 00041 License described above, Xara Group Ltd grants to you certain additional 00042 rights. 00043 00044 The additional rights are to use, modify, and distribute the software 00045 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00046 library and any other such library that any version of Xara LX relased 00047 by Xara Group Ltd requires in order to compile and execute, including 00048 the static linking of that library to XaraLX. In the case of the 00049 "CDraw" library, you may satisfy obligation under the GNU General Public 00050 License to provide source code by providing a binary copy of the library 00051 concerned and a copy of the license accompanying it. 00052 00053 Nothing in this section restricts any of the rights you have under 00054 the GNU General Public License. 00055 00056 00057 SCOPE OF LICENSE 00058 ---------------- 00059 00060 This license applies to this program (XaraLX) and its constituent source 00061 files only, and does not necessarily apply to other Xara products which may 00062 in part share the same code base, and are subject to their own licensing 00063 terms. 00064 00065 This license does not apply to files in the wxXtra directory, which 00066 are built into a separate library, and are subject to the wxWindows 00067 license contained within that directory in the file "WXXTRA-LICENSE". 00068 00069 This license does not apply to the binary libraries (if any) within 00070 the "libs" directory, which are subject to a separate license contained 00071 within that directory in the file "LIBS-LICENSE". 00072 00073 00074 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00075 ---------------------------------------------- 00076 00077 Subject to the terms of the GNU Public License (see above), you are 00078 free to do whatever you like with your modifications. However, you may 00079 (at your option) wish contribute them to Xara's source tree. You can 00080 find details of how to do this at: 00081 http://www.xaraxtreme.org/developers/ 00082 00083 Prior to contributing your modifications, you will need to complete our 00084 contributor agreement. This can be found at: 00085 http://www.xaraxtreme.org/developers/contribute/ 00086 00087 Please note that Xara will not accept modifications which modify any of 00088 the text between the start and end of this header (marked 00089 XARAHEADERSTART and XARAHEADEREND). 00090 00091 00092 MARKS 00093 ----- 00094 00095 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00096 designs are registered or unregistered trademarks, design-marks, and/or 00097 service marks of Xara Group Ltd. All rights in these marks are reserved. 00098 00099 00100 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00101 http://www.xara.com/ 00102 00103 =================================XARAHEADEREND============================ 00104 */ 00105 00106 // Version : 1.0 00107 // Started : 20/01/96 00108 00109 #include "camtypes.h" 00110 #include "macros.h" 00111 #include "vector3d.h" 00112 #include "noisebas.h" 00113 #include "noise1.h" 00114 00115 #define TABLEWIDTH 50 // we can reduce this at the expense 00116 #define MAXPTS (TABLEWIDTH*TABLEWIDTH) // of randomness. 00117 00118 /************************************************************************************** 00119 > NoiseGen1::NoiseGen1() 00120 ***************************************************************************************/ 00121 00122 NoiseGen1::NoiseGen1() 00123 { 00124 RTable=NULL; 00125 } 00126 00127 /************************************************************************************** 00128 > NoiseGen1::~NoiseGen1() 00129 ***************************************************************************************/ 00130 00131 NoiseGen1::~NoiseGen1() 00132 { 00133 if (RTable!=NULL) 00134 { 00135 free((void*)RTable); 00136 RTable=NULL; 00137 } 00138 } 00139 00140 /************************************************************************************** 00141 00142 > virtual BOOL NoiseGen1::Initialise() 00143 00144 Aurthor: Mike 00145 Created: 07/07/96 00146 Purpose: Initialise all the data tables we need to get this noise generator 00147 going. This particular table holds random float values in the range 00148 [0..1] 00149 00150 ***************************************************************************************/ 00151 00152 BOOL NoiseGen1::Initialise() 00153 { 00154 // allocate some space big enough 00155 RTable = (float*)malloc(MAXPTS * sizeof(float)); 00156 if (RTable==NULL) 00157 return FALSE; 00158 00159 // create the table 00160 SeedTable(0); 00161 return TRUE; 00162 } 00163 00164 00165 /************************************************************************************** 00166 00167 > void NoiseGen1::SeedTable(UINT32 seed) 00168 00169 Aurthor: Mike 00170 Created: 07/07/96 00171 Inputs: seed = the seed to use as an initial value in our random number table 00172 Purpose: Seed the random number table we use. 00173 00174 ***************************************************************************************/ 00175 00176 void NoiseGen1::SeedTable(UINT32 seed) 00177 { 00178 if (RTable!=NULL) 00179 { 00180 // seed the random number generator for consitency 00181 srand(seed); 00182 // now create those random impulses! 00183 // ok I'm assuming rand() will be compiled in and not a opsys level call. 00184 for (INT32 i=0; i<MAXPTS; i++) 00185 RTable[i] = (float)rand() / ((float)RAND_MAX); 00186 } 00187 } 00188 00189 00190 /************************************************************************************** 00191 00192 > double NoiseGen1::VNoise1D(const Vector3D &p, double scale) 00193 00194 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00195 Created: 27/01/97 00196 Inputs: p = a three dimensional vector 00197 scale = a scaling factor 00198 Returns: A double f, 0<=f<=1.0 00199 00200 Notes: Uses 2d quadratic B-Spline smoothing 00201 00202 1d quadratic bsplines are defined as... 00203 00204 C0 = 1 - 2u + u^2 00205 C1 = 1 + 2u - 2u^2 00206 C2 = u^2 00207 00208 v = (C0*p0 + C1*p1 + C2*p2)/2 0<=u<=1 00209 00210 Note, this spline is a none-interpolating spline, i.e. it tends towards 00211 the points but never passes through any! This doesn't matter to us as 00212 we're interpolating random impulses. 00213 To make our tile cyclic, wrap coordinates at the edges. 00214 Also note, give points { p0,p1,p2 } the curve lives in the region [p0,p1] 00215 i.e. it is does not cover all p0..p2. To get segment [p1,p2] you'll 00216 need { p1,p2,p3 } 00217 Calculating the cyclic curve through p0,p1,p2,p3 00218 fit... 00219 [p0,p1] = CF{ p0,p1,p2 } 00220 [p1,p2] = CF{ p1,p2,p3 } 00221 [p2,p3] = CF{ p2,p3,p0 } 00222 [P3,P0] = CF{ p3,p0,p1 } 00223 i.e. 4 input points = 4 curves = 4 intervals 00224 00225 ***************************************************************************************/ 00226 00227 double NoiseGen1::VNoise1D(const Vector3D &p, double scale) 00228 { 00229 float x2, x1, x0, y2, y1, y0, xf, yf; 00230 float p00, p01, p02; 00231 INT32 ax, bx, cx; 00232 INT32 ay, by, cy; 00233 INT32 samplerange; 00234 00235 // multiplying by TABLEWIDTH rather than (TABLEWIDTH-1) 00236 // forces a wrapping as our range is 0..TABLEWIDTH-1 00237 samplerange = (INT32)(scale); // *TABLEWIDTH); 00238 00239 if (samplerange<1) 00240 return 0.0; 00241 00242 // essentially ignore p.z (the calling routine sets it to 0) 00243 xf = ((float)p.x) * samplerange; 00244 yf = ((float)p.y) * samplerange; 00245 00246 // index the 9 random impulses we'll used for (xf,yf) 00247 ax = (INT32)floor(xf); 00248 ay = (INT32)floor(yf); 00249 00250 // calculate the 2d bspline blending coefs 00251 xf = xf - ax; // u (i.e. fract(p.x) 0..1) 00252 yf = yf - ay; // v (i.e. fract(p.y) 0..1) 00253 x1 = xf * xf; // u^2 00254 y1 = yf * yf; // v^2 00255 x2 = 0.5f * x1; // u^2/2 00256 y2 = 0.5f * y1; // v^2/2 00257 x1 = 0.5f + xf - x1; // 0.5 + u - u^2 00258 y1 = 0.5f + yf - y1; // 0.5 + v - v^2 00259 x0 = 0.5f - xf + x2; // 0.5 - u + u^2/2 00260 y0 = 0.5f - yf + y2; // 0.5 - v + v^2/2 00261 00262 // get the next neighbours 00263 bx = ax + 1; 00264 by = ay + 1; 00265 cx = bx + 1; 00266 cy = by + 1; 00267 00268 // do a potential double modulus as follows... 00269 // 00270 // 0 1 2 3 4 5 6 7 8 9 a b c d e f index into impulse table 00271 // 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 ... samplerange == 8 00272 // 0 1 2 3 4 0 1 2 0 1 2 3 4 0 1 2 ... tablewidth == 5 00273 // ^ ^ 00274 // notice the important symmetry of the values at either end of sample range 00275 // this gives tileable noise. 00276 00277 ax = ax % samplerange; // all 0 if samplerange == 1 00278 ay = ay % samplerange; 00279 bx = bx % samplerange; 00280 by = by % samplerange; 00281 cx = cx % samplerange; 00282 cy = cy % samplerange; 00283 00284 if (samplerange==1) // do something at zero if poss 00285 cx=cy=1; 00286 00287 if (TABLEWIDTH<samplerange) 00288 { 00289 // if our random impulse table is smaller than samplerange 00290 // then we need to mod into it. 00291 ax = ax % TABLEWIDTH; 00292 ay = ay % TABLEWIDTH; 00293 bx = bx % TABLEWIDTH; 00294 by = by % TABLEWIDTH; 00295 cx = cx % TABLEWIDTH; 00296 cy = cy % TABLEWIDTH; 00297 } 00298 00299 ay*=TABLEWIDTH; 00300 by*=TABLEWIDTH; 00301 cy*=TABLEWIDTH; 00302 00303 // read and interpolate the impulse values 00304 p00 = RTable[ax+ay]; 00305 p01 = RTable[bx+ay]; 00306 p02 = RTable[cx+ay]; 00307 00308 xf = y0 * (x0*p00 + x1*p01 + x2*p02); 00309 00310 p00 = RTable[ax+by]; 00311 p01 = RTable[bx+by]; 00312 p02 = RTable[cx+by]; 00313 00314 xf += y1 * (x0*p00 + x1*p01 + x2*p02); 00315 00316 p00 = RTable[ax+cy]; 00317 p01 = RTable[bx+cy]; 00318 p02 = RTable[cx+cy]; 00319 00320 xf += y2 * (x0*p00 + x1*p01 + x2*p02); 00321 00322 return (double)xf; 00323 } 00324 00325 00326 /* 00327 double NoiseGen1::VNoise1D(const Vector3D &p, double scale) 00328 { 00329 float x2, x1, x0, y2, y1, y0, xf, yf; 00330 float p00, p01, p02; 00331 INT32 ax, bx, cx; 00332 INT32 ay, by, cy; 00333 INT32 width; 00334 00335 width = (INT32)(scale); 00336 00337 // essentially ignore p.z (the calling routine sets it to 0) 00338 xf = ((float)p.x) * width; 00339 yf = ((float)p.y) * width; 00340 00341 // index the 9 random impulses we'll used for (xf,yf) 00342 ax = (INT32)floor(xf); 00343 ay = (INT32)floor(yf); 00344 bx = ax+1; 00345 by = ay+1; 00346 cx = bx+1; 00347 cy = by+1; 00348 00349 // modulo the width we're using 00350 if (cx>=width) 00351 { 00352 cx-=width; 00353 if (bx>=width) 00354 { 00355 bx-=width; 00356 if (ax>=width) 00357 ax-=width; 00358 } 00359 } 00360 00361 if (cy>=width) 00362 { 00363 cy-=width; 00364 if (by>=width) 00365 { 00366 by-=width; 00367 if (ay>=width) 00368 ay-=width; 00369 } 00370 } 00371 00372 // calculate the 2d bspline blending coefs 00373 00374 xf = xf - ax; // u (i.e. fract(p.x) 0..1) 00375 yf = yf - ay; // v (i.e. fract(p.y) 0..1) 00376 x1 = xf * xf; // u^2 00377 y1 = yf * yf; // v^2 00378 x2 = 0.5f * x1; // u^2/2 00379 y2 = 0.5f * y1; // v^2/2 00380 x1 = 0.5f + xf - x1; // 0.5 + u - u^2 00381 y1 = 0.5f + yf - y1; // 0.5 + v - v^2 00382 x0 = 0.5f - xf + x2; // 0.5 - u + u^2/2 00383 y0 = 0.5f - yf + y2; // 0.5 - v + v^2/2 00384 00385 ay*=TABLEWIDTH; 00386 by*=TABLEWIDTH; 00387 cy*=TABLEWIDTH; 00388 00389 // read and interpolate the impulse values 00390 p00 = RTable[ax+ay]; 00391 p01 = RTable[bx+ay]; 00392 p02 = RTable[cx+ay]; 00393 00394 xf = y0 * (x0*p00 + x1*p01 + x2*p02); 00395 00396 p00 = RTable[ax+by]; 00397 p01 = RTable[bx+by]; 00398 p02 = RTable[cx+by]; 00399 00400 xf += y1 * (x0*p00 + x1*p01 + x2*p02); 00401 00402 p00 = RTable[ax+cy]; 00403 p01 = RTable[bx+cy]; 00404 p02 = RTable[cx+cy]; 00405 00406 xf += y2 * (x0*p00 + x1*p01 + x2*p02); 00407 00408 return (double)xf; 00409 } 00410 */ 00411 00412 /************************************************************************************** 00413 00414 > Vector3D NoiseGen1::VNoise3D(const Vector3D &v) 00415 00416 Purpose: Vector-valued version of "Noise" 00417 00418 ***************************************************************************************/ 00419 00420 Vector3D NoiseGen1::VNoise3D(const Vector3D &p) 00421 { 00422 return Vector3D(0,0,0); 00423 }