(* Copyright 1993 DCC-IMECC, Universidade Estadual de Campinas *) GENERIC INTERFACE VTG(State); (* Synthesis of three-dimensional textures by the generalized reaction-diffusion technique. *) (* WHERE /\ State.Dim: CONST CARDINAL; /\ State.T: TYPE; /\ State.Throw: PROCEDURE(lo, hi: REAL): State.T; /\ State.Update: PROCEDURE(VAR s: State.T; READONLY d: State.T; dt: REAL; VAR change: REAL); /\ State.Assign: PROCEDURE(VAR s: State.T; READONLY t: State.T; VAR change: REAL); /\ State.Select: PROCEDURE(READONLY s: State.T; which: [0..State.Dim-1]): REAL; *) IMPORT Random; TYPE StateArray = ARRAY OF ARRAY OF ARRAY OF State.T; (* Texel state array. Note: indices are "[z,y,x]" --- as in VGM files. *) LocalState = ARRAY [-1..+1] OF ARRAY [-1..+1] OF ARRAY [-1..+1] OF State.T; (* Texel states in the neighborhood of a grid point. Note: indices are "[dx,dy,dz]" --- opposite to the standard VGM order! *) Operator = PROCEDURE (READONLY ts: LocalState; x, y, z: CARDINAL): State.T; (* Assumed to compute the temporal derivatives "ds/dt" of texel with coordinates "(x,y,z)", given its current state "s" and the states of neighboring texels. *) PROCEDURE Randomize( VAR s: StateArray; lo, hi: REAL; rand: Random.T; ); (* Fills the elements of "s" by calling "State.Throw(lo, hi)". *) PROCEDURE Evolve( VAR s: StateArray; dxdy, dxdz, dydz: CARDINAL; VAR d: StateArray; dt, tol: REAL; nit: CARDINAL; op: Operator ); (* Modifies a discrete periodic 3D texture "s" according to the rule "s := s + dt * d", where "d = ds/dt = op(s, x, y, z)". Note: the texel with coordinates "(x,y,z)" is stored in element "s[z,y,x]" of the array! The texture will have the array "s" as its fundamental region, and period vectors "(nx,0,0)", "(dxdy, ny, 0)", "(dxdz, dydz, nz)". The evolution is stopped once the time derivative "ds/dt" becomes less than "tol", or after "nit" iterations. *) PROCEDURE NewEvolve( VAR s: StateArray; dxdy, dxdz, dydz: CARDINAL; tol: REAL; nit: CARDINAL; op: Operator ); (* Modifies a discrete periodic 3D texture "s" according to the rule "s := op(s)". Note: the texel with coordinates "(x,y,z)" is stored in element "s[z,y,x]" of the array! The texture will have the array "s" as its fundamental region, and period vectors "(nx,0,0)", "(dxdy, ny, 0)", "(dxdz, dydz, nz)". The sizes "nx", "ny", and "nz" must be even. The evolution is stopped once the change "s - op(s)" becomes less than "tol", or after "nit" iterations. *) TYPE GetProc = PROCEDURE (READONLY st: State.T): REAL; (* Should map the state "st" to the range "[0__1]". *) PutProc = PROCEDURE (VAR st: State.T; v: REAL); (* Should store into the state "st" the value "v", which lies in "[0__1]". *) PROCEDURE Write( name: TEXT; READONLY s: StateArray; dxdy, dxdz, dydz: CARDINAL; get: GetProc ); (* Writes some component of the texture as a VGM file called "name.vgm". Scales linearly the values returned by the "get" procedure, mapping the interval "[0__1]" to "[0..255]" (with clipping). *) PROCEDURE Read( name: TEXT; VAR s: StateArray; dxdy, dxdz, dydz: CARDINAL; put: PutProc; ); (* Reads some component of the texture from a VGM file called "name.vgm". Scales linearly the values in the VGM file, from "[0..maxval]" to "[0__1]", and uses the "put" procedure to store them into "s". *) (*** BUILDING BLOCKS ***) PROCEDURE GenerationStep( nx, ny, nz: CARDINAL; dxdy, dxdz, dydz: CARDINAL; VAR s: StateArray; VAR d: StateArray; (* Workspace *) op: Operator; dt: REAL; VAR maxChange, avgChange: REAL; ); (* Performs one evolution step for the dynamical system "ds/dt = op(s)". Namely, computes the derivatives "d := ds/dt" by calling "op" for all texels, then updates "s := s + d * dt" for all texels, recording the maximum and average absolute change in the texel elements. *) PROCEDURE NewGenerationStep( nx, ny, nz: CARDINAL; dxdy, dxdz, dydz: CARDINAL; VAR s: StateArray; op: Operator; VAR maxChange, avgChange: REAL; ); (* Performs one evolution step for the iterative system "s := op(s)". Namely, applies "s := op(s)" to all pixels, in a staggered fashion, recording the maximum and average absolute change in the texel elements. *) END VTG.