
/* Example code to export to yaglviewer file format.
 *
 * This module defines Plot3D and PlotHeight for your use.
 *
 * Usage:
 *
 * PlotHeight(var1,from1,to1,steps1,var2,from2,to2,steps2,function,{r,g,b});
 *  This function will generate a mesh of "steps1"*"steps2" vertices,
 *  defining variable "var1" from "from1" to "to1", and "var2" from "from2"
 *  to "to2". At each point, "var1" and "var2" are set, and "function" is
 *  evaluated. Also, the function vertex at that point is given the color
 *  {r,g,b}. The output is written to the current output. 
 *
 */



DefaultColor:={(Eval(var1)-from1)/(to1-from1),(Eval(var2)-from2)/(to2-from2),0.5};

Function("Plot3D",{var1,from1,to1,steps1,var2,from2,to2,steps2,vector,color})
[
  Plot3DAux(var1,from1,to1,steps1,var2,from2,to2,steps2,vector,color);
];
HoldArg("Plot3D",var1);
HoldArg("Plot3D",var2);
HoldArg("Plot3D",vector);
HoldArg("Plot3D",color);
UnFence("Plot3D",10);

Function("PlotHeight",{var1,from1,to1,steps1,var2,from2,to2,steps2,function,color})
[
  Plot3DAux(var1,from1,to1,steps1,var2,from2,to2,steps2,{var1,var2,function},color);
];
HoldArg("PlotHeight",var1);
HoldArg("PlotHeight",var2);
HoldArg("PlotHeight",function);
HoldArg("PlotHeight",color);
UnFence("PlotHeight",10);


Function("Plot3DAux",{var1,from1,to1,steps1,var2,from2,to2,steps2,vector,color})
N(
[
  glBeginQuads();

  /* Write the vertex array */
  Local(plotauxx,plotauxy,scalex,scaley,field);

  scalex:=(to1-from1)/(steps1-1);
  scaley:=(to2-from2)/(steps2-1);

  MacroLocal(var1,var2);

  field:=Apply("Table",
          {Apply("Table",{N({vector,color}),var2,from2,to2,scaley}),
                          var1,from1,to1,scalex});

  Local(plx,len1,len2);
  plx:=field;
  len1:=steps1-1;

  While(len1 > 0)
  [
    Local(upper,lower);
    upper:=plx[[1]];
    lower:=plx[[2]];
    len2:=steps2-1;
    While(len2>0)
    [
      glColor4f(upper[[1]][[2]][[1]],
      		upper[[1]][[2]][[2]],
                upper[[1]][[2]][[3]],1);
      glVertex3f(upper[[1]][[1]]);
      
      glColor4f(lower[[1]][[2]][[1]],
      		lower[[1]][[2]][[2]],
                lower[[1]][[2]][[3]],1);
      glVertex3f(lower[[1]][[1]]);

      glColor4f(lower[[2]][[2]][[1]],
      		lower[[2]][[2]][[2]],
                lower[[2]][[2]][[3]],1);
      glVertex3f(lower[[2]][[1]]);

      glColor4f(upper[[2]][[2]][[1]],
      		upper[[2]][[2]][[2]],
                upper[[2]][[2]][[3]],1);
      glVertex3f(upper[[2]][[1]]);

      upper:=Tail(upper);
      lower:=Tail(lower);
      len2--;
    ];
    plx:=Tail(plx);
    len1--;
  ];
  glEnd();
]);
UnFence("Plot3DAux",10);









Function("ShowBBox",{})
[
    glDisableLighting();
    glColor4f(0,0,1,1);
    glBeginLineStrip();
    glVertex3f({glMinX,glMinY,glMinZ});
    glVertex3f({glMinX,glMaxY,glMinZ});
    glVertex3f({glMaxX,glMaxY,glMinZ});
    glVertex3f({glMaxX,glMinY,glMinZ});
    glVertex3f({glMinX,glMinY,glMinZ});
    glEnd();
    
    glBeginLineStrip();
    glVertex3f({glMinX,glMinY,glMaxZ});
    glVertex3f({glMinX,glMaxY,glMaxZ});
    glVertex3f({glMaxX,glMaxY,glMaxZ});
    glVertex3f({glMaxX,glMinY,glMaxZ});
    glVertex3f({glMinX,glMinY,glMaxZ});
    glEnd();

    glBeginLineStrip();
    glVertex3f({glMinX,glMinY,glMinZ});
    glVertex3f({glMinX,glMinY,glMaxZ});
    glEnd();
    glBeginLineStrip();
    glVertex3f({glMinX,glMaxY,glMinZ});
    glVertex3f({glMinX,glMaxY,glMaxZ});
    glEnd();
    glBeginLineStrip();
    glVertex3f({glMaxX,glMaxY,glMinZ});
    glVertex3f({glMaxX,glMaxY,glMaxZ});
    glEnd();
    glBeginLineStrip();
    glVertex3f({glMaxX,glMinY,glMinZ});
    glVertex3f({glMaxX,glMinY,glMaxZ});
    glEnd();
];

Function("ShowAxis",{})
[

    glDisableLighting();
    glColor4f(1,0,0,1);
    glBeginLineStrip();
    glVertex3f({(glMinX+glMaxX)/2,(glMinY+glMaxY)/2,glMinZ});
    glVertex3f({(glMinX+glMaxX)/2,(glMinY+glMaxY)/2,glMaxZ});
    glEnd();
    glBeginLineStrip();
    glVertex3f({(glMinX+glMaxX)/2,glMinY,(glMinZ+glMaxZ)/2});
    glVertex3f({(glMinX+glMaxX)/2,glMaxY,(glMinZ+glMaxZ)/2});
    glEnd();
    glBeginLineStrip();
    glVertex3f({glMinX,(glMinY+glMaxY)/2,(glMinZ+glMaxZ)/2});
    glVertex3f({glMaxX,(glMinY+glMaxY)/2,(glMinZ+glMaxZ)/2});
    glEnd();
];






