--
--	cdxmandel.occ -- Mandelbrot set demo for cdx
--	Copyright (C) 2005 Fred Barnes <frmb@kent.ac.uk>
--	                   Adam Sampson <ats1@kent.ac.uk>
--
--	This program is free software; you can redistribute it and/or modify
--	it under the terms of the GNU General Public License as published by
--	the Free Software Foundation; either version 2 of the License, or
--	(at your option) any later version.
--
--	This program is distributed in the hope that it will be useful,
--	but WITHOUT ANY WARRANTY; without even the implied warranty of
--	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--	GNU General Public License for more details.
--
--	You should have received a copy of the GNU General Public License
--	along with this program; if not, write to the Free Software
--	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--

#INCLUDE "cdx.module"
#INCLUDE "netbar.module"
#INCLUDE "snglmath.module"

VAL INT Width IS 640:
VAL INT Height IS 480:
VAL INT Chunk IS Width / 2:
VAL INT Workers IS 1:
VAL INT Max.count IS 20:
VAL []BYTE Host IS "localhost":
VAL []BYTE BHost IS "localhost":

VAL []INT Colours IS [#010101, #010100, #010001, #000101, #010000, #000100, #000001]:

DATA TYPE COMPLEX
  RECORD
    REAL32 r:
    REAL32 i:
:

PROC calculate.mandel (VAL INT x, y, id, VAL REAL32 zoom, []INT data)
  VAL INT colour IS Colours[id \ (SIZE Colours)]:
  SEQ i = 0 FOR SIZE data
    VAL REAL32 rr.x IS (REAL32 ROUND (x + i)) / (REAL32 ROUND Width):
    VAL REAL32 r.x IS ((rr.x - 0.5) * zoom) - 0.7:
    VAL REAL32 rr.y IS (REAL32 ROUND y) / (REAL32 ROUND Height):
    VAL REAL32 r.y IS ((rr.y - 0.5) * zoom) - 0.3:
    INITIAL COMPLEX z IS [r.x, r.y]:
    INITIAL INT count IS 0:
    INITIAL BOOL running IS TRUE:
    WHILE running
      SEQ
        z := [(z[r] * z[r]) - (z[i] * z[i]), 2.0 * (z[r] * z[i])]
        z[r] := z[r] + r.x
        z[i] := z[i] + r.y
        IF
          ((z[r] * z[r]) + (z[i] * z[i])) > 4.0
            SEQ
              data[i] := (colour * (#FF / Max.count)) * count
              running := FALSE
          TRUE
            SEQ
              count := count + 1
              IF
                count > Max.count
                  SEQ
                    data[i] := colour * #FF
                    running := FALSE
                TRUE
                  SKIP
:

PROC mandel.worker (SHARED CHAN BYTE err!)
  INT cdx.handle, rc, frame:
  NETBAR netbar:
  SEQ
    cdxclient.new (Host, 2345, Width, Height, cdx.handle)
    ASSERT (cdx.handle <> 0)
    netbar.new (BHost, 2346, netbar)
    frame := 0
    INITIAL INT y.height IS Height / netbar[max]:
    INITIAL INT y.offset IS y.height * netbar[id]:
    WHILE TRUE
      SEQ
        netbar.sync (netbar, err!)
        frame := frame + 1
        VAL REAL32 zoom IS POWER (1.5, ABS (REAL32 ROUND ((frame \ 20) - 10)) / 2.0):
        SEQ y = y.offset FOR y.height
          SEQ n = 0 FOR (Width / Chunk)
            VAL INT x IS n * Chunk:
            [Chunk]INT data:
            SEQ
              calculate.mandel (x, y, netbar[id], zoom, data)
              cdxclient.send (cdx.handle, frame, (y * Width) + x, data, rc)
              ASSERT (rc = 0)
:

PROC cdxmandel (CHAN BYTE keyb?, scr!, SHARED CHAN BYTE err!)
  PAR i = 0 FOR Workers
    mandel.worker (err!)
:


