/*--------------------------------------------------------------------

  Programm    : Relief3D
  Autor       : Daniel Gembris
  Datum       : September 1989
  Zweck       : Erstellen von Gebirgs-Objekten für Sculpt3D, SA4D ...
  Compiler    : Aztec C V3.6
  Compilieren : cc Relief3D.c, ln Relief3D.o -lc -lm

--------------------------------------------------------------------*/

#include <stdio.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <libraries/dosextens.h>
#include <libraries/dos.h>
#include <functions.h>

/*       DAS IF(F)-SC3D-FORMAT FÜR 3D-OBJEKTE :

      FORM-Chunk:
      4 bytes     "LAMP"
      long        'chunklänge in bytes
      long        'X-lampe
      long        'Z-lampe
      long        'Y-lampe
      long        'helligkeit
      3 bytes     'r-g-b lampenfarbe
      1 byte      'fuellbyte

      OBSV-Chunk:
      4 bytes     "OBSV"
      long        'chunklänge in bytes
      long        'mode 0=paint,1=snapshot,2=photo,3=wireframe
      long        'lens Brennweite
      long        '? suspect 100-150
      long        '? suspect 4-6
      long        'X-location
      long        'Y-location
      long        'Z-location
      word        'resolution 0=lo-res, 1=hi-res
      word        '0=no-interlace, 1=interlace
      word        'lens 0=mormal, 1=wideangle, 2=telephoto, 3=special
      word        'exposure 0=auto, 1=manual
      long        'lens special
      long        'exposure prozent
      long        'exposure manual
      long        'imagesize 0=tiny, 1=small, 2=medium, 3=full, 4=jumbo
      long        'angle of tilt
      long        'anti-alias 0=none, 1=good, 2=best

      WRLD-Chunk:
      4 bytes     "WRLD"
      long        'groundmode 0=none, 1=solid, 2=chechered
      long        'skymode    0=none, 1=solid, 2=graduated
      long        'dimension für ground-raster
      3 bytes     'r-g-b illiumination
      3 bytes     'r-g-b ground1
      3 bytes     'r-g-b ground2
      3 bytes     'r-g-b sky1
      3 bytes     'r-g-b sky2

      VERT-Chunk:
      4 bytes     "VERT"
      long        'chunklänge in bytes
      long        'X-eckpunkt
      long        'Z-eckpunkt
      long        'Y-eckpunkt

      EDGE-Chunk:
      4 bytes     "EDGE"
      long        'chunklänge in bytes
      long        'von Punkt Nr.
      long        'bis Punkt Nr.

      FACE-Chunk:
      4 bytes     "FACE"
      long        'chunklänge in bytes
      long        'von Punkt Nr.
      long        'bis Punkt Nr.
      long        'bis Punkt Nr.
      3 bytes     'r-g-b Fläche
      1 byte      'texture 0=dull, 1=shiny, 2=mirror, 3=luminous,
                  '4=glass, bit#8=smoothing
-----------------------------------------------------------------------*/

char name[80];
long mox, moy, moz, t, i, pc, pd;    /* globale Variablen */
long texture=0x80808000;             /* rot,grün,blau,Oberfläche */
ULONG *faces,ofaces,ausgabe;

wrpoint()
{
  Write(ausgabe, &mox, 4L);
  Write(ausgabe, &moz, 4L);
  Write(ausgabe, &moy, 4L);
}
zaun()
{
  Write(ausgabe, &t, 4L);      /* Kanten */
  Write(ausgabe, &i, 4L);
  Write(ausgabe, &i, 4L);
  Write(ausgabe, &pd, 4L);
  Write(ausgabe, &i, 4L);
  Write(ausgabe, &pc, 4L);
  *faces=i;                 /*Flächen */
  faces++;
  *faces=pd;
  faces++;
  *faces=t;
  faces++;
  *faces=texture;
  faces++;
  *faces=i;
  faces++;
  *faces=pc;
  faces++;
  *faces=pd;
  faces++;
  *faces=texture;
  faces++;
}

