2 |
// |
// |
3 |
// demo of line integral convolution (LIC) on 2D turbulent flow |
// demo of line integral convolution (LIC) on 2D turbulent flow |
4 |
// |
// |
|
// First, need to create padded vector dataset v.nrrd with: |
|
|
// unu pad -i ../data/turb2d.nrrd -min 0 -5 -5 -max M M+5 M+5 -b pad -v 0.0001 -o v.nrrd |
|
|
// We pad with value 0.0001; we padded with zero than normalize() would fail |
|
|
// But if you try take too many steps (increasing stepNum) then eventually |
|
|
// you will leave the vector field domain, which will crash the program, |
|
|
// so really the padding should be done with a vector field that |
|
|
// pointwards inwards, towards the center of the domain, so that anything |
|
|
// leaving the domain will get pushed back in. OR, really, the code |
|
|
// below should be smart and use inside() or some other test to stop |
|
|
// the integration when we get too close to the domain boundary. |
|
|
// |
|
|
// Then, need to create noise texture with: |
|
|
// unu slice -i v.nrrd -a 0 -p 0 | unu resample -s 1020 561 | unu 1op nrand -o R.nrrd |
|
|
// where "1020 561" is copied from imgSizeX and imgSizeY below; we start |
|
|
// with unu slice in order to inherit the image orientation info, to |
|
|
// create a noise texture at the same world-space position as the data |
|
|
// |
|
5 |
// process output with: |
// process output with: |
6 |
// unu reshape -i lic-turb2d.txt -s 3 1020 561 | unu quantize -b 8 -o lic-turb2d.ppm |
// unu reshape -i lic-turb2d.txt -s 3 1020 561 | unu quantize -b 8 -o lic-turb2d.ppm |
7 |
|
|
|
|
|
8 |
int imgSizeX = 1020; |
int imgSizeX = 1020; |
9 |
int imgSizeY = 561; |
int imgSizeY = 561; |
10 |
real h = 0.005; // step size of integration |
real h = 0.005; // step size of integration |
28 |
real crl = 0.0; |
real crl = 0.0; |
29 |
|
|
30 |
update { |
update { |
|
// Euler integration step |
|
|
// forw = forw + h*V(forw); |
|
|
// back = back - h*V(back); |
|
|
// Midpoint method step |
|
31 |
if(inside(forw, boundary)) { |
if(inside(forw, boundary)) { |
32 |
forw += h*normalize(V(forw + 0.5*h*normalize(V(forw)))); |
forw += h*normalize(V(forw + 0.5*h*normalize(V(forw)))); |
33 |
sum += R(forw); |
sum += R(forw); |
40 |
} |
} |
41 |
step += 1; |
step += 1; |
42 |
if((!inside(forw, boundary) && !inside(back, boundary)) || step == stepNum) { |
if((!inside(forw, boundary) && !inside(back, boundary)) || step == stepNum) { |
|
// the pow() is a way to adjust how much velocity modulates |
|
|
// contrast; lower values increase contrast at small velocity |
|
43 |
sum = pow(|V(pos0)|,0.3)*sum/real(num); |
sum = pow(|V(pos0)|,0.3)*sum/real(num); |
|
|
|
44 |
tensor[2,2] M = ∇⊗V(pos0); |
tensor[2,2] M = ∇⊗V(pos0); |
45 |
crl = M[0,1] - M[1,0]; |
crl = M[0,1] - M[1,0]; |
|
// BUG - curl ("∇×") doesn't work |
|
|
//crl = ∇×V(pos0); |
|
|
|
|
|
//sum in range -1.56, 2.58 |
|
|
//curl in rage -131.797974, 131.828476 |
|
|
|
|
|
if(crl < 0.0) { |
|
|
real h = 300.0; |
|
|
} |
|
|
else { |
|
|
real h = 120.0; |
|
|
} |
|
|
|
|
46 |
real s = lerp(0.0, 1.0, 0.0, |crl|, 132.0); |
real s = lerp(0.0, 1.0, 0.0, |crl|, 132.0); |
|
|
|
47 |
l = lerp(0.0, 1.0, -1.6, sum, 2.6); |
l = lerp(0.0, 1.0, -1.6, sum, 2.6); |
|
|
|
48 |
real c = (1.0 - |2.0 * l - 1.0|) * s; |
real c = (1.0 - |2.0 * l - 1.0|) * s; |
|
|
|
49 |
if(crl < 0.0) { |
if(crl < 0.0) { |
|
int hp = 5; |
|
50 |
real x = c; |
real x = c; |
51 |
real m = l - c / 2.0; |
real m = l - c / 2.0; |
52 |
RGB = [c + m, 0.0 + m, x + m]; |
RGB = [c + m, 0.0 + m, x + m]; |
53 |
} |
} |
54 |
else { |
else { |
|
int hp = 2; |
|
55 |
real x = 0.0; |
real x = 0.0; |
56 |
real m = l - c / 2.0; |
real m = l - c / 2.0; |
57 |
RGB = [0.0 + m, c + m, x + m]; |
RGB = [0.0 + m, c + m, x + m]; |
58 |
} |
} |
|
|
|
59 |
stabilize; |
stabilize; |
60 |
} |
} |
61 |
} |
} |