Function("Show",{showbody})
[
  InitGlFitter();
  ToFile("DummyFile")
  [
    glClearColor(0,0,0);
    glClear();
    glShadeSmooth();
    glColor4f(1,0,0,1);
    Eval(showbody);
    WriteString("End");NewLine();
  ];

  Local(OriginX,OriginY,OriginZ,Distance,Twist,Elevation,Azimuth,
        ViewWidth,ViewBack,ViewFront);
  ToFile("yaglinit")
  [
    OriginX:= -(glMinX+glMaxX)/2;
    OriginY:= -(glMinY+glMaxY)/2;
    OriginZ:= -(glMinZ+glMaxZ)/2;

    ViewWidth:=MathSqrt((glMaxX-glMinX)^2 +(glMaxY-glMinY)^2 +(glMaxZ-glMinZ)^2)/2;

    ViewBack:= -ViewWidth;
    ViewFront:=ViewWidth;


    Distance:=0;
    Twist:=0;
    Elevation:=45;
    Azimuth:=45;
    
    WriteString("OriginX "); Write(OriginX);       NewLine();
    WriteString("OriginY "); Write(OriginY);       NewLine();
    WriteString("OriginZ "); Write(OriginZ);         NewLine();
    WriteString("Distance "); Write(Distance);     NewLine();
    WriteString("Twist "); Write(Twist);           NewLine();
    WriteString("Elevation "); Write(Elevation);   NewLine();
    WriteString("Azimuth "); Write(Azimuth);       NewLine();
    WriteString("ViewWidth "); Write(ViewWidth);   NewLine();
    WriteString("ViewBack "); Write(ViewBack);     NewLine();
    WriteString("ViewFront "); Write(ViewFront);   NewLine();
    WriteString("End");                           NewLine();
  ];

  SystemCall("yacasviewer DummyFile &");
  True;
];
HoldArg("Show",showbody);


Function("glClearColor",{r,g,b})
[
  WriteString("glClearColor ");
  Write(r); Space();
  Write(g); Space();
  Write(b); NewLine();
];

Function("glColor4f",{r,g,b,a})
[
  WriteString("glColor4f ");
  Write(r); Space();
  Write(g); Space();
  Write(b); Space();
  Write(a); NewLine();
];

Function("InitGlFitter",{})
[
  glMinX:=1;
  glMaxX:= -1;
  glMinY:=1;
  glMaxY:= -1;
  glMinZ:=1;
  glMaxZ:= -1;
];

Function("glTouchPoint",{x,y,z})
[
If(glMinX > glMaxX+1,
  [
    glMinX:=x;
    glMaxX:=x;
    glMinY:=y;
    glMaxY:=y;
    glMinZ:=z;
    glMaxZ:=z;
  ],
  [
    glMinX:=Min(x,glMinX);
    glMaxX:=Max(x,glMaxX);
    glMinY:=Min(y,glMinY);
    glMaxY:=Max(y,glMaxY);
    glMinZ:=Min(z,glMinZ);
    glMaxZ:=Max(z,glMaxZ);
  ]);
];

Function("glVertex3f",{vector})
[
  Local(x,y,z);

  x:=vector[[1]];
  y:=vector[[2]];
  z:=vector[[3]];
  glTouchPoint(x,y,z);
  WriteString("glVertex3f ");
  Write(x); Space();
  Write(y); Space();
  Write(z); NewLine();
];

Function("glNormal3f",{vector})
[
  WriteString("glNormal3f ");
  Write(vector[[1]]); Space();
  Write(vector[[2]]); Space();
  Write(vector[[3]]); NewLine();
];

Function("glTranslatef",{vector})
[
  WriteString("glTranslatef ");
  Write(vector[[1]]); Space();
  Write(vector[[2]]); Space();
  Write(vector[[2]]); NewLine();
];

Function("glRotatef",{angle,vector})
[
  WriteString("glRotatef ");
  Write(angle); Space();
  Write(vector[[1]]); Space();
  Write(vector[[2]]); Space();
  Write(vector[[3]]); NewLine();
];

Function("glClear",{}) [WriteString("glClear");NewLine();];

Function("glPushMatrix",{}) [WriteString("glPushMatrix");NewLine();];
Function("glPopMatrix",{}) [WriteString("glPopMatrix");NewLine();];

Function("glShadeSmooth",{}) [WriteString("glShadeSmooth");NewLine();];
Function("glShadeFlat",{}) [WriteString("glShadeFlat");NewLine();];

Function("glBeginQuads",{}) [WriteString("glBeginQuads");NewLine();];
Function("glBeginLineStrip",{}) [WriteString("glBeginLineStrip");NewLine();];
Function("glBeginTriangles",{}) [WriteString("glBeginTriangles");NewLine();];
Function("glBeginPoints",{}) [WriteString("glBeginPoints");NewLine();];
Function("glEnd",{}) [WriteString("glEnd");NewLine();];

Function("glEnableLighting",{}) [WriteString("glEnableLighting");NewLine();];
Function("glDisableLighting",{}) [WriteString("glDisableLighting");NewLine();];









