1bc679b60SStephan Aßmus /* 2bc679b60SStephan Aßmus * Copyright 2006, Haiku. 3bc679b60SStephan Aßmus * Copyright (c) 1997 by Massimino Pascal <Pascal.Massimon@ens.fr> 4bc679b60SStephan Aßmus * 5bc679b60SStephan Aßmus * Distributed under the terms of the MIT License. 6bc679b60SStephan Aßmus * 7bc679b60SStephan Aßmus * Authors: 8bc679b60SStephan Aßmus * Massimino Pascal <Pascal.Massimon@ens.fr> 9bc679b60SStephan Aßmus * Stephan Aßmus <superstippi@gmx.de> 10bc679b60SStephan Aßmus */ 11bc679b60SStephan Aßmus 12bc679b60SStephan Aßmus /*! When shown ifs, Diana Rose (4 years old) said, "It looks like dancing." 13bc679b60SStephan Aßmus */ 14bc679b60SStephan Aßmus 15bc679b60SStephan Aßmus #include "IFS.h" 16bc679b60SStephan Aßmus 17bc679b60SStephan Aßmus #include <new> 18bc679b60SStephan Aßmus #include <malloc.h> 19bc679b60SStephan Aßmus #include <stdio.h> 20bc679b60SStephan Aßmus #include <string.h> 21bc679b60SStephan Aßmus 22bc679b60SStephan Aßmus #include <Bitmap.h> 23bc679b60SStephan Aßmus #include <OS.h> 24bc679b60SStephan Aßmus #include <Screen.h> 25bc679b60SStephan Aßmus #include <View.h> 26bc679b60SStephan Aßmus 27bc679b60SStephan Aßmus #include <unistd.h> // for getpid() 28bc679b60SStephan Aßmus #include <sys/time.h> // for gettimeofday() 29bc679b60SStephan Aßmus 30bc679b60SStephan Aßmus using std::nothrow; 31bc679b60SStephan Aßmus 32bc679b60SStephan Aßmus #define HALF 0 33bc679b60SStephan Aßmus 34bc679b60SStephan Aßmus // The following 'random' numbers are taken from CRC, 18th Edition, page 622. 35bc679b60SStephan Aßmus // Each array element was taken from the corresponding line in the table, 36bc679b60SStephan Aßmus // except that a[0] was from line 100. 8s and 9s in the table were simply 37bc679b60SStephan Aßmus // skipped. The high order digit was taken mod 4. 38bc679b60SStephan Aßmus 39bc679b60SStephan Aßmus #define VectorSize 55 40bc679b60SStephan Aßmus static unsigned int a[VectorSize] = { 41bc679b60SStephan Aßmus 035340171546, 010401501101, 022364657325, 024130436022, 002167303062, // 5 42bc679b60SStephan Aßmus 037570375137, 037210607110, 016272055420, 023011770546, 017143426366, // 10 43bc679b60SStephan Aßmus 014753657433, 021657231332, 023553406142, 004236526362, 010365611275, // 14 44bc679b60SStephan Aßmus 007117336710, 011051276551, 002362132524, 001011540233, 012162531646, // 20 45bc679b60SStephan Aßmus 007056762337, 006631245521, 014164542224, 032633236305, 023342700176, // 25 46bc679b60SStephan Aßmus 002433062234, 015257225043, 026762051606, 000742573230, 005366042132, // 30 47bc679b60SStephan Aßmus 012126416411, 000520471171, 000725646277, 020116577576, 025765742604, // 35 48bc679b60SStephan Aßmus 007633473735, 015674255275, 017555634041, 006503154145, 021576344247, // 40 49bc679b60SStephan Aßmus 014577627653, 002707523333, 034146376720, 030060227734, 013765414060, // 45 50bc679b60SStephan Aßmus 036072251540, 007255221037, 024364674123, 006200353166, 010126373326, // 50 51bc679b60SStephan Aßmus 015664104320, 016401041535, 016215305520, 033115351014, 017411670323 // 55 52bc679b60SStephan Aßmus }; 53bc679b60SStephan Aßmus 54bc679b60SStephan Aßmus static int i1, i2; 55bc679b60SStephan Aßmus 56bc679b60SStephan Aßmus // ya_random 57bc679b60SStephan Aßmus unsigned int 58bc679b60SStephan Aßmus ya_random (void) 59bc679b60SStephan Aßmus { 60bc679b60SStephan Aßmus register int ret = a[i1] + a[i2]; 61bc679b60SStephan Aßmus a[i1] = ret; 62bc679b60SStephan Aßmus if (++i1 >= VectorSize) i1 = 0; 63bc679b60SStephan Aßmus if (++i2 >= VectorSize) i2 = 0; 64bc679b60SStephan Aßmus return ret; 65bc679b60SStephan Aßmus } 66bc679b60SStephan Aßmus 67bc679b60SStephan Aßmus // ya_rand_init 68bc679b60SStephan Aßmus void 69bc679b60SStephan Aßmus ya_rand_init(unsigned int seed) 70bc679b60SStephan Aßmus { 71bc679b60SStephan Aßmus int i; 72bc679b60SStephan Aßmus if (seed == 0) 73bc679b60SStephan Aßmus { 74bc679b60SStephan Aßmus struct timeval tp; 75bc679b60SStephan Aßmus struct timezone tzp; 76bc679b60SStephan Aßmus gettimeofday(&tp, &tzp); 77bc679b60SStephan Aßmus /* ignore overflow */ 78bc679b60SStephan Aßmus seed = (999*tp.tv_sec) + (1001*tp.tv_usec) + (1003 * getpid()); 79bc679b60SStephan Aßmus } 80bc679b60SStephan Aßmus 81bc679b60SStephan Aßmus a[0] += seed; 82bc679b60SStephan Aßmus for (i = 1; i < VectorSize; i++) 83bc679b60SStephan Aßmus { 84bc679b60SStephan Aßmus seed = a[i-1]*1001 + seed*999; 85bc679b60SStephan Aßmus a[i] += seed; 86bc679b60SStephan Aßmus } 87bc679b60SStephan Aßmus 88bc679b60SStephan Aßmus i1 = a[0] % VectorSize; 89bc679b60SStephan Aßmus i2 = (i1 + 024) % VectorSize; 90bc679b60SStephan Aßmus } 91bc679b60SStephan Aßmus 92bc679b60SStephan Aßmus #define random() ya_random() 93bc679b60SStephan Aßmus #define RAND_MAX 0xFFFFFFFF 94bc679b60SStephan Aßmus 95bc679b60SStephan Aßmus #define FLOAT_TO_INT(x) (int32)( (float)(UNIT)*(x) ) 96bc679b60SStephan Aßmus 97bc679b60SStephan Aßmus #define LRAND() ((long) (random() & 0x7fffffff)) 98bc679b60SStephan Aßmus #define NRAND(n) ((int) (LRAND() % (n))) 99bc679b60SStephan Aßmus #define MAXRAND (2147483648.0) // unsigned 1<<31 as a float 100bc679b60SStephan Aßmus #define SRAND(n) // already seeded by screenhack.c TODO: ?!? is it? 101bc679b60SStephan Aßmus 102bc679b60SStephan Aßmus 103bc679b60SStephan Aßmus // gauss_rand 104bc679b60SStephan Aßmus static float 105bc679b60SStephan Aßmus gauss_rand(float c, float A, float S) 106bc679b60SStephan Aßmus { 107bc679b60SStephan Aßmus float y; 108bc679b60SStephan Aßmus 109bc679b60SStephan Aßmus y = (float) LRAND() / MAXRAND; 110bc679b60SStephan Aßmus y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); 111bc679b60SStephan Aßmus if (NRAND(2)) 112bc679b60SStephan Aßmus return (c + y); 113bc679b60SStephan Aßmus return (c - y); 114bc679b60SStephan Aßmus } 115bc679b60SStephan Aßmus 116bc679b60SStephan Aßmus // half_gauss_rand 117bc679b60SStephan Aßmus static float 118bc679b60SStephan Aßmus half_gauss_rand(float c, float A, float S) 119bc679b60SStephan Aßmus { 120bc679b60SStephan Aßmus float y; 121bc679b60SStephan Aßmus 122bc679b60SStephan Aßmus y = (float) LRAND() / MAXRAND; 123bc679b60SStephan Aßmus y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); 124bc679b60SStephan Aßmus return (c + y); 125bc679b60SStephan Aßmus } 126bc679b60SStephan Aßmus 127bc679b60SStephan Aßmus // transform 128bc679b60SStephan Aßmus inline void 129bc679b60SStephan Aßmus transform(SIMI* Simi, int32 xo, int32 yo, int32* x, int32* y) 130bc679b60SStephan Aßmus { 131bc679b60SStephan Aßmus int32 xx, yy; 132bc679b60SStephan Aßmus 133bc679b60SStephan Aßmus xo = xo - Simi->Cx; 134bc679b60SStephan Aßmus xo = (xo * Simi->R) / UNIT; 135bc679b60SStephan Aßmus yo = yo - Simi->Cy; 136bc679b60SStephan Aßmus yo = (yo * Simi->R) / UNIT; 137bc679b60SStephan Aßmus 138bc679b60SStephan Aßmus xx = xo - Simi->Cx; 139bc679b60SStephan Aßmus xx = (xx * Simi->R2) / UNIT; 140bc679b60SStephan Aßmus yy = -yo - Simi->Cy; 141bc679b60SStephan Aßmus yy = (yy * Simi->R2) / UNIT; 142bc679b60SStephan Aßmus 143bc679b60SStephan Aßmus *x = ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2) / UNIT) + Simi->Cx; 144bc679b60SStephan Aßmus *y = ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2) / UNIT) + Simi->Cy; 145bc679b60SStephan Aßmus } 146bc679b60SStephan Aßmus 147bc679b60SStephan Aßmus 148bc679b60SStephan Aßmus // constructor 149bc679b60SStephan Aßmus IFS::IFS(BRect bounds) 1507bcfb215SJohn Scipione : 1517bcfb215SJohn Scipione fRoot(NULL), 1527bcfb215SJohn Scipione fCurrentFractal(NULL), 1537bcfb215SJohn Scipione fPointBuffer(NULL), 1547bcfb215SJohn Scipione fCurrentPoint(0), 155bc679b60SStephan Aßmus fAdditive(false), 156bc679b60SStephan Aßmus fCurrentMarkValue(1) 157bc679b60SStephan Aßmus { 158*e443b44aSStephan Aßmus if (!bounds.IsValid()) 159*e443b44aSStephan Aßmus return; 160*e443b44aSStephan Aßmus 161bc679b60SStephan Aßmus ya_rand_init(system_time()); 162bc679b60SStephan Aßmus 163bc679b60SStephan Aßmus int i; 164bc679b60SStephan Aßmus FRACTAL *Fractal; 165bc679b60SStephan Aßmus 166bc679b60SStephan Aßmus if (fRoot == NULL) { 167bc679b60SStephan Aßmus fRoot = (FRACTAL*) calloc(1, sizeof (FRACTAL)); 168bc679b60SStephan Aßmus if (fRoot == NULL) 169bc679b60SStephan Aßmus return; 170bc679b60SStephan Aßmus } 171bc679b60SStephan Aßmus Fractal = fRoot; 172bc679b60SStephan Aßmus 173bc679b60SStephan Aßmus _FreeBuffers(Fractal); 174bc679b60SStephan Aßmus i = (NRAND(4)) + 2; // Number of centers 175bc679b60SStephan Aßmus switch (i) { 176bc679b60SStephan Aßmus case 3: 177bc679b60SStephan Aßmus Fractal->Depth = fAdditive ? MAX_DEPTH_3 + 1 : MAX_DEPTH_3; 178bc679b60SStephan Aßmus Fractal->r_mean = .6; 179bc679b60SStephan Aßmus Fractal->dr_mean = .4; 180bc679b60SStephan Aßmus Fractal->dr2_mean = .3; 181bc679b60SStephan Aßmus break; 182bc679b60SStephan Aßmus 183bc679b60SStephan Aßmus case 4: 184bc679b60SStephan Aßmus Fractal->Depth = MAX_DEPTH_4; 185bc679b60SStephan Aßmus Fractal->r_mean = .5; 186bc679b60SStephan Aßmus Fractal->dr_mean = .4; 187bc679b60SStephan Aßmus Fractal->dr2_mean = .3; 188bc679b60SStephan Aßmus break; 189bc679b60SStephan Aßmus 190bc679b60SStephan Aßmus case 5: 191bc679b60SStephan Aßmus Fractal->Depth = MAX_DEPTH_5; 192bc679b60SStephan Aßmus Fractal->r_mean = .5; 193bc679b60SStephan Aßmus Fractal->dr_mean = .4; 194bc679b60SStephan Aßmus Fractal->dr2_mean = .3; 195bc679b60SStephan Aßmus break; 196bc679b60SStephan Aßmus 197bc679b60SStephan Aßmus case 2: 19852a95e6fSJohn Scipione default: 199bc679b60SStephan Aßmus Fractal->Depth = fAdditive ? MAX_DEPTH_2 + 1 : MAX_DEPTH_2; 200bc679b60SStephan Aßmus Fractal->r_mean = .7; 201bc679b60SStephan Aßmus Fractal->dr_mean = .3; 202bc679b60SStephan Aßmus Fractal->dr2_mean = .4; 203bc679b60SStephan Aßmus break; 204bc679b60SStephan Aßmus } 205bc679b60SStephan Aßmus // fprintf( stderr, "N=%d\n", i ); 206bc679b60SStephan Aßmus Fractal->Nb_Simi = i; 207bc679b60SStephan Aßmus Fractal->Max_Pt = Fractal->Nb_Simi - 1; 208bc679b60SStephan Aßmus for (i = 0; i <= Fractal->Depth + 2; ++i) 209bc679b60SStephan Aßmus Fractal->Max_Pt *= Fractal->Nb_Simi; 210bc679b60SStephan Aßmus 211bc679b60SStephan Aßmus if ((Fractal->buffer1 = (Point *) calloc(Fractal->Max_Pt, 212bc679b60SStephan Aßmus sizeof (Point))) == NULL) { 213bc679b60SStephan Aßmus _FreeIFS(Fractal); 214bc679b60SStephan Aßmus return; 215bc679b60SStephan Aßmus } 216bc679b60SStephan Aßmus if ((Fractal->buffer2 = (Point *) calloc(Fractal->Max_Pt, 217bc679b60SStephan Aßmus sizeof (Point))) == NULL) { 218bc679b60SStephan Aßmus _FreeIFS(Fractal); 219bc679b60SStephan Aßmus return; 220bc679b60SStephan Aßmus } 221bc679b60SStephan Aßmus Fractal->Speed = 6; 222bc679b60SStephan Aßmus #if HALF 223bc679b60SStephan Aßmus Fractal->Width = bounds.IntegerWidth() / 2 + 1; 224bc679b60SStephan Aßmus Fractal->Height = bounds.IntegerHeight() / 2 + 1; 225bc679b60SStephan Aßmus #else 226bc679b60SStephan Aßmus Fractal->Width = bounds.IntegerWidth() + 1; 227bc679b60SStephan Aßmus Fractal->Height = bounds.IntegerHeight() + 1; 228bc679b60SStephan Aßmus #endif 229bc679b60SStephan Aßmus Fractal->Cur_Pt = 0; 230bc679b60SStephan Aßmus Fractal->Count = 0; 231bc679b60SStephan Aßmus Fractal->Lx = (Fractal->Width - 1) / 2; 232bc679b60SStephan Aßmus Fractal->Ly = (Fractal->Height - 1) / 2; 233bc679b60SStephan Aßmus Fractal->Col = NRAND(Fractal->Width * Fractal->Height - 1) + 1; 234bc679b60SStephan Aßmus 235bc679b60SStephan Aßmus _RandomSimis(Fractal, Fractal->Components, 5 * MAX_SIMI); 236bc679b60SStephan Aßmus 237bc679b60SStephan Aßmus delete Fractal->bitmap; 238bc679b60SStephan Aßmus Fractal->bitmap = new (nothrow) BBitmap(BRect(0.0, 0.0, 239bc679b60SStephan Aßmus Fractal->Width - 1, 240bc679b60SStephan Aßmus Fractal->Height - 1), 241bc679b60SStephan Aßmus 0, 242bc679b60SStephan Aßmus B_RGB32); 243bc679b60SStephan Aßmus delete Fractal->markBitmap; 244bc679b60SStephan Aßmus Fractal->markBitmap = new (nothrow) BBitmap(BRect(0.0, 0.0, 245bc679b60SStephan Aßmus Fractal->Width - 1, 246bc679b60SStephan Aßmus Fractal->Height - 1), 247bc679b60SStephan Aßmus 0, 248bc679b60SStephan Aßmus B_GRAY8); 249bc679b60SStephan Aßmus // Allocation checked 250bc679b60SStephan Aßmus if (Fractal->bitmap != NULL && Fractal->bitmap->IsValid()) { 251bc679b60SStephan Aßmus memset(Fractal->bitmap->Bits(), 0, Fractal->bitmap->BitsLength()); 252bc679b60SStephan Aßmus } else { 253bc679b60SStephan Aßmus delete Fractal->bitmap; 254bc679b60SStephan Aßmus Fractal->bitmap = NULL; 255bc679b60SStephan Aßmus } 256bc679b60SStephan Aßmus if (Fractal->markBitmap != NULL && Fractal->markBitmap->IsValid()) { 257bc679b60SStephan Aßmus memset(Fractal->markBitmap->Bits(), 0, Fractal->markBitmap->BitsLength()); 258bc679b60SStephan Aßmus } else { 259bc679b60SStephan Aßmus delete Fractal->markBitmap; 260bc679b60SStephan Aßmus Fractal->markBitmap = NULL; 261bc679b60SStephan Aßmus } 262bc679b60SStephan Aßmus } 263bc679b60SStephan Aßmus 264bc679b60SStephan Aßmus // destructor 265bc679b60SStephan Aßmus IFS::~IFS() 266bc679b60SStephan Aßmus { 267bc679b60SStephan Aßmus if (fRoot != NULL) { 268bc679b60SStephan Aßmus _FreeIFS(fRoot); 269bc679b60SStephan Aßmus free((void*) fRoot); 270bc679b60SStephan Aßmus } 271bc679b60SStephan Aßmus } 272bc679b60SStephan Aßmus 273bc679b60SStephan Aßmus // Draw 274bc679b60SStephan Aßmus void 275bc679b60SStephan Aßmus IFS::Draw(BView* view, const buffer_info* info, int32 frames) 276bc679b60SStephan Aßmus { 277bc679b60SStephan Aßmus //bigtime_t now = system_time(); 278bc679b60SStephan Aßmus int i; 279bc679b60SStephan Aßmus float u, uu, v, vv, u0, u1, u2, u3; 280bc679b60SStephan Aßmus SIMI *S, *S1, *S2, *S3, *S4; 281bc679b60SStephan Aßmus FRACTAL *F; 282bc679b60SStephan Aßmus 283bc679b60SStephan Aßmus if (fRoot == NULL) 284bc679b60SStephan Aßmus return; 285bc679b60SStephan Aßmus F = fRoot; 286bc679b60SStephan Aßmus if (F->buffer1 == NULL) 287bc679b60SStephan Aßmus return; 288bc679b60SStephan Aßmus 289bc679b60SStephan Aßmus //if (frames > 1) 290bc679b60SStephan Aßmus // printf("skipping %ld frames\n", frames); 291bc679b60SStephan Aßmus 292bc679b60SStephan Aßmus // do this as many times as necessary to calculate the missing frames 293bc679b60SStephan Aßmus // so the animation doesn't jerk when we miss a few frames 294bc679b60SStephan Aßmus for (int32 frame = 0; frame < frames; frame++) { 295bc679b60SStephan Aßmus 296bc679b60SStephan Aßmus u = (float) (F->Count) * (float) (F->Speed) / 1000.0; 297bc679b60SStephan Aßmus uu = u * u; 298bc679b60SStephan Aßmus v = 1.0 - u; 299bc679b60SStephan Aßmus vv = v * v; 300bc679b60SStephan Aßmus u0 = vv * v; 301bc679b60SStephan Aßmus u1 = 3.0 * vv * u; 302bc679b60SStephan Aßmus u2 = 3.0 * v * uu; 303bc679b60SStephan Aßmus u3 = u * uu; 304bc679b60SStephan Aßmus 305bc679b60SStephan Aßmus S = F->Components; 306bc679b60SStephan Aßmus S1 = S + F->Nb_Simi; 307bc679b60SStephan Aßmus S2 = S1 + F->Nb_Simi; 308bc679b60SStephan Aßmus S3 = S2 + F->Nb_Simi; 309bc679b60SStephan Aßmus S4 = S3 + F->Nb_Simi; 310bc679b60SStephan Aßmus 311bc679b60SStephan Aßmus for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) { 312bc679b60SStephan Aßmus S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x; 313bc679b60SStephan Aßmus S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y; 314bc679b60SStephan Aßmus S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r; 315bc679b60SStephan Aßmus S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2; 316bc679b60SStephan Aßmus S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A; 317bc679b60SStephan Aßmus S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2; 318bc679b60SStephan Aßmus } 319bc679b60SStephan Aßmus 320bc679b60SStephan Aßmus //bigtime_t beforeDraw = system_time(); 321bc679b60SStephan Aßmus if (frame == frames - 1) 322bc679b60SStephan Aßmus _DrawFractal(view, info); 323bc679b60SStephan Aßmus 324bc679b60SStephan Aßmus //bigtime_t draw = system_time() - beforeDraw; 325bc679b60SStephan Aßmus 326bc679b60SStephan Aßmus if (F->Count >= 1000 / F->Speed) { 327bc679b60SStephan Aßmus S = F->Components; 328bc679b60SStephan Aßmus S1 = S + F->Nb_Simi; 329bc679b60SStephan Aßmus S2 = S1 + F->Nb_Simi; 330bc679b60SStephan Aßmus S3 = S2 + F->Nb_Simi; 331bc679b60SStephan Aßmus S4 = S3 + F->Nb_Simi; 332bc679b60SStephan Aßmus 333bc679b60SStephan Aßmus for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) { 334bc679b60SStephan Aßmus S2->c_x = 2.0 * S4->c_x - S3->c_x; 335bc679b60SStephan Aßmus S2->c_y = 2.0 * S4->c_y - S3->c_y; 336bc679b60SStephan Aßmus S2->r = 2.0 * S4->r - S3->r; 337bc679b60SStephan Aßmus S2->r2 = 2.0 * S4->r2 - S3->r2; 338bc679b60SStephan Aßmus S2->A = 2.0 * S4->A - S3->A; 339bc679b60SStephan Aßmus S2->A2 = 2.0 * S4->A2 - S3->A2; 340bc679b60SStephan Aßmus 341bc679b60SStephan Aßmus *S1 = *S4; 342bc679b60SStephan Aßmus } 343bc679b60SStephan Aßmus _RandomSimis(F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi); 344bc679b60SStephan Aßmus 345bc679b60SStephan Aßmus _RandomSimis(F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi); 346bc679b60SStephan Aßmus 347bc679b60SStephan Aßmus F->Count = 0; 348bc679b60SStephan Aßmus } else 349bc679b60SStephan Aßmus F->Count++; 350bc679b60SStephan Aßmus // F->Col++; 351bc679b60SStephan Aßmus //bigtime_t finish = (system_time() - now) - draw; 352bc679b60SStephan Aßmus //if (info) 353bc679b60SStephan Aßmus //printf("draw: %lld\nnon-draw: %lld\n\n", draw, finish); 354bc679b60SStephan Aßmus } 355bc679b60SStephan Aßmus 356bc679b60SStephan Aßmus } 357bc679b60SStephan Aßmus 358bc679b60SStephan Aßmus // SetAdditive 359bc679b60SStephan Aßmus void 360bc679b60SStephan Aßmus IFS::SetAdditive(bool additive) 361bc679b60SStephan Aßmus { 362bc679b60SStephan Aßmus fAdditive = additive; 363bc679b60SStephan Aßmus } 364bc679b60SStephan Aßmus 365bc679b60SStephan Aßmus // SetSpeed 366bc679b60SStephan Aßmus void 367bc679b60SStephan Aßmus IFS::SetSpeed(int32 speed) 368bc679b60SStephan Aßmus { 369bc679b60SStephan Aßmus if (fRoot && speed > 0 && speed <= 12) 370bc679b60SStephan Aßmus fRoot->Speed = speed; 371bc679b60SStephan Aßmus } 372bc679b60SStephan Aßmus 373bc679b60SStephan Aßmus // Draw 374bc679b60SStephan Aßmus void 375bc679b60SStephan Aßmus IFS::_DrawFractal(BView* view, const buffer_info* info) 376bc679b60SStephan Aßmus { 377bc679b60SStephan Aßmus FRACTAL* F = fRoot; 378bc679b60SStephan Aßmus int i, j; 379bc679b60SStephan Aßmus int32 x, y, xo, yo; 380bc679b60SStephan Aßmus SIMI* Cur, *Simi; 381bc679b60SStephan Aßmus 382bc679b60SStephan Aßmus for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) { 383bc679b60SStephan Aßmus Cur->Cx = FLOAT_TO_INT(Cur->c_x); 384bc679b60SStephan Aßmus Cur->Cy = FLOAT_TO_INT(Cur->c_y); 385bc679b60SStephan Aßmus 386bc679b60SStephan Aßmus Cur->Ct = FLOAT_TO_INT(cos(Cur->A)); 387bc679b60SStephan Aßmus Cur->St = FLOAT_TO_INT(sin(Cur->A)); 388bc679b60SStephan Aßmus Cur->Ct2 = FLOAT_TO_INT(cos(Cur->A2)); 389bc679b60SStephan Aßmus Cur->St2 = FLOAT_TO_INT(sin(Cur->A2)); 390bc679b60SStephan Aßmus 391bc679b60SStephan Aßmus Cur->R = FLOAT_TO_INT(Cur->r); 392bc679b60SStephan Aßmus Cur->R2 = FLOAT_TO_INT(Cur->r2); 393bc679b60SStephan Aßmus } 394bc679b60SStephan Aßmus 395bc679b60SStephan Aßmus 396bc679b60SStephan Aßmus fCurrentPoint = 0; 397bc679b60SStephan Aßmus fCurrentFractal = F; 398bc679b60SStephan Aßmus fPointBuffer = F->buffer2; 399bc679b60SStephan Aßmus for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) { 400bc679b60SStephan Aßmus xo = Cur->Cx; 401bc679b60SStephan Aßmus yo = Cur->Cy; 402bc679b60SStephan Aßmus for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) { 403bc679b60SStephan Aßmus if (Simi == Cur) 404bc679b60SStephan Aßmus continue; 405bc679b60SStephan Aßmus transform(Simi, xo, yo, &x, &y); 406bc679b60SStephan Aßmus _Trace(F, x, y); 407bc679b60SStephan Aßmus } 408bc679b60SStephan Aßmus } 409bc679b60SStephan Aßmus 410bc679b60SStephan Aßmus if (F->bitmap != NULL && F->markBitmap != NULL) { 411bc679b60SStephan Aßmus uint8* bits = (uint8*)F->bitmap->Bits(); 412bc679b60SStephan Aßmus uint32 bpr = F->bitmap->BytesPerRow(); 413bc679b60SStephan Aßmus uint8* markBits = (uint8*)F->markBitmap->Bits(); 414bc679b60SStephan Aßmus uint32 markBPR = F->markBitmap->BytesPerRow(); 415bc679b60SStephan Aßmus int32 minX = F->Width; 416bc679b60SStephan Aßmus int32 minY = F->Height; 417bc679b60SStephan Aßmus int32 maxX = 0; 418bc679b60SStephan Aßmus int32 maxY = 0; 419bc679b60SStephan Aßmus // Erase previous dots from bitmap, 420bc679b60SStephan Aßmus // but only if we're not in BDirectWindow mode, 421bc679b60SStephan Aßmus // since the dots will have been erased already 422bc679b60SStephan Aßmus if (!info) { 423bc679b60SStephan Aßmus if (F->Cur_Pt) { 424bc679b60SStephan Aßmus for (int32 i = 0; i < F->Cur_Pt; i++) { 425bc679b60SStephan Aßmus Point p = F->buffer1[i]; 426bc679b60SStephan Aßmus if (p.x >= 0 && p.x < F->Width 427bc679b60SStephan Aßmus && p.y >= 0 && p.y < F->Height) { 428bc679b60SStephan Aßmus int32 offset = bpr * p.y + p.x * 4; 429bc679b60SStephan Aßmus *(uint32*)&bits[offset] = 0; 430bc679b60SStephan Aßmus if (minX > p.x) 431bc679b60SStephan Aßmus minX = p.x; 432bc679b60SStephan Aßmus if (minY > p.y) 433bc679b60SStephan Aßmus minY = p.y; 434bc679b60SStephan Aßmus if (maxX < p.x) 435bc679b60SStephan Aßmus maxX = p.x; 436bc679b60SStephan Aßmus if (maxY < p.y) 437bc679b60SStephan Aßmus maxY = p.y; 438bc679b60SStephan Aßmus } 439bc679b60SStephan Aßmus } 440bc679b60SStephan Aßmus } 441bc679b60SStephan Aßmus } 442bc679b60SStephan Aßmus // draw the new dots into the bitmap 443bc679b60SStephan Aßmus if (fCurrentPoint) { 444bc679b60SStephan Aßmus if (info) { 445bc679b60SStephan Aßmus for (int32 i = 0; i < fCurrentPoint; i++) { 446bc679b60SStephan Aßmus Point p = F->buffer2[i]; 447bc679b60SStephan Aßmus if (p.x >= 0 && p.x < F->Width 448bc679b60SStephan Aßmus && p.y >= 0 && p.y < F->Height) { 449bc679b60SStephan Aßmus int32 offset = bpr * p.y + p.x * 4; 450bc679b60SStephan Aßmus if (fAdditive) { 451bc679b60SStephan Aßmus if (bits[offset + 0] < 255) { 452bc679b60SStephan Aßmus bits[offset + 0] += 51; 453bc679b60SStephan Aßmus bits[offset + 1] += 51; 454bc679b60SStephan Aßmus bits[offset + 2] += 51; 455bc679b60SStephan Aßmus } 456bc679b60SStephan Aßmus } else { 457bc679b60SStephan Aßmus *(uint32*)&bits[offset] = 0xffffffff; 458bc679b60SStephan Aßmus } 459bc679b60SStephan Aßmus } 460bc679b60SStephan Aßmus } 461bc679b60SStephan Aßmus } else { 462bc679b60SStephan Aßmus // in this version, remember the bounds rectangle 463bc679b60SStephan Aßmus for (int32 i = 0; i < fCurrentPoint; i++) { 464bc679b60SStephan Aßmus Point p = F->buffer2[i]; 465bc679b60SStephan Aßmus if (p.x >= 0 && p.x < F->Width 466bc679b60SStephan Aßmus && p.y >= 0 && p.y < F->Height) { 467bc679b60SStephan Aßmus int32 offset = bpr * p.y + p.x * 4; 468bc679b60SStephan Aßmus if (fAdditive) { 469bc679b60SStephan Aßmus if (bits[offset + 0] < 255) { 470bc679b60SStephan Aßmus bits[offset + 0] += 15; 471bc679b60SStephan Aßmus bits[offset + 1] += 15; 472bc679b60SStephan Aßmus bits[offset + 2] += 15; 473bc679b60SStephan Aßmus } 474bc679b60SStephan Aßmus } else { 475bc679b60SStephan Aßmus *(uint32*)&bits[offset] = 0xffffffff; 476bc679b60SStephan Aßmus } 477bc679b60SStephan Aßmus if (minX > p.x) 478bc679b60SStephan Aßmus minX = p.x; 479bc679b60SStephan Aßmus if (minY > p.y) 480bc679b60SStephan Aßmus minY = p.y; 481bc679b60SStephan Aßmus if (maxX < p.x) 482bc679b60SStephan Aßmus maxX = p.x; 483bc679b60SStephan Aßmus if (maxY < p.y) 484bc679b60SStephan Aßmus maxY = p.y; 485bc679b60SStephan Aßmus } 486bc679b60SStephan Aßmus } 487bc679b60SStephan Aßmus } 488bc679b60SStephan Aßmus } 489bc679b60SStephan Aßmus if (info && info->bits) { 490bc679b60SStephan Aßmus 491bc679b60SStephan Aßmus uint8* screenBits = (uint8*)info->bits; 492bc679b60SStephan Aßmus uint32 screenBPR = info->bytesPerRow; 493bc679b60SStephan Aßmus int32 left = info->bounds.left; 494bc679b60SStephan Aßmus int32 top = info->bounds.top; 495bc679b60SStephan Aßmus int32 bpp = info->bits_per_pixel; 496bc679b60SStephan Aßmus screenBits += left * bpp + top * bpr; 497bc679b60SStephan Aßmus 498bc679b60SStephan Aßmus int32 screenWidth = info->bounds.right - left; 499bc679b60SStephan Aßmus int32 screenHeight = info->bounds.bottom - top; 500bc679b60SStephan Aßmus 501bc679b60SStephan Aßmus //printf("using BDirectWindow (%p %dx%d)\n", this, F->Width, F->Height); 502bc679b60SStephan Aßmus // redraw the previous points on screen 503bc679b60SStephan Aßmus // with the contents of the current bitmap 504bc679b60SStephan Aßmus // 505bc679b60SStephan Aßmus // draw the new points, erasing the bitmap as we go 506bc679b60SStephan Aßmus int32 maxPoints = max_c(F->Cur_Pt, fCurrentPoint); 507bc679b60SStephan Aßmus if (maxPoints > 0) { 508bc679b60SStephan Aßmus 509bc679b60SStephan Aßmus // BScreen screen(B_MAIN_SCREEN_ID); 510bc679b60SStephan Aßmus // screen.WaitForRetrace(); 511bc679b60SStephan Aßmus 512bc679b60SStephan Aßmus for (int32 i = 0; i < maxPoints; i++) { 513bc679b60SStephan Aßmus // copy previous points (black) 514bc679b60SStephan Aßmus if (i < F->Cur_Pt) { 515bc679b60SStephan Aßmus Point p = F->buffer1[i]; 516bc679b60SStephan Aßmus if (p.x >= 0 && p.x < F->Width && p.x < screenWidth 517bc679b60SStephan Aßmus && p.y >= 0 && p.y < F->Height && p.y < screenHeight) { 518bc679b60SStephan Aßmus int32 markOffset = markBPR * p.y + p.x; 519bc679b60SStephan Aßmus if (markBits[markOffset] != fCurrentMarkValue) { 520bc679b60SStephan Aßmus int32 offset = bpr * p.y + p.x * 4; 521bc679b60SStephan Aßmus // copy the pixel to the screen 522bc679b60SStephan Aßmus uint32* src = (uint32*)&bits[offset]; 523bc679b60SStephan Aßmus if (bpp == 32) { 524bc679b60SStephan Aßmus int32 screenOffset = screenBPR * p.y + p.x * 4; 525bc679b60SStephan Aßmus *(uint32*)&screenBits[screenOffset] = *src; 526bc679b60SStephan Aßmus } else if (bpp == 16) { 527bc679b60SStephan Aßmus int32 screenOffset = screenBPR * p.y + p.x * 2; 528bc679b60SStephan Aßmus *(uint16*)&screenBits[screenOffset] = 529bc679b60SStephan Aßmus (uint16)(((bits[offset + 2] & 0xf8) << 8) | 530bc679b60SStephan Aßmus ((bits[offset + 1] & 0xfc) << 3) | 531bc679b60SStephan Aßmus (bits[offset] >> 3)); 532bc679b60SStephan Aßmus } else if (bpp == 15) { 533bc679b60SStephan Aßmus int32 screenOffset = screenBPR * p.y + p.x * 2; 534bc679b60SStephan Aßmus *(uint16*)&screenBits[screenOffset] = 535bc679b60SStephan Aßmus (uint16)(((bits[offset + 2] & 0xf8) << 7) | 536bc679b60SStephan Aßmus ((bits[offset + 1] & 0xf8) << 2) | 537bc679b60SStephan Aßmus (bits[offset] >> 3)); 538bc679b60SStephan Aßmus } else if (bpp == 8) { 539bc679b60SStephan Aßmus int32 screenOffset = screenBPR * p.y + p.x; 540bc679b60SStephan Aßmus screenBits[screenOffset] = bits[offset]; 541bc679b60SStephan Aßmus } 542bc679b60SStephan Aßmus *src = 0; 543bc679b60SStephan Aßmus markBits[markOffset] = fCurrentMarkValue; 544bc679b60SStephan Aßmus } // else it means the pixel has been copied already 545bc679b60SStephan Aßmus } 546bc679b60SStephan Aßmus } 547bc679b60SStephan Aßmus // copy current points (white) and erase them from the bitmap 548bc679b60SStephan Aßmus if (i < fCurrentPoint) { 549bc679b60SStephan Aßmus Point p = F->buffer2[i]; 550bc679b60SStephan Aßmus if (p.x >= 0 && p.x < F->Width && p.x < screenWidth 551bc679b60SStephan Aßmus && p.y >= 0 && p.y < F->Height && p.y < screenHeight) { 552bc679b60SStephan Aßmus int32 markOffset = markBPR * p.y + p.x; 553bc679b60SStephan Aßmus int32 offset = bpr * p.y + p.x * 4; 554bc679b60SStephan Aßmus // copy the pixel to the screen 555bc679b60SStephan Aßmus uint32* src = (uint32*)&bits[offset]; 556bc679b60SStephan Aßmus if (markBits[markOffset] != fCurrentMarkValue) { 557bc679b60SStephan Aßmus if (bpp == 32) { 558bc679b60SStephan Aßmus int32 screenOffset = screenBPR * p.y + p.x * 4; 559bc679b60SStephan Aßmus *(uint32*)&screenBits[screenOffset] = *src; 560bc679b60SStephan Aßmus } else if (bpp == 16) { 561bc679b60SStephan Aßmus int32 screenOffset = screenBPR * p.y + p.x * 2; 562bc679b60SStephan Aßmus *(uint16*)&screenBits[screenOffset] = 563bc679b60SStephan Aßmus (uint16)(((bits[offset + 2] & 0xf8) << 8) | 564bc679b60SStephan Aßmus ((bits[offset + 1] & 0xfc) << 3) | 565bc679b60SStephan Aßmus (bits[offset] >> 3)); 566bc679b60SStephan Aßmus } else if (bpp == 15) { 567bc679b60SStephan Aßmus int32 screenOffset = screenBPR * p.y + p.x * 2; 568bc679b60SStephan Aßmus *(uint16*)&screenBits[screenOffset] = 569bc679b60SStephan Aßmus (uint16)(((bits[offset + 2] & 0xf8) << 7) | 570bc679b60SStephan Aßmus ((bits[offset + 1] & 0xf8) << 2) | 571bc679b60SStephan Aßmus (bits[offset] >> 3)); 572bc679b60SStephan Aßmus } else if (bpp == 1) { 573bc679b60SStephan Aßmus int32 screenOffset = screenBPR * p.y + p.x; 574bc679b60SStephan Aßmus screenBits[screenOffset] = bits[offset]; 575bc679b60SStephan Aßmus } 576bc679b60SStephan Aßmus markBits[markOffset] = fCurrentMarkValue; 577bc679b60SStephan Aßmus } // else it means the pixel has been copied already 578bc679b60SStephan Aßmus *src = 0; 579bc679b60SStephan Aßmus } 580bc679b60SStephan Aßmus } 581bc679b60SStephan Aßmus } 582bc679b60SStephan Aßmus } 583bc679b60SStephan Aßmus } else { 584bc679b60SStephan Aßmus //printf("using BView (%p %dx%d)\n", this, F->Width, F->Height); 585bc679b60SStephan Aßmus // if not in BDirectWindow mode, draw the bitmap 586bc679b60SStephan Aßmus BRect b(minX, minY, maxX, maxY); 587bc679b60SStephan Aßmus view->DrawBitmapAsync(F->bitmap, b, b); 588bc679b60SStephan Aßmus } 589bc679b60SStephan Aßmus } 590bc679b60SStephan Aßmus 591bc679b60SStephan Aßmus // flip buffers 592bc679b60SStephan Aßmus F->Cur_Pt = fCurrentPoint; 593bc679b60SStephan Aßmus fPointBuffer = F->buffer1; 594bc679b60SStephan Aßmus F->buffer1 = F->buffer2; 595bc679b60SStephan Aßmus F->buffer2 = fPointBuffer; 596bc679b60SStephan Aßmus if (fCurrentMarkValue == 255) 597bc679b60SStephan Aßmus fCurrentMarkValue = 0; 598bc679b60SStephan Aßmus else 599bc679b60SStephan Aßmus fCurrentMarkValue++; 600bc679b60SStephan Aßmus } 601bc679b60SStephan Aßmus 602bc679b60SStephan Aßmus // _Trace 603bc679b60SStephan Aßmus void 604bc679b60SStephan Aßmus IFS::_Trace(FRACTAL* F, int32 xo, int32 yo) 605bc679b60SStephan Aßmus { 606bc679b60SStephan Aßmus int32 x, y, i; 607bc679b60SStephan Aßmus SIMI* Cur; 608bc679b60SStephan Aßmus 609bc679b60SStephan Aßmus Cur = fCurrentFractal->Components; 610bc679b60SStephan Aßmus for (i = fCurrentFractal->Nb_Simi; i; --i, Cur++) { 611bc679b60SStephan Aßmus transform(Cur, xo, yo, &x, &y); 612bc679b60SStephan Aßmus // fPointBuffer->x = F->Lx + (x * F->Lx / (UNIT * 2)); 613bc679b60SStephan Aßmus // fPointBuffer->y = F->Ly - (y * F->Ly / (UNIT * 2)); 614bc679b60SStephan Aßmus fPointBuffer->x = (UNIT * 2 + x) * F->Lx / (UNIT * 2); 615bc679b60SStephan Aßmus fPointBuffer->y = (UNIT * 2 - y) * F->Ly / (UNIT * 2); 616bc679b60SStephan Aßmus fPointBuffer++; 617bc679b60SStephan Aßmus fCurrentPoint++; 618bc679b60SStephan Aßmus 619bc679b60SStephan Aßmus if (F->Depth && ((x - xo) >> 4) && ((y - yo) >> 4)) { 620bc679b60SStephan Aßmus F->Depth--; 621bc679b60SStephan Aßmus _Trace(F, x, y); 622bc679b60SStephan Aßmus F->Depth++; 623bc679b60SStephan Aßmus } 624bc679b60SStephan Aßmus } 625bc679b60SStephan Aßmus } 626bc679b60SStephan Aßmus 627bc679b60SStephan Aßmus // _RandomSimis 628bc679b60SStephan Aßmus void 629bc679b60SStephan Aßmus IFS::_RandomSimis(FRACTAL* f, SIMI* cur, int i) const 630bc679b60SStephan Aßmus { 631bc679b60SStephan Aßmus while (i--) { 632bc679b60SStephan Aßmus cur->c_x = gauss_rand(0.0, .8, 4.0); 633bc679b60SStephan Aßmus cur->c_y = gauss_rand(0.0, .8, 4.0); 634bc679b60SStephan Aßmus cur->r = gauss_rand(f->r_mean, f->dr_mean, 3.0); 635bc679b60SStephan Aßmus cur->r2 = half_gauss_rand(0.0,f->dr2_mean, 2.0); 636bc679b60SStephan Aßmus cur->A = gauss_rand(0.0, 360.0, 4.0) * (M_PI / 180.0); 637bc679b60SStephan Aßmus cur->A2 = gauss_rand(0.0, 360.0, 4.0) * (M_PI / 180.0); 638bc679b60SStephan Aßmus cur++; 639bc679b60SStephan Aßmus } 640bc679b60SStephan Aßmus } 641bc679b60SStephan Aßmus 642bc679b60SStephan Aßmus // _FreeBuffers 643bc679b60SStephan Aßmus void 644bc679b60SStephan Aßmus IFS::_FreeBuffers(FRACTAL *f) 645bc679b60SStephan Aßmus { 646bc679b60SStephan Aßmus if (f->buffer1) { 647bc679b60SStephan Aßmus free((void*) f->buffer1); 648bc679b60SStephan Aßmus f->buffer1 = (Point*)NULL; 649bc679b60SStephan Aßmus } 650bc679b60SStephan Aßmus if (f->buffer2) { 651bc679b60SStephan Aßmus free((void*) f->buffer2); 652bc679b60SStephan Aßmus f->buffer2 = (Point*)NULL; 653bc679b60SStephan Aßmus } 654bc679b60SStephan Aßmus } 655bc679b60SStephan Aßmus 656bc679b60SStephan Aßmus // _FreeIFS 657bc679b60SStephan Aßmus void 658bc679b60SStephan Aßmus IFS::_FreeIFS(FRACTAL* f) 659bc679b60SStephan Aßmus { 660bc679b60SStephan Aßmus _FreeBuffers(f); 661bc679b60SStephan Aßmus delete f->bitmap; 662bc679b60SStephan Aßmus f->bitmap = NULL; 663bc679b60SStephan Aßmus delete f->markBitmap; 664bc679b60SStephan Aßmus f->markBitmap = NULL; 665bc679b60SStephan Aßmus } 666bc679b60SStephan Aßmus 667bc679b60SStephan Aßmus 668bc679b60SStephan Aßmus 669