home *** CD-ROM | disk | FTP | other *** search
/ Falcon 030 Power 2 / F030_POWER2.iso / ST_STE / MAGS / MAGGIE22.ARJ / magg22st.msa / GOODIES / TEXTURES.ZIP / TEXTURES / PERLIN2.PAS < prev    next >
Pascal/Delphi Source File  |  1997-01-08  |  6KB  |  181 lines

  1. PROGRAM Perlin;
  2.  
  3. {
  4.   Example code to demonstrate artificial texture creation
  5.  
  6.   Steve Tattersall for (Maggie 22)
  7.  
  8.   Program and routines to implement noise and turbulence functions
  9.   as described in Perlin (1985) See the article in this issue
  10.   for more help
  11.  
  12.   This is purely an example: those wishing to develop a full texture
  13.   system should think about storing values in the lattice in the range
  14.   0 to 1 rather than as integer values, for example. Also the code is
  15.   completely unoptimised to better show the algorithm used.
  16.  
  17.   email: s.j.tattersall@cms.salford.ac.uk
  18.   smail: 6 Derwent Drive, Littleborough, Lancs OL15 0BT England
  19.  
  20. }
  21.  
  22. USES Dos, Crt, Graph;
  23.  
  24. CONST
  25.    LatticeSize = 20;                      { Lattice size }
  26.  
  27. VAR
  28.  
  29.    x,y,                                 { FOR..NEXT type counters }
  30.    Driver,Mode : Integer;               { used for graphics - ignore }
  31.  
  32.    Lattice : ARRAY [0..LatticeSize,0..LatticeSize,1..3] OF integer;
  33.  
  34.  
  35.    { ------------------ Subprograms ----------------------------------}
  36.    PROCEDURE Init_Lattice;
  37.    VAR
  38.       X, Y : integer;
  39.    BEGIN
  40.       FOR Y:= 0 TO LatticeSize-1 DO
  41.          FOR X:= 0 TO LatticeSize-1 DO
  42.          BEGIN
  43.             Lattice [X,Y,1] := Random (256) - 128;
  44.             Lattice [X,Y,2] := Random (256) - 128;
  45.             Lattice [X,Y,3] := Random (256) - 128;
  46.          END
  47.    END;
  48.  
  49.    { ------------------------------------------------------------ }
  50.    PROCEDURE Get_Lattice ( x,y : integer;
  51.                            VAR value, xgrad, ygrad : real );
  52.    BEGIN
  53.       xgrad := Lattice [x MOD LatticeSize , y MOD LatticeSize, 1];
  54.       ygrad := Lattice [x MOD LatticeSize , y MOD LatticeSize, 2];
  55.       value := Lattice [x MOD LatticeSize , y MOD LatticeSize, 3];
  56.    END;
  57.  
  58.    { ------------------------------------------------------------ }
  59.    FUNCTION Interpolate_Cubic
  60.                ( v0, v1, g0, g1, x : real ) : real;
  61.    BEGIN
  62.       Interpolate_Cubic := (-2*v1 + 2*v0 + g0 + g1 ) * x*x*x
  63.                         +  (-2*g0 - g1 - 3*v0 + 3*v1) * x*x
  64.                         +  (g0) * x
  65.                         +  (v0)
  66.    END;
  67.  
  68.    { ------------------------------------------------------------ }
  69.  
  70.    FUNCTION Interpolate_Square
  71.                ( v0, v1, g0, g1, x : real ) : real;
  72.    BEGIN
  73.       Interpolate_Square := 3 * (-2*v1 + 2*v0 + g0 + g1 ) * x*x
  74.                         +  2 * (-2*g0 - g1 - 3*v0 + 3*v1) * x
  75.                         +  (g0)
  76.    END;
  77.  
  78.    { ------------------------------------------------------------ }
  79.    { This procedure interpolates both value and new gradient }
  80.    PROCEDURE Interpolate1
  81.                   ( VAR value1, value2, xgrad1, xgrad2,
  82.                     ygrad1, ygrad2,
  83.                     xfrac : real;
  84.                 VAR newvalue, newygrad : real );
  85.    BEGIN
  86.       newvalue := Interpolate_Cubic ( value1, value2, xgrad1, xgrad2, xfrac);
  87.       newygrad := Interpolate_Cubic ( value1, value2, ygrad1, ygrad2, xfrac);
  88.    END;
  89.    { ------------------------------------------------------------ }
  90.    { Interpolates the final value only. }
  91.    PROCEDURE Interpolate2
  92.                   ( VAR value1, value2,
  93.                     ygrad1, ygrad2,
  94.                     yfrac    : real;
  95.                 VAR newvalue : real );
  96.    BEGIN
  97.       newvalue := Interpolate_Cubic ( value1, value2, ygrad1, ygrad2, yfrac);
  98.    END;
  99.  
  100.    { ------------------------------------------------------------ }
  101.    FUNCTION Noise2D ( x, y : real ) : real;
  102.  
  103.    VAR
  104.       value1, value2, value3, value4,
  105.       xgrad1, xgrad2, xgrad3, xgrad4,
  106.       ygrad1, ygrad2, ygrad3, ygrad4 : real;
  107.  
  108.       newvalue1, newvalue2,
  109.       newygrad1, newygrad2 : real;
  110.       finalvalue : real;
  111.  
  112.       xint, yint : integer;
  113.       xfrac, yfrac : real;
  114.  
  115.    { Method:
  116.       - Take the 4 corners' xgrad,ygrad and values.
  117.       - Interpolate [x,y] to [x+1,y], giving new value and ygrad
  118.       - Interpolate [x,y+1] to [x+1,y+1], giving same
  119.       - Use two values and ygrads to calculate final value.
  120.    }
  121.    BEGIN
  122.       xint := trunc (x); yint := trunc (y);
  123.       xfrac := x - xint ; yfrac := y - yint;
  124.  
  125.       Get_Lattice ( xint,   yint,   value1, xgrad1, ygrad1 );
  126.       Get_Lattice ( xint+1, yint,   value2, xgrad2, ygrad2 );
  127.       Get_Lattice ( xint,   yint+1, value3, xgrad3, ygrad3 );
  128.       Get_Lattice ( xint+1, yint+1, value4, xgrad4, ygrad4 );
  129.  
  130.       Interpolate1 ( value1, value2, xgrad1, xgrad2,
  131.                            ygrad1, ygrad2, xfrac, newvalue1, newygrad1 );
  132.       Interpolate1 ( value3, value4, xgrad3, xgrad4,
  133.                            ygrad3, ygrad4, xfrac, newvalue2, newygrad2 );
  134.       Interpolate2 ( newvalue1, newvalue2, newygrad1,
  135.                            newygrad2, yfrac, finalvalue );
  136.       Noise2D := finalvalue;
  137.    END;
  138.    { ------------------------------------------------------------ }
  139.  
  140.    FUNCTION Turb2D ( x, y : real ) : real;
  141.    VAR
  142.       T, size : real;
  143.    BEGIN
  144.       T := 0;
  145.       size := 1 ;
  146.       WHILE size > 0.01 DO
  147.       BEGIN
  148.          T := T + abs ( Noise2D(x/size,y/size) * size );
  149.          size := size * 0.5
  150.       END;
  151.       Turb2D := T;
  152.    END;
  153.  
  154.    { ------------------ End of subprograms ------------------------- }
  155.  
  156.  
  157.  
  158. { This is now the main program code - subprograms are called from this }
  159.  
  160. BEGIN
  161.    { Set up the lattice of points }
  162.    Init_Lattice;                            { initialize lattice values }
  163.  
  164.    { Put in graphics mode }
  165.    Driver := DETECT;                        { these lines init the graphics }
  166.  
  167.    InitGraph(Driver,Mode,'');               { add path if using TurboPascal }
  168.  
  169.    { Main plotting loop. To look at the turbulence function, change
  170.      "Noise2D" to "Turb2D" and recompile }
  171.  
  172.    FOR Y := 0 TO 199 DO
  173.       IF NOT KeyPressed THEN
  174.          FOR X := 0 TO 319 DO
  175.             PutPixel ( X,Y, trunc (Noise2D(X*0.01,Y*0.01)) MOD 16 );
  176.  
  177.    readln;                                  { wait for a keypress }
  178.    CloseGraph;                              { shut down graphics, quit }
  179. END.
  180.  
  181.