main()
{
  char var[5];
  char ask[2];
  float xl=-.15, xr=.26, yo=.9, yu=.47, xc=0, yc=0;  /* Input-Variablen */
  long xm=1000000, ym=1000000, zm=1000000, imax=100;
  long xp=13, yp=13, korx=0, kory=0, korz=0;

  float dx,dy,x1,y1;                                 /* Arbeitsvariablen */
  register float x2, y2, x, y;
  long dyy, dxx, dzz, n, m, k, again, pa, pb;
  long anzpunkte, edgelen, length, faclen;

  again = TRUE;
  while(again)
  {
    printf("\f             Relief3D (w) by Daniel Gembris in 1989\n");
    printf("             ======================================\n");
    printf("\nUnter welchem Namen soll das Gebirgs-Objekt abgespeichert");
    printf(" werden?\n");
    scanf("%79s", name);
    if ((ausgabe = (LONG) Open((UBYTE *) name, MODE_NEWFILE))==0L)
    {
     printf("\nDatei konnte nicht geöffnet werden!\n");
     exit(FALSE);
    }

    while(strcmp(var, "g"))
    {
      printf("\fApfelmännchen-Parameter :\n");
      printf("xl   = %f\n", xl);
      printf("xr   = %f\n", xr);
      printf("yo   = %f\n", yo);
      printf("yu   = %f\n", yu);
      printf("xc   = %f\n", xc);
      printf("yc   = %f\n", yc);
      printf("imax = %ld\n", imax);
      printf("xp   = %ld\n", xp);
      printf("yp   = %ld\n", yp);
      printf("\nObjekt-Parameter :\n");
      printf("xm   = %ld\n", xm);
      printf("ym   = %ld\n", ym);
      printf("zm   = %ld\n", zm);
      printf("korx = %ld\n", korx);
      printf("kory = %ld\n", kory);
      printf("korz = %ld\n", korz);
      printf("\nWelche Variable möchten Sie ändern ?\n");
      printf("(Berechnung starten : g)\n");
      scanf("%s", var);
      if (strcmp(var, "g")) printf("Neuer Wert :\n");
      if (!strcmp(var, "xl")) scanf("%f", &xl);
      if (!strcmp(var, "xr")) scanf("%f", &xr);
      if (!strcmp(var, "yu")) scanf("%f", &yu);
      if (!strcmp(var, "yo")) scanf("%f", &yo);
      if (!strcmp(var, "xc")) scanf("%f", &xc);
      if (!strcmp(var, "yc")) scanf("%f", &yc);
      if (!strcmp(var, "imax")) scanf("%ld", &imax);
      if (!strcmp(var, "xp")) scanf("%ld", &xp);
      if (!strcmp(var, "yp")) scanf("%ld", &yp);
      if (!strcmp(var, "xm")) scanf("%ld", &xm);
      if (!strcmp(var, "ym")) scanf("%ld", &ym);
      if (!strcmp(var, "zm")) scanf("%ld", &zm);
      if (!strcmp(var, "korx")) scanf("%ld", &korx);
      if (!strcmp(var, "kory")) scanf("%ld", &kory);
      if (!strcmp(var, "korz")) scanf("%ld", &korz);
    }

    *var = ' ';
    anzpunkte = (2*(xp-1)+2*(yp-1)+xp*yp)*3*4; /* Speicherverbrauch */
    edgelen   = (6*xp*yp+8*xp+8*yp-20)*4+32;   /* berechnen */
    faclen    = 6*xp*yp+6*xp+6*yp-12;
    faclen    = (faclen+(faclen/3))*4;
    length    = anzpunkte+edgelen+faclen+36;
    printf("\nDie Objektdatei wird genau %ld Bytes lang sein\n", length);

    length = length-8;                 /* Objekt-Kopf schreiben */
    Write(ausgabe, "FORM", 4L);
    Write(ausgabe, &length, 4L);
    Write(ausgabe, "SC3D", 4L);
    Write(ausgabe, "VERT", 4L);
    Write(ausgabe, &anzpunkte, 4L);
                                       /* Apfelmännchen-Berechnung */
    dyy=ym/imax;
    dxx=xm/(xp-1);
    dzz=zm/(yp-1);
    dx=(xr-xl)/xp;
    dy=(yo-yu)/yp;
    y1=yu-dy;
  
    for(n=0;n<yp;n++)
    {
      y1=y1+dy;
      x1=xl-dx;
      moz=n*dzz+korz;
      for(m=0;m<xp;m++)
      {
        x1=x1+dx;
        k=0;
        x2=xc;
        y2=yc;
        do
        {
          x=x2;
          y=y2;
          x2=x*x-y*y+x1;
          y2=2*x*y+y1;
          k+=1;
        }
        while ((k < imax) && (x2*x2+y2*y2<4));
        mox=m*dxx+korx;
        moy=k*dyy+kory;
        wrpoint();
      }
    }
    moy=kory;                  /* zusätzliche Punkte schreiben */
    moz=korz;
    for(i=0;i<(xp-1);i++)
    {
      mox=i*dxx+korx;
      wrpoint();
    }
    mox=korx+xm;
    for(i=0;i<(yp-1);i++)
    {
      moz=i*dzz+korz;
      wrpoint();
    }
    moz=korz+zm;
    for(i=(xp-1);i>0;i--)
    {
      mox=i*dxx+korx;
      wrpoint();
    }
    mox=korx;
    for(i=(yp-1);i>0;i--)
    {
      moz=i*dzz+korz;
      wrpoint();
    }

    Write(ausgabe, "EDGE", 4L);       /*Kanten und Flächen schreiben */
    Write(ausgabe, &edgelen, 4L);     /*(Flächen werden im RAM zwischenge-*/
    ofaces = AllocMem(faclen,0L); /*speichert) */
    if (ofaces==0L)
    {
      printf("\nNicht genug Speicher !\n");
      exit(FALSE);
    }
    faces=ofaces;

    for(n=0;n<(yp-1);n++)
    {
      for(m=0;m<(xp-1);m++)
      {
        pa=n*xp+m;                    /* Px gibt eine Punktnummer an */
        pb=pa+1;
        pc=pa+xp;
        pd=pc+1;
        Write(ausgabe, &pa, 4L);
        Write(ausgabe, &pb, 4L);
        Write(ausgabe, &pa, 4L);
        Write(ausgabe, &pc, 4L);
        Write(ausgabe, &pa, 4L);
        Write(ausgabe, &pd, 4L);
        *faces=pa;
        faces++;
        *faces=pb;
        faces++;
        *faces=pd;
        faces++;
        *faces=texture;
        faces++;
        *faces=pa;
        faces++;
        *faces=pc;
        faces++;
        *faces=pd;
        faces++;
        *faces=texture;
        faces++;
      }
    }
    i=xp*yp;
    for(t=0;t<(xp-1);t++)
    {
      pc=i+1;
      pd=t+1;
      zaun();
      i++;
    }
    for(t=xp-1;t<(xp*yp)-1;t+=xp)
    {
      pc=i+1;
      pd=t+xp;
      zaun();
      Write(ausgabe, &t, 4L);
      Write(ausgabe, &pd, 4L);
      i++;
    }
    for(t=(xp*yp)-1;t>xp*(yp-1);t--)
    {
      pc=i+1;
      pd=t-1;
      zaun();
      Write(ausgabe, &t, 4L);
      Write(ausgabe, &pd, 4L);
      i++;
    }
    for(t=xp*(yp-1);t>0;t-=xp)
    {
      pc=i+1;
      if (pc==2*(xp-1)+2*(yp-1)+xp*yp) pc=xp*yp;
      pd=t-xp;
      zaun();
      i++;
    }
    pa=xp*yp;                          /* Boden definieren */
    pc=pa+xp-1;
    pb=pc+yp-1;
    pd=pb+xp-1;
    Write(ausgabe, &pa, 4L);
    Write(ausgabe, &pb, 4L);
    Write(ausgabe, &pa, 4L), Write(ausgabe, &pc, 4L);
    Write(ausgabe, &pc, 4L), Write(ausgabe, &pb, 4L);
    Write(ausgabe, &pb, 4L), Write(ausgabe, &pd, 4L);
    Write(ausgabe, &pd, 4L), Write(ausgabe, &pa, 4L);
    *faces=pa;
    faces++;
    *faces=pb;
    faces++;
    *faces=pc;
    faces++;
    *faces=texture;
    faces++;
    *faces=pa;
    faces++;
    *faces=pb;
    faces++;
    *faces=pd;
    faces++;
    *faces=texture;

    Write(ausgabe, "FACE", 4L);
    Write(ausgabe, &faclen, 4L);
    Write(ausgabe, ofaces, faclen);
    Close(ausgabe);
    FreeMem(ofaces, faclen);

    printf("\nNeustart (j|n) ?\n");
    scanf("%s", ask);
    if (!(strcmp(ask, "n"))) again=FALSE;
  }
}

 
