Computer Science Canada

3D Snowflake Generator!

Author:  Abstraction [ Fri Apr 06, 2007 1:02 pm ]
Post subject:  3D Snowflake Generator!

It doesn't really generate 3D snowflakes per se, but it does look very three-dimensional
The code isn't very....logical, since it took a lot of fiddling to get it to work in its current state

Also, the snow only moves in one direction at the moment: down. I haven't got it to move in a very snow-like fashion yet

Quote:

setscreen ("graphics:550;350;position:center;center,nobuttonbar")
View.Set ("offscreenonly")
const CX := maxx div 2
const CY := maxy div 2

var sX : array 1 .. 6 of int
var sY : array 1 .. 6 of int
var minSnowSize : int := 8
var maxSnowSize : int := 17

var flakes : int := 20
var lA : int := 0

fcn cosP (deg, x : int, mX : real) : int
result round (cosd (deg) * (mX)) + x
end cosP

fcn sinP (deg, y : int, mX : real) : int
result round (sind (deg) * (mX)) + y
end sinP

fcn angle (x, y : int) : real
if x = 0 then
if y > 0 then
result - 90
else
result 90
end if
elsif x > 0
then
result arctand (y / x)
else
result arctand (y / x) + 180
end if
end angle

var x, y, centerx, centery, a, d, c : array 1 .. flakes, 1 .. 8, 1 .. 6 of int
var n : int := 1

proc assign (xl, yl, cx, cy, nf, i, s : int)
x (nf, n, i) := xl
y (nf, n, i) := yl
a (nf, n, i) := round (angle (xl - cx, yl - cy))
d (nf, n, i) := round (sqrt ((xl - cx) ** 2 + (yl - cy) ** 2))
c (nf, n, i) := s + (31 - maxSnowSize)

%Makes the flakes generally brighter
if c (nf, n, i) not= 31 then
c (nf, n, i) += 1
end if

centerx (nf, n, i) := cx
centery (nf, n, i) := cy
end assign

proc oct (s, x, y, cx, cy, nf, snowSize : int)
for i : 1 .. 6
sX (i) := round (cosd (i * 60) * s) + x
sY (i) := round (sind (i * 60) * s) + y
assign (sX (i), sY (i), cx, cy, nf, i, snowSize)
end for

if n < 8 then
n += 1
else
n := 1
end if
end oct

proc sF (sx, sy, s, nf : int)
oct (s, sx, sy, sx, sy, nf, s)
oct (round (s * 0.8), sx, sy, sx, sy, nf, s)

for i : 1 .. 6
oct (round (s * 0.3), cosP (i * 60, sx, s * 1.5), sinP (i * 60, sy, s * 1.5), sx, sy, nf, s)
end for
end sF

for i : 1 .. flakes
sF (Rand.Int (1, maxx), Rand.Int (1, maxy), Rand.Int (minSnowSize, maxSnowSize), i)
end for

var deg : int

%Varies the snow path
var snowPath : int

var r : array 1 .. flakes of int
for i : 1 .. flakes
r (i) := 0
end for

var v : int := 6
var sA : int := 270

%Rotates as if it was three dimensional
fcn rotate3D (i, ii, iii, r : int) : int
result round ((x (i, ii, iii) - centerx (i, ii, iii)) * cosd (r)) + centerx (i, ii, iii)
end rotate3D

loop
drawfillbox (0, 0, maxx, maxy, 17)

for i : 1 .. flakes
%Ensures that each snowflake will rotate at a random speed
%this method used so that segments of flake are consistent.
deg := Rand.Int (3, 13)

%3D Rotation value- Randomized rotation speed
r (i) += Rand.Int (-5, 25)
snowPath := Rand.Int (-15, 15)

if r (i) > 360
then
r (i) -= 360
end if

%Tries to make sure that it doesn't flatten- looks ugly
if abs (r (i) - 90) < 10 or abs (r (i) - 270) < 10
then
r (i) += 15
end if

for ii : 1 .. 8

for iii : 1 .. 5
drawline (rotate3D (i, ii, iii, r (i)), y (i, ii, iii),
rotate3D (i, ii, iii + 1, r (i)), y (i, ii, iii + 1), c (i, ii, iii))
end for
drawline (rotate3D (i, ii, 6, r (i)), y (i, ii, 6), rotate3D (i, ii, 1, r (i)), y (i, ii, 1), c (i, ii, 1))

%Reassigns the locations for 3D effect
for iii : 1 .. 6
%2D Rotation
a (i, ii, iii) += deg
x (i, ii, iii) := round (cosd (a (i, ii, iii)) * d (i, ii, iii)) + centerx (i, ii, iii)
y (i, ii, iii) := round (sind (a (i, ii, iii)) * d (i, ii, iii)) + centery (i, ii, iii)

%Moves the flakes based on velocity and angle
x (i, ii, iii) += round (cosd (sA + snowPath) * v)
y (i, ii, iii) += round (sind (sA + snowPath) * v)
centerx (i, ii, iii) += round (cosd (sA) * v)
centery (i, ii, iii) += round (sind (sA) * v)
end for
end for
end for

%Generates new snowlakes when old ones disappear
for i : 1 .. flakes
for ii : 1 .. 8
for iii : 1 .. 6
%Generates a new snowflake everytime one leaves the boundaries of the screen
if centerx (i, ii, iii) < -18 or centerx (i, ii, iii) > maxx + 18
or centery (i, ii, iii) < -18
then
sF (Rand.Int (0, maxx), Rand.Int (maxy, maxy + 200), Rand.Int (8, 16), i)
end if
end for
end for
end for

View.Update
end loop

Author:  LaZ3R [ Fri Apr 06, 2007 5:11 pm ]
Post subject:  Re: 3D Snowflake Generator!

You only really need to Rand.Int the new x value of each snowflake, and make it so that the bigger snowflakes have a greater decrease in y value compared to the smaller ones... I'm slightly confused with your coding though Sad

Very cool program however! Smile

Author:  lordroba [ Fri Apr 06, 2007 8:13 pm ]
Post subject:  Re: 3D Snowflake Generator!

wow, there is a really messed up glitch. Try these settings for the min and max snowflake size
code:
var minSnowSize : int := 1
var maxSnowSize : int := 2


after an initial round of small white snowflakes, you get big colorful snowflakes. it's really weird.

Author:  Abstraction [ Mon Apr 09, 2007 1:58 pm ]
Post subject:  Re: 3D Snowflake Generator!

Ah....oops....I was supposed to use the minSnowSize & maxSnowSize variables instead of 8 and 16 ^^

%Generates new snowlakes when old ones disappear
for i : 1 .. flakes
for ii : 1 .. 8
for iii : 1 .. 6
%Generates a new snowflake everytime one leaves the boundaries of the screen
if centerx (i, ii, iii) < -18 or centerx (i, ii, iii) > maxx + 18
or centery (i, ii, iii) < -18
then
sF (Rand.Int (0, maxx), Rand.Int (maxy, maxy + 200), Rand.Int (8, 16), i)
end if
end for
end for
end for

Author:  kshorting [ Wed Apr 25, 2007 10:17 pm ]
Post subject:  Re: 3D Snowflake Generator!

Very cool. I like it. Mistakes and all. Thanks for your hard work to put this together.


: