| 1 |
/***** |
| 2 |
* TPlasma.cp |
| 3 |
* |
| 4 |
* Drawing clouds (Perlin noise?) |
| 5 |
* |
| 6 |
*****/ |
| 7 |
|
| 8 |
#include <Packages.h> // for NumToString prototype |
| 9 |
#include "TFractalViewerWindow.h" |
| 10 |
#include "TPlasma.h" |
| 11 |
#include <stdlib.h> |
| 12 |
#include <math.h> |
| 13 |
|
| 14 |
|
| 15 |
/**** |
| 16 |
* TFractalViewerWindow constructor |
| 17 |
* |
| 18 |
* Create a bullseye window. This constructor relies |
| 19 |
* on the TWindow constructor to place the window in |
| 20 |
* in attractive place. Then it appends a number to the |
| 21 |
* window title. |
| 22 |
* |
| 23 |
****/ |
| 24 |
|
| 25 |
|
| 26 |
TPlasma::TPlasma(void) |
| 27 |
{ |
| 28 |
PrepareStyles(); |
| 29 |
// Set the width, and show the window. |
| 30 |
SetStyle(2); |
| 31 |
Show(); |
| 32 |
} |
| 33 |
|
| 34 |
|
| 35 |
/**** |
| 36 |
* Hit |
| 37 |
* |
| 38 |
* Handle a mouse down in the window. |
| 39 |
* Bullseye window just force a refresh. |
| 40 |
* |
| 41 |
****/ |
| 42 |
|
| 43 |
|
| 44 |
|
| 45 |
|
| 46 |
/**** |
| 47 |
* Noise calculations |
| 48 |
* |
| 49 |
* |
| 50 |
****/ |
| 51 |
|
| 52 |
|
| 53 |
// This code is adapted from a Javascript example found at perlin.mydevelops.com (unknown author) |
| 54 |
|
| 55 |
int p[] = { |
| 56 |
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, |
| 57 |
103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, |
| 58 |
26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, |
| 59 |
87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, |
| 60 |
77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, |
| 61 |
46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, |
| 62 |
187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, |
| 63 |
198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, |
| 64 |
255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, |
| 65 |
170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, |
| 66 |
172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, |
| 67 |
104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, |
| 68 |
241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, |
| 69 |
157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, |
| 70 |
93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 |
| 71 |
}; |
| 72 |
|
| 73 |
|
| 74 |
int round(float f) |
| 75 |
{ |
| 76 |
int fl = floor(f); |
| 77 |
float d = f - (float)fl; |
| 78 |
if (d > 0.5) |
| 79 |
return fl + 1; |
| 80 |
else |
| 81 |
return fl; |
| 82 |
} |
| 83 |
|
| 84 |
int Perm(int x) |
| 85 |
{ |
| 86 |
return p[(x & 255)]; |
| 87 |
} |
| 88 |
|
| 89 |
|
| 90 |
int Index(int x, int y) |
| 91 |
{ |
| 92 |
return Perm(x + Perm(y)); |
| 93 |
} |
| 94 |
|
| 95 |
|
| 96 |
float Gradient(int vector,float x,float y) |
| 97 |
{ |
| 98 |
//we will find the right gradient |
| 99 |
float val = 0; |
| 100 |
switch (vector % 4) |
| 101 |
{ |
| 102 |
case 0: |
| 103 |
val = x + y; |
| 104 |
break; |
| 105 |
case 1: |
| 106 |
val = -x + y; |
| 107 |
break; |
| 108 |
case 2: |
| 109 |
val = x - y; |
| 110 |
break; |
| 111 |
case 3: |
| 112 |
val = -x - y; |
| 113 |
break; |
| 114 |
} |
| 115 |
|
| 116 |
return val; |
| 117 |
} |
| 118 |
|
| 119 |
|
| 120 |
float Smooth(float t) |
| 121 |
{ |
| 122 |
return t * t * t * (6 * t * t - 15.0 * t + 10.0); |
| 123 |
} |
| 124 |
|
| 125 |
|
| 126 |
float Interpolate(float t,float a,float b) |
| 127 |
{ |
| 128 |
return a + t * ( b - a); |
| 129 |
} |
| 130 |
|
| 131 |
float Perlin2D(float x,float y) |
| 132 |
{ |
| 133 |
float hX = floor(x); |
| 134 |
float hY = floor(y); |
| 135 |
|
| 136 |
float dX = x - hX; |
| 137 |
float dY = y - hY; |
| 138 |
|
| 139 |
//field for gradients |
| 140 |
float gradients[4]; |
| 141 |
|
| 142 |
//now let's go through the vertices of the creator and their vectors |
| 143 |
for (int i = 0; i < 4; i++) { |
| 144 |
// 00, 01, 10, 11 |
| 145 |
int tmpX = (i & 2) ? 1: 0; |
| 146 |
int tmpY = (i & 1); |
| 147 |
int vector = Index(hX + tmpX, hY + tmpY); |
| 148 |
|
| 149 |
gradients[i] = Gradient(vector, dX - tmpX, dY - tmpY); |
| 150 |
|
| 151 |
} |
| 152 |
|
| 153 |
//let's use the smoothing function |
| 154 |
float smoothX = Smooth(dX); |
| 155 |
float smoothY = Smooth(dY); |
| 156 |
|
| 157 |
//we make a bilinear interpolation of the gradient of vectors first two and two |
| 158 |
// and finally the results from the first and the second and we get the result |
| 159 |
float x_prva = Interpolate(smoothX, gradients[0], gradients[2]); |
| 160 |
double x_druha = Interpolate(smoothX, gradients[1], gradients[3]); |
| 161 |
|
| 162 |
return Interpolate(smoothY, x_prva, x_druha); |
| 163 |
} |
| 164 |
|
| 165 |
int PerlinMapped(double value) |
| 166 |
{ |
| 167 |
//we will scale it from -1 1 to 0 1 and then from it to 0 255 |
| 168 |
return round( ((value + 1.0) / 2.0) * 255.0); |
| 169 |
} |
| 170 |
|
| 171 |
int PerlinOctFrec(int x, int y, int oct, double frec) |
| 172 |
{ |
| 173 |
double together = 0; |
| 174 |
// int amp = 0; |
| 175 |
double frek = 0; |
| 176 |
|
| 177 |
for(int i = 1; i <= oct; i++) { |
| 178 |
frek = frec * (double)i; |
| 179 |
together += Perlin2D((double)x * frek, (double)y * frek); |
| 180 |
} |
| 181 |
|
| 182 |
return PerlinMapped((double)(together / oct)); |
| 183 |
} |
| 184 |
|
| 185 |
|
| 186 |
|
| 187 |
/**** |
| 188 |
* DrawShape methods |
| 189 |
* |
| 190 |
* |
| 191 |
****/ |
| 192 |
|
| 193 |
|
| 194 |
|
| 195 |
void TPlasma::DrawShape(Rect *drawingRect) |
| 196 |
{ |
| 197 |
RGBColor colPix; |
| 198 |
double frekvencia = 0.004; |
| 199 |
int oktava = 3; |
| 200 |
|
| 201 |
short st = GetStyle() - 1; |
| 202 |
|
| 203 |
sWidth = drawingRect->right - drawingRect->left + 1; |
| 204 |
sHeigth = drawingRect->bottom - drawingRect->top + 1; |
| 205 |
|
| 206 |
for(int x=0; x<sWidth; x++) { |
| 207 |
for (int y=0; y<sHeigth; y++) { |
| 208 |
int shade = PerlinOctFrec(x, y, oktava, frekvencia); |
| 209 |
colPix = spec[st][shade]; |
| 210 |
SetCPixel(x, y, &colPix); |
| 211 |
} |
| 212 |
} |
| 213 |
|
| 214 |
|
| 215 |
|
| 216 |
/* Test code to draw stuff using DrawPicture. It crashes for complex images (memory issues?) |
| 217 |
OpenCPicParams myOpenCPicParams; |
| 218 |
PicHandle myPic; |
| 219 |
Rect rect; |
| 220 |
|
| 221 |
rect.left = drawingRect->left; |
| 222 |
rect.right = drawingRect->right; |
| 223 |
rect.top = drawingRect->top; |
| 224 |
rect.bottom = drawingRect->bottom; |
| 225 |
|
| 226 |
myOpenCPicParams.srcRect = rect; |
| 227 |
myOpenCPicParams.hRes = 0x00480000; |
| 228 |
myOpenCPicParams.vRes = 0x00480000; |
| 229 |
myOpenCPicParams.version = -2; |
| 230 |
myOpenCPicParams.reserved1 = 0; |
| 231 |
myOpenCPicParams.reserved2 = 0; |
| 232 |
|
| 233 |
myPic = OpenCPicture(&myOpenCPicParams); |
| 234 |
|
| 235 |
PenSize(style, style); |
| 236 |
ClipRect(drawingRect); |
| 237 |
|
| 238 |
while (drawingRect->left < drawingRect->right && |
| 239 |
drawingRect->top < drawingRect->bottom) { |
| 240 |
MoveTo(drawingRect->left, drawingRect->bottom); |
| 241 |
LineTo(drawingRect->right, drawingRect->bottom); |
| 242 |
LineTo(drawingRect->left, drawingRect->top); |
| 243 |
LineTo(drawingRect->left, drawingRect->bottom); |
| 244 |
InsetRect(drawingRect, style*2, style*2); |
| 245 |
} |
| 246 |
|
| 247 |
ClosePicture(); |
| 248 |
|
| 249 |
DrawPicture(myPic, &rect); |
| 250 |
*/ |
| 251 |
|
| 252 |
} |
| 253 |
|
| 254 |
|
| 255 |
// |
| 256 |
// PREPARE STYLES METHODS |
| 257 |
// |
| 258 |
|
| 259 |
|
| 260 |
void TPlasma::PrepareStyles() |
| 261 |
{ |
| 262 |
short ci; |
| 263 |
// Style 1 |
| 264 |
for(ci=0; ci < 256; ci++) { |
| 265 |
spec[0][ci].red = ci * 256; |
| 266 |
spec[0][ci].green = ci * 256; |
| 267 |
spec[0][ci].blue = 65535; |
| 268 |
} |
| 269 |
// Style 2 |
| 270 |
for(ci=0; ci < 256; ci++) { |
| 271 |
spec[1][ci].red = 65535 - ci * 256; |
| 272 |
spec[1][ci].green = 65535 - ci * 256; |
| 273 |
spec[1][ci].blue = 65535; |
| 274 |
} |
| 275 |
// Style 3 |
| 276 |
for(ci=0; ci < 256; ci++) { |
| 277 |
spec[2][ci].red = 65535 - ci * 256; |
| 278 |
spec[2][ci].green = 65535 - ci * 256; |
| 279 |
spec[2][ci].blue = 65535 - ci * 256; |
| 280 |
} |
| 281 |
// Style 4 |
| 282 |
for(ci=0; ci < 256; ci++) { |
| 283 |
spec[3][ci].red = ci * 256; |
| 284 |
spec[3][ci].green = ci * 256; |
| 285 |
spec[3][ci].blue = ci * 256; |
| 286 |
} |
| 287 |
// Style 4 |
| 288 |
for(ci=0; ci < 256; ci++) { |
| 289 |
spec[4][ci].red = 32768 - ci * 128; |
| 290 |
spec[4][ci].green = ci * 256; |
| 291 |
spec[4][ci].blue = 65535 - ci * 256; |
| 292 |
} |
| 293 |
} |
| 294 |
|
| 295 |
|
| 296 |
|
| 297 |
// |
| 298 |
// ZOOM CONTENT |
| 299 |
// |