import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.image.*;
import java.awt.*;
import java.io.*;
import java.net.*;

class face {
  int p,p1,p2,nr,clr,clr1,clr2,nx,ny,nx1,ny1,nx2,ny2;
}

class PL {
  int x,mapx,mapy;
}

class POLY3_2 {
  int x[] = new int[3];
  int y[] = new int[3];
}

class mat {

  int a1,a2,a3,b1,b2,b3,c1,c2,c3;

}

class idx {
  int z,nr;
}

class Particle {

float fx,fy,fz;
int sx,sy,sz,px,py,pz,phix,phiy,phiz;
mat rotx = new mat(), roty = new mat(), rotz = new mat();

  public Particle(int x, int y, int z) {
    fx=x; fy=y; fz=z;
    sx=x; sy=y; sz=z;
  }

  public void addx(float x) {
    fx+=x;
    sx=(int)fx;
  }

  public void addy(float y) {
    fy+=y;
    sy=(int)fy;
  }

  public void addz(float z) {
    fz+=z;
    sz=(int)fz;
  }

  public void setRotx(int x) {
    phix=x;
  }

  public void setRoty(int y) {
    phiy=y;
  }

  public void setRotz(int z) {
    phiz=z;
  }

}

public class Coal extends Applet implements Runnable{


int i,i1,x,y,color,cnt = 1,xpos = 0,timer = 0, cnter = 0, cnter1 = 0, cval = 1;
int scrx=120,scrx1=120,scrx2=200,scrx3=200,sx=60;
int cameray = 120, camerax = 0, cameraz = 100;
double tstval,xadd,xval,yval;
int cnt1 = 0;
int cnt2 = 0;
int cnt3 = 0;
Particle stars[] = new Particle[250];
double lightx = 0.1f, lighty=0.1f, lightz=0.8f;
idx indx[] = new idx[520];
int maxverts,maxface;
int SinTab[] = new int[256],CosTab[] = new int[256];
mat rotz = new mat(), roty = new mat(), rotx = new mat();
int pointx[] = new int[1290],pointy[] = new int[1290],pointz[] = new int[300], pointz2[] = new int[300];
double normx[] = new double[900], normy[] = new double[900], normz[] = new double[900];
double gnormx[] = new double[520], gnormy[] = new double[520], gnormz[] = new double[520];
int px[] = new int[300],py[] = new int[300],pz[] = new int[300];
int pix[] = new int[240*200];
int pix1[] = new int[240*200];
int difx[] = new int[240*200];
int dispic[] = new int[240*200];
int blue[] = new int[240*200];
int red[] = new int[240*200];
int green[] = new int[240*200];
int tex[];
int noise[] = new int[3000];
int cloud[] = new int[128*128];
int cloud1[] = new int[128*128];
double Stab[] = new double[361];
double Ctab[] = new double[361];
Image Img,Img1,Shows[];
int frameNumber = -1;
MemoryImageSource source;
Toolkit t = getToolkit();
Thread killme = null;
PixelGrabber grab;
Dimension offDimension;
Image offImage;
Graphics offGraphics;
int delay,partnr;
int sxpos[] = new int[240],sypos[] = new int[240];
int scnt[] = new int[125];
int picxsize = 240;
int picysize = 100;
double brnval = 0.2f;
boolean pos = false;
boolean pos1[] = new boolean[121];
String s,text[] = new String[4];
MediaTracker tracer = new MediaTracker(this);
face facelist[] = new face[520];
AudioClip music;
PL poly_hullxs[] = new PL[3000];
PL poly_hullxe[] = new PL[3000];

Color c = new Color(0.0f,0.0f,0.0f);

public int Rand1(int base,int delta)
{ int i;
  i=base+(int)(Math.random()*delta)-delta/2;
  if (i<0) i=0; if (i>255) i=255;
  return i;
}

  public int Sinus(int Idx)
   { return(SinTab[Idx]); }

  public int Cosinus(int Idx)
   { return(CosTab[Idx]); }

  public void Calrotxmat (int phix, mat rotx)
   {
     rotx.a1=0; rotx.a2=0; rotx.a3=0;
     rotx.b1=0; rotx.b2=Cosinus(phix); rotx.b3=Sinus(phix);
     rotx.c1=0; rotx.c2=Sinus(phix); rotx.c3=Cosinus(phix);
   }

   public void Calrotymat (int phiy, mat roty)
   {
      roty.a1=Cosinus(phiy); roty.a2=0; roty.a3=-Sinus(phiy);
      roty.b1=0; roty.b2=0; roty.b3=0;
      roty.c1=Sinus(phiy); roty.c2=0; roty.c3=Cosinus(phiy);
   }

   public void Calrotzmat (int phiz, mat rotz)
   {
     rotz.a1=Cosinus(phiz); rotz.a2=Sinus(phiz); rotz.a3=0;
     rotz.b1=Sinus(phiz); rotz.b2=Cosinus(phiz); rotz.b3=0;
     rotz.c1=0; rotz.c2=0; rotz.c3=0;
   }

void Normvek(double normx[], double normy[], double normz[], int nr)
{
  double l=normx[nr]*normx[nr]+normy[nr]*normy[nr]+normz[nr]*normz[nr];
  if (l>0.0f) { l=1/Math.sqrt(l);
    normx[nr]*=l;
    normy[nr]*=l;
    normz[nr]*=l;
 }
}

void Calcnorm(face Face,double normx[], double normy[], double normz[], int nr)
{ int x,y,z;
  normx[nr]=normy[nr]=normz[nr]=0;
  x=(py[Face.p]-py[Face.p1])*(pz[Face.p]+pz[Face.p1]);
  y=(pz[Face.p]-pz[Face.p1])*(px[Face.p]+px[Face.p1]);
  z=(px[Face.p]-px[Face.p1])*(py[Face.p]+py[Face.p1]);
  normx[nr]+=x;
  normy[nr]+=y;
  normz[nr]+=z;
  x=(py[Face.p1]-py[Face.p2])*(pz[Face.p1]+pz[Face.p2]);
  y=(pz[Face.p1]-pz[Face.p2])*(px[Face.p1]+px[Face.p2]);
  z=(px[Face.p1]-px[Face.p2])*(py[Face.p1]+py[Face.p2]);
  normx[nr]+=x;
  normy[nr]+=y;
  normz[nr]+=z;
  x=(py[Face.p2]-py[Face.p])*(pz[Face.p2]+pz[Face.p]);
  y=(pz[Face.p2]-pz[Face.p])*(px[Face.p2]+px[Face.p]);
  z=(px[Face.p2]-px[Face.p])*(py[Face.p2]+py[Face.p]);
  normx[nr]+=x;
  normy[nr]+=y;
  normz[nr]+=z;
//  normz[nr]*=-1;
}

public int[] CalcMarble(int K,int H)
{ int i,j,i2,j2,i3,j3,h,h2,delta,a,b,c,d;
  int cloud[] = new int[256*256];
  for (h=256; h>1; h=h2)
    { h2=h/2; delta=h*K+H;
      for (i=0; i<256; i+=h)
        for (i2=((i+h)&255),j=0; j<256; j+=h)
          { /* Get corner heights (a=TL, b=TR, c=BL, d=BR) */
            j2=((j+h)&255);
            i3=i+h2; j3=j+h2;
            a=cloud[(i<<8)+j]; b=cloud[(i2<<8)+j];
            c=cloud[(i<<8)+j2]; d=cloud[(i2<<8)+j2];
            /* Central point */
            cloud[(i3<<8)+j3]=Rand1((a+b+c+d)/4,delta);
            /* Top point */
            if (i==0)
              cloud[(i3<<8)+j]=Rand1((a+b)/2,delta);
            /* Left point */
            if (j==0)
              cloud[(i<<8)+j3]=Rand1((a+c)/2,delta);
            /* Right point */
            cloud[(i2<<8)+j3]=Rand1((b+d)/2,delta);
            /* Bottom point */
            cloud[(i3<<8)+j2]=Rand1((c+d)/2,delta);
          }
    }
    return cloud;
}

void Texture_poly3(POLY3_2 pnt,int x0,int y0,int x1,int y1,int x2, int y2) {
//ÍÍÍ shade poly with Z-Buffer

  int i,i1,miny,maxy;
  int ys,ye;     // y start,end
  int xl,yl;     // x,y length
  int xp,yp;     // x,y position
  int xadd,yadd; // x,y adders
  int xcnt;      // x position counter
  int cadd,zadd;
  int ccnt,zcnt;
  int a1,a2;
  int ysort[] = new int[3];
  int order;
  int map = 0;
  
  // calc point order in y axis
  ysort[2] = 2;
  if(pnt.y[0]<pnt.y[1]) {
    ysort[0] = 0; ysort[1] = 1;
  } else {
    ysort[0] = 1; ysort[1] = 0;
  }
  if(pnt.y[ysort[1]]>pnt.y[ysort[2]]) {
    i = ysort[2];  // swap ysort[x] and ysort[y]
    ysort[2] = ysort[1];
    ysort[1] = i;
  };
  if(pnt.y[ysort[0]]>pnt.y[ysort[1]]) {
    i = ysort[0];   // swap ysort[x] and ysort[y]
    ysort[0] = ysort[1];
    ysort[1] = i;
  };

  // y start,end setzen
  ys = pnt.y[ysort[0]];
  ye = pnt.y[ysort[2]];

  // winkel berechnen:  a1 zu y-achse, a2 zu y-achse
  a1 = ((pnt.x[ysort[1]]-pnt.x[ysort[0]]) << 16)/((pnt.y[ysort[1]]-pnt.y[ysort[0]])+1);
  a2 = ((pnt.x[ysort[2]]-pnt.x[ysort[0]]) << 16)/((pnt.y[ysort[2]]-pnt.y[ysort[0]])+1);

  // Sortierfolge abbilden
  order = ysort[0] * 3 + ysort[2];

  // map bilden, bit 0 -> start punkte 1 -> end punkte
  switch(order) {
    // p0,p2,p1: a2<=a1 -> 110
    case 1: map = 6; break;
    // p0,p1,p2: a2<=a1 -> 011
    case 2: map = 3; break;
    // p1,p2,p0: a2<=a1 -> 110
    case 3: map = 6; break;
    // p1,p0,p2: a2<=a1 -> 101
    case 5: map = 5; break;
    // p2,p1,p0: a2<=a1 -> 011
    case 6: map = 3; break;
    // p2,p0,p1: a2<=a1 -> 101
    case 7: map = 5; break;
  }
  if(a2>a1) map ^= 0xff;  // angle a2>a1 -> turn map

  //ÄÄÄ  run from x0,y0 to x1,y1
  xl = pnt.x[1] - pnt.x[0];
  yl = Math.abs(pnt.y[1] - pnt.y[0]);
  if((map & 0x01) == 0) {
  // poly_hullxs; else poly_hull = poly_hullxe;
    yp = pnt.y[0];
    poly_hullxs[yp].x = pnt.x[0];
    ccnt = (x0 << 8);
    zcnt = (y0 << 8);
    poly_hullxs[yp].mapx = ccnt;
    poly_hullxs[yp].mapy = zcnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[1]>pnt.y[0]) yadd = 1; else yadd = -1;
      xcnt = pnt.x[0] << 8;
      cadd = ((x1 - x0) << 8) / yl;
      zadd = ((y1 - y0) << 8) / yl;
      while(yp != pnt.y[1]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxs[yp].x = xcnt / 256;
        ccnt += cadd;
        zcnt += zadd;
        poly_hullxs[yp].mapx = ccnt;
        poly_hullxs[yp].mapy = zcnt;
      }
    }
  } else {
    yp = pnt.y[0];
    poly_hullxe[yp].x = pnt.x[0];
    ccnt = (x0 << 8);
    zcnt = (y0 << 8);
    poly_hullxe[yp].mapx = ccnt;
    poly_hullxe[yp].mapy = zcnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[1]>pnt.y[0]) yadd = 1; else yadd = -1;
      xcnt = pnt.x[0] << 8;
      cadd = ((x1 - x0) << 8) / yl;
      zadd = ((y1 - y0) << 8) / yl;
      while(yp != pnt.y[1]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxe[yp].x = xcnt / 256;
        ccnt += cadd;
        zcnt += zadd;
        poly_hullxe[yp].mapx = ccnt;
        poly_hullxe[yp].mapy = zcnt;
      }
    }
  }
  //ÄÄÄ  run from x1,y1 to x2,y2
  xl = pnt.x[2] - pnt.x[1];
  yl = Math.abs(pnt.y[2] - pnt.y[1]);
  if((map & 0x02) == 0) {
    //poly_hull = poly_hullxs; else poly_hull = poly_hullxe;
    yp = pnt.y[1];
    poly_hullxs[yp].x = pnt.x[1];
    ccnt = (x1 << 8);
    zcnt = (y1 << 8);
    poly_hullxs[yp].mapx = ccnt;
    poly_hullxs[yp].mapy = zcnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[2]>pnt.y[1]) yadd = 1; else yadd = -1; // y direction
      xcnt = pnt.x[1] << 8;
      cadd = ((x2 - x1) << 8) / yl;
      zadd = ((y2 - y1) << 8) / yl;
      while(yp != pnt.y[2]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxs[yp].x = xcnt / 256;
        ccnt += cadd;
        zcnt += zadd;
        poly_hullxs[yp].mapx = ccnt;
        poly_hullxs[yp].mapy = zcnt;
      }
    }
  } else {
    yp = pnt.y[1];
    poly_hullxe[yp].x = pnt.x[1];
    ccnt = (x1 << 8);
    zcnt = (y1 << 8);
    poly_hullxe[yp].mapx = ccnt;
    poly_hullxe[yp].mapy = zcnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[2]>pnt.y[1]) yadd = 1; else yadd = -1; // y direction
      xcnt = pnt.x[1] << 8;
      cadd = ((x2 - x1) << 8) / yl;
      zadd = ((y2 - y1) << 8) / yl;
      while(yp != pnt.y[2]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxe[yp].x = xcnt / 256;
        ccnt += cadd;
        zcnt += zadd;
        poly_hullxe[yp].mapx = ccnt;
        poly_hullxe[yp].mapy = zcnt;
      }
    }
  }
  //ÄÄÄ  run from x2,y2 to x0,y0
  xl = pnt.x[0] - pnt.x[2];
  yl = Math.abs(pnt.y[0] - pnt.y[2]);
  if((map & 0x04) == 0) {
    //poly_hull = poly_hullxs; else poly_hull = poly_hullxe;
    yp = pnt.y[2];
    poly_hullxs[yp].x = pnt.x[2];
    ccnt = (x2 << 8);
    zcnt = (y2 << 8);
    poly_hullxs[yp].mapx = ccnt;
    poly_hullxs[yp].mapy = zcnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[0]>pnt.y[2]) yadd = 1; else yadd = -1;
      xcnt = pnt.x[2] << 8;
      cadd = ((x0 - x2) << 8) / yl;
      zadd = ((y0 - y2) << 8) / yl;
      while(yp != pnt.y[0]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxs[yp].x = xcnt / 256;
        ccnt += cadd;
        zcnt += zadd;
        poly_hullxs[yp].mapx = ccnt;
        poly_hullxs[yp].mapy = zcnt;
      }
    }
   } else {
    yp = pnt.y[2];
    poly_hullxe[yp].x = pnt.x[2];
    ccnt = (x2 << 8);
    zcnt = (y2 << 8);
    poly_hullxe[yp].mapx = ccnt;
    poly_hullxe[yp].mapy = zcnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[0]>pnt.y[2]) yadd = 1; else yadd = -1;
      xcnt = pnt.x[2] << 8;
      cadd = ((x0 - x2) << 8) / yl;
      zadd = ((y0 - y2) << 8) / yl;
      while(yp != pnt.y[0]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxe[yp].x = xcnt / 256;
        ccnt += cadd;
        zcnt += zadd;
        poly_hullxe[yp].mapx = ccnt;
        poly_hullxe[yp].mapy = zcnt;
      }
    }
  }
  // draw
  for(i=ys; i<=ye; i++) {
    int ypos=i*picxsize;
    ccnt = (poly_hullxs[i].mapx + 127) << 8;
    zcnt = (poly_hullxs[i].mapy + 127) << 8;
    xl = poly_hullxe[i].x - poly_hullxs[i].x;
    if(xl>0) {
      cadd = ((poly_hullxe[i].mapx - poly_hullxs[i].mapx) << 8)/ xl;
      zadd = ((poly_hullxe[i].mapy - poly_hullxs[i].mapy) << 8)/ xl;
    } else {cadd = 0; zadd=0; }
    for(i1=poly_hullxs[i].x; i1<=poly_hullxe[i].x; i1++) {
       if (i1>0&&i1<picxsize&&i>0&&i<picysize) red[i1+ypos]=tex[(ccnt >> 16)+((zcnt >> 16) << 8)];
      ccnt += cadd;
      zcnt += zadd;
    }
  }
}

public void Bubble (int xc,int yc,int r,int col)
{int x,y,p;
  x=0; y=r;
  if (xc+x>0&&xc+x<picxsize&&yc+y>0&&yc+y<picysize) blue[xc+x+(yc+y)*picxsize]=col;
  if (xc-x>0&&xc-x<picxsize&&yc+y>0&&yc+y<picysize) blue[xc-x+(yc+y)*picxsize]=col;
  if (xc+x>0&&xc+x<picxsize&&yc-y>0&&yc-y<picysize) blue[xc+x+(yc-y)*picxsize]=col;
  if (xc-x>0&&xc-x<picxsize&&yc-y>0&&yc-y<picysize) blue[xc-x+(yc-y)*picxsize]=col;
  if (xc+y>0&&xc+y<picxsize&&yc+x>0&&yc+x<picysize) blue[xc+y+(yc+x)*picxsize]=col;
  if (xc-y>0&&xc-y<picxsize&&yc+x>0&&yc+x<picysize) blue[xc-y+(yc+x)*picxsize]=col;
  if (xc+y>0&&xc+y<picxsize&&yc-x>0&&yc-x<picysize) blue[xc+y+(yc-x)*picxsize]=col;
  if (xc-y>0&&xc-y<picxsize&&yc-x>0&&yc-x<picysize) blue[xc-y+(yc-x)*picxsize]=col;
  p=1-r;
  while (x<y) {
    if (p<0) x=x+1; else {x=x+1; y=y-1;}
    if (p<0) p=p+2*x+1; else p=p+2*(x-y)+1;
    if (xc+x>0&&xc+x<picxsize&&yc+y>0&&yc+y<picysize) blue[xc+x+(yc+y)*picxsize]=col;
    if (xc-x>0&&xc-x<picxsize&&yc+y>0&&yc+y<picysize) blue[xc-x+(yc+y)*picxsize]=col;
    if (xc+x>0&&xc+x<picxsize&&yc-y>0&&yc-y<picysize) blue[xc+x+(yc-y)*picxsize]=col;
    if (xc-x>0&&xc-x<picxsize&&yc-y>0&&yc-y<picysize) blue[xc-x+(yc-y)*picxsize]=col;
    if (xc+y>0&&xc+y<picxsize&&yc+x>0&&yc+x<picysize) blue[xc+y+(yc+x)*picxsize]=col;
    if (xc-y>0&&xc-y<picxsize&&yc+x>0&&yc+x<picysize) blue[xc-y+(yc+x)*picxsize]=col;
    if (xc+y>0&&xc+y<picxsize&&yc-x>0&&yc-x<picysize) blue[xc+y+(yc-x)*picxsize]=col;
    if (xc-y>0&&xc-y<picxsize&&yc-x>0&&yc-x<picysize) blue[xc-y+(yc-x)*picxsize]=col;
  }
}

public void Circle1 (int xc,int yc,int r,int col)
{int x,y,p;
  x=0; y=r;
  if (xc+x>0&&xc+x<picxsize&&yc+y>0&&yc+y<picysize) pix1[xc+x+(yc+y)*picxsize]=col;
  if (xc-x>0&&xc-x<picxsize&&yc+y>0&&yc+y<picysize) pix1[xc-x+(yc+y)*picxsize]=col;
  if (xc+x>0&&xc+x<picxsize&&yc-y>0&&yc-y<picysize) pix1[xc+x+(yc-y)*picxsize]=col;
  if (xc-x>0&&xc-x<picxsize&&yc-y>0&&yc-y<picysize) pix1[xc-x+(yc-y)*picxsize]=col;
  if (xc+y>0&&xc+y<picxsize&&yc+x>0&&yc+x<picysize) pix1[xc+y+(yc+x)*picxsize]=col;
  if (xc-y>0&&xc-y<picxsize&&yc+x>0&&yc+x<picysize) pix1[xc-y+(yc+x)*picxsize]=col;
  if (xc+y>0&&xc+y<picxsize&&yc-x>0&&yc-x<picysize) pix1[xc+y+(yc-x)*picxsize]=col;
  if (xc-y>0&&xc-y<picxsize&&yc-x>0&&yc-x<picysize) pix1[xc-y+(yc-x)*picxsize]=col;
  p=1-r;
  while (x<y) {
    if (p<0) x=x+1; else {x=x+1; y=y-1;}
    if (p<0) p=p+2*x+1; else p=p+2*(x-y)+1;
    if (xc+x>0&&xc+x<picxsize&&yc+y>0&&yc+y<picysize) pix1[xc+x+(yc+y)*picxsize]=col;
    if (xc-x>0&&xc-x<picxsize&&yc+y>0&&yc+y<picysize) pix1[xc-x+(yc+y)*picxsize]=col;
    if (xc+x>0&&xc+x<picxsize&&yc-y>0&&yc-y<picysize) pix1[xc+x+(yc-y)*picxsize]=col;
    if (xc-x>0&&xc-x<picxsize&&yc-y>0&&yc-y<picysize) pix1[xc-x+(yc-y)*picxsize]=col;
    if (xc+y>0&&xc+y<picxsize&&yc+x>0&&yc+x<picysize) pix1[xc+y+(yc+x)*picxsize]=col;
    if (xc-y>0&&xc-y<picxsize&&yc+x>0&&yc+x<picysize) pix1[xc-y+(yc+x)*picxsize]=col;
    if (xc+y>0&&xc+y<picxsize&&yc-x>0&&yc-x<picysize) pix1[xc+y+(yc-x)*picxsize]=col;
    if (xc-y>0&&xc-y<picxsize&&yc-x>0&&yc-x<picysize) pix1[xc-y+(yc-x)*picxsize]=col;
  }
}

public void Circle (int xc,int yc,int r,int col)
{int x,y,p;
  x=0; y=r;
  if (xc+x>0&&xc+x<240&&yc+y>0&&yc+y<200) if (difx[xc+x+(yc+y)*240]>15&&dispic[xc+x+(yc+y)*240]<col) dispic[xc+x+(yc+y)*240]=col;
  if (xc-x>0&&xc-x<240&&yc+y>0&&yc+y<200) if (difx[xc-x+(yc+y)*240]>15&&dispic[xc-x+(yc+y)*240]<col) dispic[xc-x+(yc+y)*240]=col;
  if (xc+x>0&&xc+x<240&&yc-y>0&&yc-y<200) if (difx[xc+x+(yc-y)*240]>15&&dispic[xc+x+(yc-y)*240]<col) dispic[xc+x+(yc-y)*240]=col;
  if (xc-x>0&&xc-x<240&&yc-y>0&&yc-y<200) if (difx[xc-x+(yc-y)*240]>15&&dispic[xc-x+(yc-y)*240]<col) dispic[xc-x+(yc-y)*240]=col;
  if (xc+y>0&&xc+y<240&&yc+x>0&&yc+x<200) if (difx[xc+y+(yc+x)*240]>15&&dispic[xc+y+(yc+x)*240]<col) dispic[xc+y+(yc+x)*240]=col;
  if (xc-y>0&&xc-y<240&&yc+x>0&&yc+x<200) if (difx[xc-y+(yc+x)*240]>15&&dispic[xc-y+(yc+x)*240]<col) dispic[xc-y+(yc+x)*240]=col;
  if (xc+y>0&&xc+y<240&&yc-x>0&&yc-x<200) if (difx[xc+y+(yc-x)*240]>15&&dispic[xc+y+(yc-x)*240]<col) dispic[xc+y+(yc-x)*240]=col;
  if (xc-y>0&&xc-y<240&&yc-x>0&&yc-x<200) if (difx[xc-y+(yc-x)*240]>15&&dispic[xc-y+(yc-x)*240]<col) dispic[xc-y+(yc-x)*240]=col;
  p=1-r;
  while (x<y) {
    if (p<0) x=x+1; else {x=x+1; y=y-1;}
    if (p<0) p=p+2*x+1; else p=p+2*(x-y)+1;
    if (xc+x>0&&xc+x<240&&yc+y>0&&yc+y<200) if (difx[xc+x+(yc+y)*240]>15&&dispic[xc+x+(yc+y)*240]<col) dispic[xc+x+(yc+y)*240]=col;
    if (xc-x>0&&xc-x<240&&yc+y>0&&yc+y<200) if (difx[xc-x+(yc+y)*240]>15&&dispic[xc-x+(yc+y)*240]<col) dispic[xc-x+(yc+y)*240]=col;
    if (xc+x>0&&xc+x<240&&yc-y>0&&yc-y<200) if (difx[xc+x+(yc-y)*240]>15&&dispic[xc+x+(yc-y)*240]<col) dispic[xc+x+(yc-y)*240]=col;
    if (xc-x>0&&xc-x<240&&yc-y>0&&yc-y<200) if (difx[xc-x+(yc-y)*240]>15&&dispic[xc-x+(yc-y)*240]<col) dispic[xc-x+(yc-y)*240]=col;
    if (xc+y>0&&xc+y<240&&yc+x>0&&yc+x<200) if (difx[xc+y+(yc+x)*240]>15&&dispic[xc+y+(yc+x)*240]<col) dispic[xc+y+(yc+x)*240]=col;
    if (xc-y>0&&xc-y<240&&yc+x>0&&yc+x<200) if (difx[xc-y+(yc+x)*240]>15&&dispic[xc-y+(yc+x)*240]<col) dispic[xc-y+(yc+x)*240]=col;
    if (xc+y>0&&xc+y<240&&yc-x>0&&yc-x<200) if (difx[xc+y+(yc-x)*240]>15&&dispic[xc+y+(yc-x)*240]<col) dispic[xc+y+(yc-x)*240]=col;
    if (xc-y>0&&xc-y<240&&yc-x>0&&yc-x<200) if (difx[xc-y+(yc-x)*240]>15&&dispic[xc-y+(yc-x)*240]<col) dispic[xc-y+(yc-x)*240]=col;
  }
}

void Shade_poly3(POLY3_2 pnt,int c0,int c1,int c2) {
//ÍÍÍ shade poly with Z-Buffer

  int i,i1,miny,maxy;
  int ys,ye;     // y start,end
  int xl,yl;     // x,y length
  int xp,yp;     // x,y position
  int xadd,yadd; // x,y adders
  int xcnt;      // x position counter
  int cadd,zadd;
  int ccnt,zcnt;
  int a1,a2;
  int ysort[] = new int[3];
  int order;
  int map = 0;
  
  // calc point order in y axis
  ysort[2] = 2;
  if(pnt.y[0]<pnt.y[1]) {
    ysort[0] = 0; ysort[1] = 1;
  } else {
    ysort[0] = 1; ysort[1] = 0;
  }
  if(pnt.y[ysort[1]]>pnt.y[ysort[2]]) {
    i = ysort[2];  // swap ysort[x] and ysort[y]
    ysort[2] = ysort[1];
    ysort[1] = i;
  };
  if(pnt.y[ysort[0]]>pnt.y[ysort[1]]) {
    i = ysort[0];   // swap ysort[x] and ysort[y]
    ysort[0] = ysort[1];
    ysort[1] = i;
  };

  // y start,end setzen
  ys = pnt.y[ysort[0]];
  ye = pnt.y[ysort[2]];

  // winkel berechnen:  a1 zu y-achse, a2 zu y-achse
  a1 = ((pnt.x[ysort[1]]-pnt.x[ysort[0]]) << 16)/((pnt.y[ysort[1]]-pnt.y[ysort[0]])+1);
  a2 = ((pnt.x[ysort[2]]-pnt.x[ysort[0]]) << 16)/((pnt.y[ysort[2]]-pnt.y[ysort[0]])+1);

  // Sortierfolge abbilden
  order = ysort[0] * 3 + ysort[2];

  // map bilden, bit 0 -> start punkte 1 -> end punkte
  switch(order) {
    // p0,p2,p1: a2<=a1 -> 110
    case 1: map = 6; break;
    // p0,p1,p2: a2<=a1 -> 011
    case 2: map = 3; break;
    // p1,p2,p0: a2<=a1 -> 110
    case 3: map = 6; break;
    // p1,p0,p2: a2<=a1 -> 101
    case 5: map = 5; break;
    // p2,p1,p0: a2<=a1 -> 011
    case 6: map = 3; break;
    // p2,p0,p1: a2<=a1 -> 101
    case 7: map = 5; break;
  }
  if(a2>a1) map ^= 0xff;  // angle a2>a1 -> turn map

  //ÄÄÄ  run from x0,y0 to x1,y1
  xl = pnt.x[1] - pnt.x[0];
  yl = Math.abs(pnt.y[1] - pnt.y[0]);
  if((map & 0x01) == 0) {
  // poly_hullxs; else poly_hull = poly_hullxe;
    yp = pnt.y[0];
    poly_hullxs[yp].x = pnt.x[0];
    ccnt = (c0 << 8);
    poly_hullxs[yp].mapx = ccnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[1]>pnt.y[0]) yadd = 1; else yadd = -1;
      xcnt = pnt.x[0] << 8;
      cadd = ((c1 - c0) << 8) / yl;
      while(yp != pnt.y[1]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxs[yp].x = xcnt / 256;
        ccnt += cadd;
        poly_hullxs[yp].mapx = ccnt;
      }
    }
  } else {
    yp = pnt.y[0];
    poly_hullxe[yp].x = pnt.x[0];
    ccnt = (c0 << 8);
    poly_hullxe[yp].mapx = ccnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[1]>pnt.y[0]) yadd = 1; else yadd = -1;
      xcnt = pnt.x[0] << 8;
      cadd = ((c1 - c0) << 8) / yl;
      while(yp != pnt.y[1]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxe[yp].x = xcnt / 256;
        ccnt += cadd;
        poly_hullxe[yp].mapx = ccnt;
      }
    }
  }
  //ÄÄÄ  run from x1,y1 to x2,y2
  xl = pnt.x[2] - pnt.x[1];
  yl = Math.abs(pnt.y[2] - pnt.y[1]);
  if((map & 0x02) == 0) {
    //poly_hull = poly_hullxs; else poly_hull = poly_hullxe;
    yp = pnt.y[1];
    poly_hullxs[yp].x = pnt.x[1];
    ccnt = (c1 << 8);
    poly_hullxs[yp].mapx = ccnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[2]>pnt.y[1]) yadd = 1; else yadd = -1; // y direction
      xcnt = pnt.x[1] << 8;
      cadd = ((c2 - c1) << 8) / yl;
      while(yp != pnt.y[2]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxs[yp].x = xcnt / 256;
        ccnt += cadd;
        poly_hullxs[yp].mapx = ccnt;
      }
    }
  } else {
    yp = pnt.y[1];
    poly_hullxe[yp].x = pnt.x[1];
    ccnt = (c1 << 8);
    poly_hullxe[yp].mapx = ccnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[2]>pnt.y[1]) yadd = 1; else yadd = -1; // y direction
      xcnt = pnt.x[1] << 8;
      cadd = ((c2 - c1) << 8) / yl;
      while(yp != pnt.y[2]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxe[yp].x = xcnt / 256;
        ccnt += cadd;
        poly_hullxe[yp].mapx = ccnt;
      }
    }
  }
  //ÄÄÄ  run from x2,y2 to x0,y0
  xl = pnt.x[0] - pnt.x[2];
  yl = Math.abs(pnt.y[0] - pnt.y[2]);
  if((map & 0x04) == 0) {
    //poly_hull = poly_hullxs; else poly_hull = poly_hullxe;
    yp = pnt.y[2];
    poly_hullxs[yp].x = pnt.x[2];
    ccnt = (c2 << 8);
    poly_hullxs[yp].mapx = ccnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[0]>pnt.y[2]) yadd = 1; else yadd = -1;
      xcnt = pnt.x[2] << 8;
      cadd = ((c0 - c2) << 8) / yl;
      while(yp != pnt.y[0]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxs[yp].x = xcnt / 256;
        ccnt += cadd;
        poly_hullxs[yp].mapx = ccnt;
      }
    }
   } else {
    yp = pnt.y[2];
    poly_hullxe[yp].x = pnt.x[2];
    ccnt = (c2 << 8);
    poly_hullxe[yp].mapx = ccnt;
    if(yl>0) {
      xadd = (xl << 8) / yl;
      if(pnt.y[0]>pnt.y[2]) yadd = 1; else yadd = -1;
      xcnt = pnt.x[2] << 8;
      cadd = ((c0 - c2) << 8) / yl;
      while(yp != pnt.y[0]) {
        yp += yadd;
        xcnt += xadd;
        poly_hullxe[yp].x = xcnt / 256;
        ccnt += cadd;
        poly_hullxe[yp].mapx = ccnt;
      }
    }
  }
  // draw
  for(i=ys; i<=ye; i++) {
    int ypos=i*picxsize;
    ccnt = (poly_hullxs[i].mapx + 127) << 8;
    xl = poly_hullxe[i].x - poly_hullxs[i].x;
    if(xl>0) {
      cadd = ((poly_hullxe[i].mapx - poly_hullxs[i].mapx) << 8)/ xl;
    } else {cadd = 0; zadd=0; }
    for(i1=poly_hullxs[i].x; i1<=poly_hullxe[i].x; i1++) {
      if (i1>0&&i1<picxsize&&i>0&&i<picysize)
        red[i1+ypos]=(ccnt >> 16);
      ccnt += cadd;
    }
  }
}

void sort(int l,int r)
{int i,j,x,y,tst,z;
  i=l; j=r; tst=((l+r) >> 1);
  x=indx[tst].z;
  while (i<j) {
    while (indx[i].z<x) i++;
    while (x<indx[j].z) j--;
	if (i<=j) {
      y=indx[i].z; indx[i].z=indx[j].z; indx[j].z=y;
      y=indx[i].nr; indx[i].nr=indx[j].nr; indx[j].nr=y;
      i++; j--;
     }
  }
  if (l<j) sort(l,j);
  if (i<r) sort(i,r);
}

void quicksort(int lo, int hi)
{
  sort(lo,hi);
}

void Shade_tria3d(face Face, int clr)
{  int Xp[] = new int[3],Yp[] = new int[3];
   POLY3_2 p1 = new POLY3_2();
   int tst=((camerax-px[Face.p])*100); int tst1=pz[Face.p]-100;
   int tst2=((cameray-py[Face.p])*100);
   int tst3=((camerax-px[Face.p1])*100); int tst4=pz[Face.p1]-100;
   int tst5=((cameray-py[Face.p1])*100);
   int tst6=((camerax-px[Face.p2])*100); int tst7=pz[Face.p2]-100;
   int tst8=((cameray-py[Face.p2])*100);
   Xp[0] = 100+(int)tst/tst1;
   Yp[0] = 84+(int)tst2/tst1;
   Xp[1] = 100+(int)tst3/tst4;
   Yp[1] = 84+(int)tst5/tst4;
   Xp[2] = 100+(int)tst6/tst7;
   Yp[2] = 84+(int)tst8/tst7;
   p1.x[0]=Xp[0];
   p1.y[0]=Yp[0];
   p1.x[1]=Xp[1];
   p1.y[1]=Yp[1];
   p1.x[2]=Xp[2];
   p1.y[2]=Yp[2];
   Shade_poly3(p1,Face.clr,Face.clr1,Face.clr2);
}

void Texture_tria3d(face Face)
{  int Xp[] = new int[3],Yp[] = new int[3];
   POLY3_2 p1 = new POLY3_2();
   int tst=((camerax-px[Face.p])*100); int tst1=pz[Face.p]-100;
   int tst2=((cameray-py[Face.p])*100);
   int tst3=((camerax-px[Face.p1])*100); int tst4=pz[Face.p1]-100;
   int tst5=((cameray-py[Face.p1])*100);
   int tst6=((camerax-px[Face.p2])*100); int tst7=pz[Face.p2]-100;
   int tst8=((cameray-py[Face.p2])*100);
   Xp[0] = 100+(int)tst/tst1;
   Yp[0] = 84+(int)tst2/tst1;
   Xp[1] = 100+(int)tst3/tst4;
   Yp[1] = 84+(int)tst5/tst4;
   Xp[2] = 100+(int)tst6/tst7;
   Yp[2] = 84+(int)tst8/tst7;
   p1.x[0]=Xp[0];
   p1.y[0]=Yp[0];
   p1.x[1]=Xp[1];
   p1.y[1]=Yp[1];
   p1.x[2]=Xp[2];
   p1.y[2]=Yp[2];
   Texture_poly3(p1,Face.nx,Face.ny,Face.nx1,Face.ny1,Face.nx2,Face.ny2);
}

public void X_line(int x1,int y1,int x2, int y2,int clr)
{int x,y,dx,dy,ince,incne,d,cx,cy,fsh;
 dx=x2-x1;
 dy=y2-y1;
 if (dx<0) dx=dx*-1; if (dy<=0) dy=dy*-1;
 if (dx>dy) d=dy*2-dx; else d=dx*2-dy;
 if (dx>dy) ince=dy*2; else ince=dx*2;
 x=x1; y=y1;
 incne=(dy-dx)*2;
 if (dx>=dy) {
    if (x1<x2) while (x<x2) {
      if (d<=0) {d=d+ince; x++; } else {d=d+incne; x++; if (y1<y2) y++; else y--;}
        if (x>=0&&x<picxsize&&y>=0&&y<picysize) dispic[x+y*picxsize]+=clr;
       }
    if (x1>x2) while (x>x2) {
     if (d<=0) {d=d+ince; x--; } else {d=d+incne; x--; if (y1<y2) y++; else y--;}
        if (x>=0&&x<picxsize&&y>=0&&y<picysize) dispic[x+y*picxsize]+=clr;
    }
 }
 if (dy>dx) {
    if (y<y2) while (y<y2) {
      if (d<=0) {d=d+ince; y++;} else {d=d-incne; y++; if(x1>x2) x--; else x++;}
        if (x>=0&&x<picxsize&&y>=0&&y<picysize) dispic[x+y*picxsize]+=clr;
     }
     if (y>y2) while (y>y2) {
      if (d<=0) {d=d+ince; y--;} else {d=d-incne; y--; if(x1>x2) x--; else x++;}
        if (x>=0&&x<picxsize&&y>=0&&y<picysize) dispic[x+y*picxsize]+=clr;
     }
  }
}

public void line(int x1,int y1,int x2, int y2,int clr)
{int x,y,dx,dy,ince,incne,d,cx,cy,fsh;
 dx=x2-x1;
 dy=y2-y1;
 if (dx<0) dx=dx*-1; if (dy<=0) dy=dy*-1;
 if (dx>dy) d=dy*2-dx; else d=dx*2-dy;
 if (dx>dy) ince=dy*2; else ince=dx*2;
 x=x1; y=y1;
 incne=(dy-dx)*2;
 if (dx>=dy) {
    if (x1<x2) while (x<x2) {
      if (d<=0) {d=d+ince; x++; } else {d=d+incne; x++; if (y1<y2) y++; else y--;}
        if (x>=0&&x<picxsize&&y>=0&&y<picysize) { red[x+y*picxsize]=clr; }
       }
    if (x1>x2) while (x>x2) {
     if (d<=0) {d=d+ince; x--; } else {d=d+incne; x--; if (y1<y2) y++; else y--;}
       if (x>=0&&x<picxsize&&y>=0&&y<picysize) { red[x+y*picxsize]=clr; }
    }
 }
 if (dy>dx) {
    if (y<y2) while (y<y2) {
      if (d<=0) {d=d+ince; y++;} else {d=d-incne; y++; if(x1>x2) x--; else x++;}
        if (x>=0&&x<picxsize&&y>=0&&y<picysize) { red[x+y*picxsize]=clr; }
     }
     if (y>y2) while (y>y2) {
      if (d<=0) {d=d+ince; y--;} else {d=d-incne; y--; if(x1>x2) x--; else x++;}
        if (x>=0&&x<picxsize&&y>=0&&y<picysize) { red[x+y*picxsize]=clr; }
     }
  }
}

public void LensCircle (int xc,int yc,int r,int col)
{int x,y,p;
  x=0; y=r;
  if (xc+x>0&&xc+x<200&&yc+y>0&&yc+y<167) red[xc+x+(yc+y)*200]=col;
  if (xc-x>0&&xc-x<200&&yc+y>0&&yc+y<167) red[xc-x+(yc+y)*200]=col;
  if (xc+x>0&&xc+x<200&&yc-y>0&&yc-y<167) red[xc+x+(yc-y)*200]=col;
  if (xc-x>0&&xc-x<200&&yc-y>0&&yc-y<167) red[xc-x+(yc-y)*200]=col;
  if (xc+y>0&&xc+y<200&&yc+x>0&&yc+x<167) red[xc+y+(yc+x)*200]=col;
  if (xc-y>0&&xc-y<200&&yc+x>0&&yc+x<167) red[xc-y+(yc+x)*200]=col;
  if (xc+y>0&&xc+y<200&&yc-x>0&&yc-x<167) red[xc+y+(yc-x)*200]=col;
  if (xc-y>0&&xc-y<200&&yc-x>0&&yc-x<167) red[xc-y+(yc-x)*200]=col;
  p=1-r;
  while (x<y) {
    if (p<0) x=x+1; else {x=x+1; y=y-1;}
    if (p<0) p=p+2*x+1; else p=p+2*(x-y)+1;
    if (xc+x>0&&xc+x<200&&yc+y>0&&yc+y<167) red[xc+x+(yc+y)*200]=col;
    if (xc-x>0&&xc-x<200&&yc+y>0&&yc+y<167) red[xc-x+(yc+y)*200]=col;
    if (xc+x>0&&xc+x<200&&yc-y>0&&yc-y<167) red[xc+x+(yc-y)*200]=col;
    if (xc-x>0&&xc-x<200&&yc-y>0&&yc-y<167) red[xc-x+(yc-y)*200]=col;
    if (xc+y>0&&xc+y<200&&yc+x>0&&yc+x<167) red[xc+y+(yc+x)*200]=col;
    if (xc-y>0&&xc-y<200&&yc+x>0&&yc+x<167) red[xc-y+(yc+x)*200]=col;
    if (xc+y>0&&xc+y<200&&yc-x>0&&yc-x<167) red[xc+y+(yc-x)*200]=col;
    if (xc-y>0&&xc-y<200&&yc-x>0&&yc-x<167) red[xc-y+(yc-x)*200]=col;
  }
}

void Line3d (int x1, int y1, int z1, int x2, int y2, int z2)
{ int Xp[] = new int[2],Yp[] = new int[2];
  int tst,tst1,tst2,tst3,tst4,tst5;
   tst=((camerax-x1)*100); tst1=z1-100;
   tst2=((cameray-y1)*100);
   tst3=((camerax-x2)*100); tst4=z2-100;
   tst5=((cameray-y2)*100);
   if (z1<100&&z2<100) {
     Xp[0] = 100+(int)tst/tst1;
     Yp[0] = 83+(int)tst2/tst1;
     Xp[1] = 100+(int)tst3/tst4;
     Yp[1] = 83+(int)tst5/tst4;
     line(Xp[0],Yp[0],Xp[1],Yp[1],192);
   }
}

void Lens3d(int x, int y, int z ,int clr) {
   int tst=((camerax-x)*100); int tst1=z-100;
   int tst2=((cameray-y)*100);
   int xp = 100+(int)tst/tst1;
   int yp = 83+(int)tst2/tst1;
   int r = 4+(z >> 3);
   for (int i=0; i<r; i++) {
     int color=clr-(i << 3);
     LensCircle(xp,yp,i,Math.abs(color));
     LensCircle(xp+1,yp,i,Math.abs(color));
   }
}


  void Set3dPixel2 (int x1, int y1, int z1,int clr) {
    int Xp[] = new int[1],Yp[] = new int[1];
    int tst,tst1,tst2;
    if (z1<cameraz) {
      tst=((camerax-x1)*cameraz); tst1=z1-cameraz;
      tst2=((cameray-y1)*cameraz);
      Xp[0] = 100+(int)tst/tst1;
      Yp[0] = 84+(int)tst2/tst1;
      for (int i=0; i<3; i++) { LensCircle(Xp[0],Yp[0],i,clr-(i << 4)); LensCircle(Xp[0]+1,Yp[0],i,clr-(i << 4)); }
    }
 }

void Tria3d(face Face, int clr)
{  int Xp[] = new int[3],Yp[] = new int[3];
   int tst=((camerax-px[Face.p])*100); int tst1=pz[Face.p]-100;
   int tst2=((cameray-py[Face.p])*100);
   int tst3=((camerax-px[Face.p1])*100); int tst4=pz[Face.p1]-100;
   int tst5=((cameray-py[Face.p1])*100);
   int tst6=((camerax-px[Face.p2])*100); int tst7=pz[Face.p2]-100;
   int tst8=((cameray-py[Face.p2])*100);
   Xp[0] = 100+(int)tst/tst1;
   Yp[0] = 83+(int)tst2/tst1;
   Xp[1] = 100+(int)tst3/tst4;
   Yp[1] = 83+(int)tst5/tst4;
   Xp[2] = 100+(int)tst6/tst7;
   Yp[2] = 83+(int)tst8/tst7;
   line(Xp[0],Yp[0],Xp[1],Yp[1],clr);
   line(Xp[1],Yp[1],Xp[2],Yp[2],clr);
   line(Xp[2],Yp[2],Xp[0],Yp[0],clr);
}

public void ClearCircle (int xc,int yc,int r,int col)
{int x,y,p;
  x=0; y=r;
  if (xc+x>0&&xc+x<240&&yc+y>0&&yc+y<200) green[xc+x+(yc+y)*240]+=col;
  if (xc-x>0&&xc-x<240&&yc+y>0&&yc+y<200) green[xc-x+(yc+y)*240]+=col;
  if (xc+x>0&&xc+x<240&&yc-y>0&&yc-y<200) green[xc+x+(yc-y)*240]+=col;
  if (xc-x>0&&xc-x<240&&yc-y>0&&yc-y<200) green[xc-x+(yc-y)*240]+=col;
  if (xc+y>0&&xc+y<240&&yc+x>0&&yc+x<200) green[xc+y+(yc+x)*240]+=col;
  if (xc-y>0&&xc-y<240&&yc+x>0&&yc+x<200) green[xc-y+(yc+x)*240]+=col;
  if (xc+y>0&&xc+y<240&&yc-x>0&&yc-x<200) green[xc+y+(yc-x)*240]+=col;
  if (xc-y>0&&xc-y<240&&yc-x>0&&yc-x<200) green[xc-y+(yc-x)*240]+=col;
  p=1-r;
  while (x<y) {
    if (p<0) x=x+1; else {x=x+1; y=y-1;}
    if (p<0) p=p+2*x+1; else p=p+2*(x-y)+1;
    if (xc+x>0&&xc+x<240&&yc+y>0&&yc+y<200) green[xc+x+(yc+y)*240]+=col;
    if (xc-x>0&&xc-x<240&&yc+y>0&&yc+y<200) green[xc-x+(yc+y)*240]+=col;
    if (xc+x>0&&xc+x<240&&yc-y>0&&yc-y<200) green[xc+x+(yc-y)*240]+=col;
    if (xc-x>0&&xc-x<240&&yc-y>0&&yc-y<200) green[xc-x+(yc-y)*240]+=col;
    if (xc+y>0&&xc+y<240&&yc+x>0&&yc+x<200) green[xc+y+(yc+x)*240]+=col;
    if (xc-y>0&&xc-y<240&&yc+x>0&&yc+x<200) green[xc-y+(yc+x)*240]+=col;
    if (xc+y>0&&xc+y<240&&yc-x>0&&yc-x<200) green[xc+y+(yc-x)*240]+=col;
    if (xc-y>0&&xc-y<240&&yc-x>0&&yc-x<200) green[xc-y+(yc-x)*240]+=col;
  }
}

  public void init() {
    for (i=0; i<256; i++) SinTab[i]=(int)(Math.sin(2*i*Math.PI/255)*128);
    for (i=0; i<256; i++) CosTab[i]=(int)(Math.cos(2*i*Math.PI/255)*128);
    music = getAudioClip(getCodeBase(),"data/music.au");
    setBackground(c);
    int fps = 30;
    int index = 0;
    offGraphics= null;
    delay = (fps >0) ? (1000 / fps) : 100;
    s=getParameter("Variante");
    int clouds[] = new int[256*256];
    clouds=CalcMarble(4,6);
    for (int y=0; y<128; y++)
       for (int x=0; x<128; x++) cloud[x+(y << 7)]=clouds[(x << 1)+((y << 1) << 8)];
    clouds=CalcMarble(4,8);
    for (int y=0; y<128; y++)
       for (int x=0; x<128; x++) cloud1[x+(y << 7)]=clouds[(x << 1)+((y << 1) << 8)];
    getAppletContext().showStatus("Applet from OtakInc loaded pure REALTIME!");
    Img = getImage(getCodeBase(),"data/logo.gif");
    grab = new PixelGrabber(Img,0,0,240,200,pix1,0,240);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
    for (int i1=0; i1<200; i1++)
      for (int i=0; i<240; i++) {
        red[i+i1*240]=(int)((pix1[i+i1*240] >> 16) & 0xff);
        green[i+i1*240]=(int)((pix1[i+i1*240] >> 8) & 0xff);
        blue[i+i1*240]=(int)(pix1[i+i1*240] & 0xff);
        difx[i+i1*240]=(int)(red[i+i1*240]+green[i+i1*240]+blue[i+i1*240])/3;
        dispic[i+i1*240]=0;
    }
    for (i=0; i<360; i++) { Stab[i]=Math.sin(Math.PI*i/180); Ctab[i]=Math.cos(Math.PI*i/180); }
    for (i=0; i<5; i++) scnt[i]=(int)(Math.random()*360);
    for (i=0; i<3000; i++) noise[i]=(int)(Math.random()*16);
    source = new MemoryImageSource(240,200,pix,0,240);
    Img = createImage(source);
    for (int i=0; i<520; i++)  facelist[i] = new face();
    for (int i=0; i<3000; i++) {
      poly_hullxs[i] = new PL();
      poly_hullxe[i] = new PL();
    }
    for (int i=0; i<520; i++) indx[i] = new idx();
    boolean CORDS = true;
    cnt=cnt1=0;
    try {
      URL url = new URL(getCodeBase(), "data/scene1.3D");
      DataInputStream in = new DataInputStream((InputStream) url.getContent());
      try {
          String X="a";
          while (X!=null) {
            X = in.readLine();
            if (X==null||X.regionMatches(false,0,"FACES",0,4))
             { CORDS=false;
                if (X!=null) X = in.readLine();
             }
            if (X!=null&&CORDS==false&&X.compareTo("VERTEX")==0) {
               CORDS=true;
               X = in.readLine();
            }
            if (CORDS==true) {
              String Y = in.readLine();
              String Z = in.readLine();
              Float cx = Float.valueOf(X);
              Float cy = Float.valueOf(Y);
              Float cz = Float.valueOf(Z);
              double x = cx.doubleValue();
              double y = cy.doubleValue();
              double z = cz.doubleValue();
              pointx[cnt]=(int)(x*25);
              pointy[cnt]=(int)(y*25);
              pointz[cnt]=(int)(z*25);
              pointz2[cnt]=pointz[cnt];
              cnt++;
            }
            if (CORDS==false&&X!=null) {
              String p1 = in.readLine();
              String p2 = in.readLine();
              Float cp = Float.valueOf(X);
              int fp = (int)cp.doubleValue();
              cp = Float.valueOf(p1);
              int fp1 = (int)cp.doubleValue();
              cp = Float.valueOf(p2);
              int fp2 = (int)cp.doubleValue();
              facelist[cnt1].p=fp;
              facelist[cnt1].p1=fp1;
              facelist[cnt1].p2=fp2;
              facelist[cnt1].nr=cnt1;
              cnt1++;
            }
          }
      } catch (EOFException e) {}
      in.close();
    } catch (IOException e) { getAppletContext().showStatus("FILE-ERROR"); }
    for (int i=cnt; i<cnt+10; i++) {
      pointx[i]=30;
      pointy[i]=30;
      pointz[i]=20;
      scnt[i-cnt]=i*36;
    }
    maxverts=cnt;
    maxface=cnt1;
    cnt=cnt1=0;
    Font myFont=new Font("TimesRoman", Font.BOLD, 24);
    FontMetrics myMetrix=getFontMetrics(myFont);
    setFont(myFont);
    sxpos[0]=80; sypos[0]=0;
    sxpos[1]=60; sypos[1]=0;
    partnr=timer=0;
//    partnr=9;
    music.loop();
  }

  public void start() {
  if (killme== null)
   {
     killme = new Thread(this);
     killme.start();
    }
  }


  public void LoadOp_2() {
    Img = getImage(getCodeBase(),"data/pic1.jpg");
    tracer.addImage(Img,0);
    try {
      tracer.waitForAll();
    } catch (InterruptedException e) {}
    grab = new PixelGrabber(Img,0,0,240,100,pix1,0,240);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
    for (int y=0; y<picysize; y++)
      for (int x=0; x<picxsize; x++) {
        blue[x+y*picxsize]=pix1[x+y*picxsize]&0xff;
        red[x+y*picxsize]=(pix1[x+y*picxsize] >> 16)&0xff;
        green[x+y*picxsize]=(pix1[x+y*picxsize] >> 8)&0xff;
    }
    source = new MemoryImageSource(picxsize,100,pix,0,picxsize);
    Img = createImage(source);
    xadd=(double)picxsize/100;
    xval=8*xadd; yval=0.0f; cnt=0; cnt1=8;
    timer=0; partnr=2;
  }

  public void LoadOp_3() {
    Img = getImage(getCodeBase(),"data/pic2.jpg");
    tracer.addImage(Img,0);
    try {
      tracer.waitForAll();
    } catch (InterruptedException e) {}
    grab = new PixelGrabber(Img,0,0,240,200,pix1,0,240);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
    picysize=200;
    for (int y=0; y<picysize; y++)
      for (int x=0; x<picxsize; x++) {
        blue[x+y*picxsize]=pix1[x+y*picxsize]&0xff;
        red[x+y*picxsize]=(pix1[x+y*picxsize] >> 16)&0xff;
        green[x+y*picxsize]=(pix1[x+y*picxsize] >> 8)&0xff;
        difx[x+y*picxsize]=(int)(blue[x+y*picxsize]+green[x+y*picxsize]+red[x+y*picxsize])/3;
    }
    source = new MemoryImageSource(picxsize,200,pix,0,picxsize);
    Img = createImage(source);
    cnt1=255; partnr=4; timer=0; cnt2=0;
  }


  public void Load_Op4() {
    Img = getImage(getCodeBase(),"data/pic4.jpg");
    grab = new PixelGrabber(Img,0,0,240,200,pix1,0,240);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
    for (int i1=0; i1<200; i1++)
      for (int i=0; i<125; i++) {
        red[i+i1*125]=pix1[i+50+i1*240];
    }
    Img = getImage(getCodeBase(),"data/pic5.jpg");
    grab = new PixelGrabber(Img,0,0,240,200,pix1,0,240);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
    for (int i1=0; i1<200; i1++)
      for (int i=0; i<125; i++) {
        green[i+i1*125]=pix1[i+50+i1*240];
    }
    Img = getImage(getCodeBase(),"data/pic3.jpg");
    grab = new PixelGrabber(Img,0,0,240,200,pix1,0,240);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
    for (int i1=0; i1<200; i1++)
      for (int i=0; i<125; i++) {
        pix[i+i1*125]=pix1[i+50+i1*240];
    }
    cnt=0;
    source = new MemoryImageSource(125,200,pix,0,125);
    Img1 = createImage(source);
    pos1[0]=false;
    pos1[1]=false;
    pos1[2]=false;
    cnt=cnt1=cnt2=timer=0;
    partnr=6;
  }

  public void Load_Part1() {
    source = new MemoryImageSource(240,200,pix,0,240);
    Img = createImage(source);
    for (y=-100; y<100; y++)
      for (x=-120; x<120; x++) {
         tstval=Math.atan((double)y/(double)x);
          red[(x+120)+(y+100)*240]=0;
          green[(x+120)+(y+100)*240]=0;
          difx[(x+120)+(y+100)*240]=(int)((Math.sin(tstval)+Math.cos(tstval)*32.0f*64.0f)/(double)x);
          dispic[(x+120)+(y+100)*240]=(int)(tstval*180/(360/255)/Math.PI);
      }
    cnt=cnt1=cnt2=timer=0; partnr=8;
    text[0]="Oh no not again!";
    text[1]="Yes thats better";
    sxpos[0]=260;
    pos1[0]=false;
    for (int i=1; i<11; i++) scnt[i]=(i-1)*36;
  }

  public void Load_Part2() {
    source = new MemoryImageSource(200,167,pix,0,200);
    Img = createImage(source);
    cnt=cnt1=cnt2=timer=0; partnr=10;
    picxsize=200;
    picysize=167;
    for (int y=0; y<200; y++) {
      int ypos=y*240;
      for (int x=0 ; x<240; x++) { dispic[x+ypos]=red[x+ypos]=green[x+ypos]=0;
       pix[x+ypos]=(255 << 24);  }
    }
  }

  public void Load_Part4() {
    cnt=cnt1=cnt2=cnter=timer=0; partnr=14;
    picxsize=200;
    picysize=167;
    camerax=-80; cameray=-80; cameraz=100;
    boolean CORDS = true;
    int val=0;
    try {
      URL url = new URL(getCodeBase(), "data/scene2.3D");
      DataInputStream in = new DataInputStream((InputStream) url.getContent());
      try {
          String X="a";
          while (X!=null) {
            X = in.readLine();
            if (X==null||X.regionMatches(false,0,"FACES",0,4))
             { CORDS=false;
                if (X!=null) X = in.readLine();
             }
            if (X!=null&&CORDS==false&&X.compareTo("VERTEX")==0) {
               CORDS=true;
               val=cnt;
               X = in.readLine();
            }
            if (CORDS==true) {
              String Y = in.readLine();
              String Z = in.readLine();
              Float cx = Float.valueOf(X);
              Float cy = Float.valueOf(Y);
              Float cz = Float.valueOf(Z);
              double x = cx.doubleValue();
              double y = cy.doubleValue();
              double z = cz.doubleValue();
              pointx[cnt]=(int)(x*40);
              pointy[cnt]=(int)(y*40);
              pointz[cnt]=(int)(z*40);
              cnt++;
            }
            if (CORDS==false&&X!=null) {
              String p1 = in.readLine();
              String p2 = in.readLine();
              Float cp = Float.valueOf(X);
              int fp = (int)cp.doubleValue();
              cp = Float.valueOf(p1);
              int fp1 = (int)cp.doubleValue();
              cp = Float.valueOf(p2);
              int fp2 = (int)cp.doubleValue();
              facelist[cnt1].p=fp+val;
              facelist[cnt1].p1=fp1+val;
              facelist[cnt1].p2=fp2+val;
              facelist[cnt1].nr=cnt1;
              cnt1++;
            }
          }
      } catch (EOFException e) {}
      in.close();
    } catch (IOException e) { getAppletContext().showStatus("FILE-ERROR"); }
    maxverts=cnt;
    maxface=cnt1;
    cnt=cnt1=0;
    for (int y=0; y<200; y++) {
      int ypos=y*240;
      for (int x=0 ; x<240; x++) { dispic[x+ypos]=red[x+ypos]=green[x+ypos]=0;
       pix[x+ypos]=(255 << 24);  }
    }
  }

  public void Load_Part5_1() {
    cnt=cnt1=cnt2=cnter=timer=0; partnr=16;
    picxsize=200;
    picysize=167;
    camerax=120; cameray=0; cameraz=100;
    tex = new int[256*256];
    Img = getImage(getCodeBase(),"data/texture.jpg");
    grab = new PixelGrabber(Img,0,0,256,256,tex,0,256);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
    for (int y=0; y<256; y++)
      for (int x=0; x<256; x++) tex[x+(y << 8)]=(tex[x+(y << 8)] >> 16)&0xff;
    boolean CORDS = true;
    int val=0;
    try {
      URL url = new URL(getCodeBase(), "data/scene3.3D");
      DataInputStream in = new DataInputStream((InputStream) url.getContent());
      try {
          String X="a";
          while (X!=null) {
            X = in.readLine();
            if (X==null||X.regionMatches(false,0,"FACES",0,4))
             { CORDS=false;
                if (X!=null) X = in.readLine();
             }
            if (X!=null&&CORDS==false&&X.compareTo("VERTEX")==0) {
               CORDS=true;
               val=cnt;
               X = in.readLine();
            }
            if (CORDS==true) {
              String Y = in.readLine();
              String Z = in.readLine();
              Float cx = Float.valueOf(X);
              Float cy = Float.valueOf(Y);
              Float cz = Float.valueOf(Z);
              double x = cx.doubleValue();
              double y = cy.doubleValue();
              double z = cz.doubleValue();
              pointx[cnt]=(int)(x*15);
              pointy[cnt]=(int)(y*15);
              pointz[cnt]=(int)(z*15);
              cnt++;
            }
            if (CORDS==false&&X!=null) {
              String p1 = in.readLine();
              String p2 = in.readLine();
              Float cp = Float.valueOf(X);
              int fp = (int)cp.doubleValue();
              cp = Float.valueOf(p1);
              int fp1 = (int)cp.doubleValue();
              cp = Float.valueOf(p2);
              int fp2 = (int)cp.doubleValue();
              facelist[cnt1].p=fp+val;
              facelist[cnt1].p1=fp1+val;
              facelist[cnt1].p2=fp2+val;
              facelist[cnt1].nr=cnt1;
              cnt1++;
            }
          }
      } catch (EOFException e) {}
      in.close();
    } catch (IOException e) { getAppletContext().showStatus("FILE-ERROR"); }
    maxverts=cnt;
    maxface=cnt1;
    cnt=cnt1=0;
    for (int y=0; y<200; y++) {
      int ypos=y*240;
      for (int x=0 ; x<240; x++) { dispic[x+ypos]=red[x+ypos]=green[x+ypos]=0;
       pix[x+ypos]=(255 << 24);  }
    }
  }

  public void Load_Part6() {
    Img = getImage(getCodeBase(),"data/pic6.jpg");
    tracer.addImage(Img,0);
    try {
      tracer.waitForAll();
    } catch (InterruptedException e) {}
    grab = new PixelGrabber(Img,0,0,240,200,pix1,0,240);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
    for (int i=0; i<25; i++) { sxpos[i]=(int)(Math.random()*240); sypos[i]=(int)(Math.random()*140); }
    for (int i1=0; i1<picysize; i1++)
      for (int i=0; i<picxsize; i++) {
        red[i+i1*picxsize]=0;
        green[i+i1*picxsize]=(int)((pix1[i+i1*picxsize] >> 8) & 0xff);
        blue[i+i1*picxsize]=0;
    }
    for (int i=0; i<20; i++) { pointx[i]=(int)(Math.random()*240); pointy[i]=200+(int)(Math.random()*30);
      pointz[i]=(int)(Math.random()*5); py[i]=3+(int)(Math.random()*3);
     }
    cnt=cnt1=cnt2=cnter=timer=0; partnr=20;
  }

  public void Load_EndPart() {
    Img = getImage(getCodeBase(),"data/pic7.gif");
    tracer.addImage(Img,0);
    try {
      tracer.waitForAll();
    } catch (InterruptedException e) {}
    Shows = new Image[7];
    text = new String[49];
    text[0]="You have";
    text[1]="experienced";
    text[2]="COAL from";
    text[3]="OtakInc";
    text[4]="A JAVA-Demo";
    text[5]="made in 1998";
    text[6]="for the";
    text[7]="TakeOver '98";
    text[8]="Party in";
    text[9]="Eindhoven";
    text[10]="in";
    text[11]="Netherland";
    text[12]="This is";
    text[13]="the first";
    text[14]="Demo or";
    text[15]="Intro, etc";
    text[16]="Which uses";
    text[17]="a realtime";
    text[18]="coaldraw -";
    text[19]="filter";
    text[20]="Coaldraw and";
    text[21]="Coal3D is";
    text[22]="an OtakInc";
    text[23]="development.";
    text[24]="Our goal was";
    text[25]="to demonstrate";
    text[26]="some new code";
    text[27]="not seen";
    text[28]="before!";
    text[29]="We hope you";
    text[30]="enjoyed it";
    text[31]="Thanks for";
    text[32]="watching!";
    text[33]="And thanks";
    text[34]="to the";
    text[35]="organisers";
    text[36]="especially";
    text[37]="Sparcus from";
    text[38]="Nostalgia";
    text[39]="who considered";
    text[40]="a JAVA-Compo";
    text[41]="in the last";
    text[42]="minute.";
    text[43]=" ";
    text[44]="C'YA";
    text[45]=" ";
    text[46]="Furuike ya";
    text[47]="kawazu tobikamu";
    text[48]="mizu no oto";
    for (int i=0; i<50; i++) pointy[i]=300+i*10;
    Shows[0] = getImage(getCodeBase(),"data/end1.jpg");
    Shows[1] = getImage(getCodeBase(),"data/end2.jpg");
    Shows[2] = getImage(getCodeBase(),"data/end3.jpg");
    Shows[3] = getImage(getCodeBase(),"data/end4.jpg");
    Shows[4] = getImage(getCodeBase(),"data/end5.jpg");
    Shows[5] = getImage(getCodeBase(),"data/end6.jpg");
    Shows[6] = getImage(getCodeBase(),"data/end7.jpg");
    for (int i=0; i<7; i++) tracer.addImage(Shows[i],i);
    try {
      tracer.waitForAll();
    } catch (InterruptedException e) {}
    picxsize = Img.getWidth(null);
    picysize = Img.getHeight(null);
    grab = new PixelGrabber(Img,0,0,picxsize,picysize,pix1,0,picxsize);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
    source = new MemoryImageSource(picxsize,picysize,pix,0,picxsize);
    Img = createImage(source);
    for (int y=0; y<picysize; y++)
      for (int x=0; x<picxsize; x++) {
        red[x+y*picxsize]=(int)((pix1[x+y*picxsize] >> 16) & 0xff);
        pix1[x+y*picxsize]=0;
    }
    Img = createImage(source);
    Font myFont=new Font("Arial", Font.BOLD, 10);
    FontMetrics myMetrix=getFontMetrics(myFont);
    offGraphics.setFont(myFont);
    sxpos[0]=picxsize >> 1;
    sypos[0]=picysize >> 1;
    sxpos[1]=30+picxsize >> 1;
    sypos[1]=-15+(picysize >> 1);
    scnt[0]=40;
    scnt[1]=160;
    for (int i=2; i<9; i++) scnt[i]=(i-2)*50;
    cnt=cnt1=cnt2=cnter=timer=0; partnr=22;
    sxpos[2]=0; sypos[2]=6;
    sxpos[3]=240; sypos[3]=188;
  }

  public void Load_Part5() {
    cnt=cnt1=cnt2=cnter=timer=0; partnr=18;
    picxsize=240;
    picysize=200;
    cnt=cnt1=0;
    int val=0;
    Img = getImage(getCodeBase(),"data/greetz.gif");
    tracer.addImage(Img,0);
    try {
      tracer.waitForAll();
    } catch (InterruptedException e) {}
    grab = new PixelGrabber(Img,0,0,64,64,pix1,0,64);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
     for (int y=0; y<64; y++) {
       int ypos=(y << 6);
       for (int x=0; x<64; x++) pix1[x+ypos]=(pix1[x+ypos] >> 16)&0xff;
     }
     Img = getImage(getCodeBase(),"data/greetz2.gif");
    tracer.addImage(Img,0);
    try {
      tracer.waitForAll();
    } catch (InterruptedException e) {}
    grab = new PixelGrabber(Img,0,0,240,200,difx,0,240);
    try {
      grab.grabPixels();
     } catch (InterruptedException e) {};
     for (int y=0; y<200; y++) {
       int ypos=y*240;
       for (int x=0; x<240; x++) difx[x+ypos]=(difx[x+ypos] >> 16)&0xff;
     }
    cnt=cnt1=0;
/*    text = new String[9];
    text[0]="   RAM-JAM";
    text[1]="  D-LUSION";
    text[2]="DIGITAL NERDS";
    text[3]="   COMPLEX";
    text[4]="    CREST";
    text[5]="H-TOWN PLAYERZ";
    text[6]="  NOSTALGIA";
    text[7]="    STACK";
    text[8]="    QUAD";*/
    Font myFont=new Font("Arial", Font.BOLD, 24);
    FontMetrics myMetrix=getFontMetrics(myFont);
    offGraphics.setFont(myFont);
    pos=false;
    for (int y=0; y<200; y++) {
      int ypos=y*240;
      for (int x=0 ; x<240; x++) { red[x+ypos]=green[x+ypos]=0;
       pix[x+ypos]=(255 << 24);  }
    }
    cnt3=0; timer=1;
    Img.flush();
    source = new MemoryImageSource(240,200,pix,0,240);
    Img = createImage(source);
  }



  public void Load_Part3() {
    cnt=cnt1=cnt2=cnter=timer=0; partnr=12;
    picxsize=200;
    picysize=167;
    camerax=0; cameray=0; cameraz=100;
    for (int y=0; y<200; y++) {
      int ypos=y*240;
      for (int x=0 ; x<240; x++) { dispic[x+ypos]=red[x+ypos]=green[x+ypos]=0;
       pix[x+ypos]=(255 << 24);  }
    }
    for (int i=0; i<125; i++) scnt[i]=(int)(Math.random()*100);
    for (int i2=0; i2<5; i2++)
      for (int i1=0; i1<5; i1++)
        for (int i=0; i<5; i++) { pointx[i+i1*5+i2*25]=-10+i*5; pointy[i+i1*5+i2*25]=-10+i1*5; pointz[i+i1*5+i2*25]=-10+i2*5; }
  }

  public void paint(Graphics g) {
    update(g);
  }

  public void Pic_1() {
     offGraphics.setColor(Color.black);
     if (pos1[0]==false) offGraphics.drawImage(Img,0,0,this);
     if (pos1[0]==true) {
       offGraphics.drawImage(Img1,sx,0,80,200,this);
       if (pos1[1]==false) sx-=8;
       if (sx<0) { sx=0; pos1[1]=true; }
       offGraphics.drawImage(Img1,scrx,0,scrx1,200,20,30,100,130,this);
       offGraphics.drawImage(Img1,scrx2,0,scrx3,200,55,60,85,90,this);
       if (pos1[1]==true) {
         offGraphics.drawString("Code",10,65);
         offGraphics.drawString("  & ",10,95);
         offGraphics.drawString("Ideas",10,125);
         if (scrx>80) { scrx-=4; scrx1+=4; }
         if (scrx<80) scrx=125;
       }
       if (scrx<90) pos1[2]=true;
       if (pos1[2]==true) {
         offGraphics.drawString("By",100,95);
         if (scrx2>160) { scrx2-=4; scrx3+=4; }
         if (scrx2<=160) offGraphics.drawString("Chojin",160,95);
       }
     }
     timer++;
     if (timer>10) pos1[0]=true;
     if (timer>60) {
       source = new MemoryImageSource(125,200,red,0,125);
       Img1 = createImage(source);
       Img = getImage(getCodeBase(),"data/pic4.jpg");
       tracer.addImage(Img,0);
       try {
         tracer.waitForAll();
       } catch (InterruptedException e) {}
       cnt=1;
       scrx=120; scrx1=120; scrx2=200; scrx3=200; sx=60; timer=0;
       pos1[0]=false;
       pos1[1]=false;
       pos1[2]=false;
     }
   }

   public void Pic_2() {
     offGraphics.setColor(Color.black);
     if (pos1[0]==false) offGraphics.drawImage(Img,0,0,this);
     if (pos1[0]==true) {
       offGraphics.drawImage(Img1,sx,0,80,200,this);
       if (pos1[1]==false) sx-=8;
       if (sx<0) { sx=0; pos1[1]=true; }
       offGraphics.drawImage(Img1,scrx,0,scrx1,200,20,30,100,130,this);
       offGraphics.drawImage(Img1,scrx2,0,scrx3,200,35,65,85,105,this);
       if (pos1[1]==true) {
         offGraphics.drawString("Music",10,95);
         if (scrx>80) { scrx-=4; scrx1+=4; }
         if (scrx<80) scrx=125;
       }
       if (scrx<90) pos1[2]=true;
       if (pos1[2]==true) {
         offGraphics.drawString("From",100,95);
         if (scrx2>160) { scrx2-=4; scrx3+=4; }
        if (scrx2<=160) { offGraphics.drawString("Slayers",160,75);
                          offGraphics.drawString("  &    ",160,95);
                          offGraphics.drawString("Chojin",160,115);
                         }
       }
     }
     timer++;
     if (timer>10) pos1[0]=true;
     if (timer>60) {
       source = new MemoryImageSource(125,200,green,0,125);
       Img1 = createImage(source);
       Img = getImage(getCodeBase(),"data/pic5.jpg");
       tracer.addImage(Img,0);
       try {
         tracer.waitForAll();
       } catch (InterruptedException e) {}
       cnt=2;
       scrx=120; scrx1=120; scrx2=200; scrx3=200; sx=60; timer=0;
       pos1[0]=false;
       pos1[1]=false;
       pos1[2]=false;
     }
   }

 public void Pic_3() {
     offGraphics.setColor(Color.white);
     if (pos1[0]==false) offGraphics.drawImage(Img,0,0,this);
     if (pos1[0]==true) {
       offGraphics.drawImage(Img1,sx,0,80,200,this);
       if (pos1[1]==false) sx-=8;
       if (sx<0) { sx=0; pos1[1]=true; }
       offGraphics.drawImage(Img1,scrx,0,scrx1,200,12,56,65,125,this);
       offGraphics.drawImage(Img1,scrx2,0,scrx3,200,17,108,57,153,this);
       if (pos1[1]==true) {
         offGraphics.drawString("Guest",10,65);
         offGraphics.drawString("Stars",10,95);
         if (scrx>80) { scrx-=4; scrx1+=4; }
         if (scrx<80) scrx=125;
       }
       if (scrx<90) pos1[2]=true;
       if (pos1[2]==true) {
         if (scrx2>160) { scrx2-=4; scrx3+=4; }
         if (scrx2<=160) { offGraphics.drawString("The",155,65);
                           offGraphics.drawString("Slayers",155,95);
                           offGraphics.drawString("Crew",155,125);
                         }
       }
     }
    timer++;
    if (timer>10) pos1[0]=true;
    if (timer>60) partnr=7;
   }

 public void Opening_1() {
    int distort;
    int dred=0,dblue=0,dgreen=0;
    for (int i=0; i<2; i++) {
      sxpos[i]=(int)(Math.random()*240);
      sypos[i]=0;
    }
    for (int i1=0; i1<2; i1++) {
      while (sxpos[i1]<239&&sxpos[i1]>1&&sypos[i1]<199&&difx[sxpos[i1]+sypos[i1]*240]<48) {
         dispic[sxpos[i1]+sypos[i1]*240]=128;
         difx[sxpos[i1]+sypos[i1]*240]+=2;
         int value=difx[(sxpos[i1]-1)+(sypos[i1]+1)*240];
         int min=value;
         int value1=difx[sxpos[i1]+(sypos[i1]+1)*240];
         int value2=difx[sxpos[i1]+1+(sypos[i1]+1)*240];
         int value3=difx[sxpos[i1]+1+sypos[i1]*240];
         int value4=difx[sxpos[i1]-1+sypos[i1]*240];
         if (value1<min) min=value1; else value1=min+1;
         if (value2<min) min=value2; else value2=min+1;
         if (value3<min) min=value3; else value3=min+1;
         if (value4<min) min=value4; else value4=min+1;
         if (min==value) sypos[i1]++;
         if (min==value1) { sxpos[i1]--; sypos[i1]++; }
         if (min==value2) { sxpos[i1]++; sypos[i1]++; }
         if (min==value3) sxpos[i1]++;
         if (min==value4) sxpos[i1]--;
       }
       if (difx[sxpos[i1]+sypos[i1]*240]>20) {
          for (int r=0; r<30; r++) { Circle(sxpos[i1],sypos[i1],r,128-(r << 2));
                                    Circle(sxpos[i1]+1,sypos[i1],r,128-(r << 2));
                                  }
       }
     }
     for (int y=0; y < 200; y++) {
        int ypos=y*240;
        for (int x = 0; x < 240; x++) {
          dblue=((3*blue[x+ypos]) >> 3) + (dispic[x+ypos] << 1);
          dgreen=((3*green[x+ypos]) >> 3)+(dispic[x+ypos] << 1);
          dred=((3*red[x+ypos]) >> 3)-(dispic[x+ypos] << 1);
          if (dgreen>255) dgreen=255;
          if (dred<0) dred=0;
          if (dblue>255) dblue=255;
          pix[x+ypos]=(255 << 24)+(dred << 16)+(dgreen << 8)+dblue;
          if (red[x+ypos]>16) difx[x+ypos]=red[x+ypos]; else difx[x+ypos]=noise[(cnt++)%3000];
          dispic[x+ypos]=0;
       }
     }
     timer++;
     if (timer>75) partnr=1;
  }

 public void Opening_2() {
    int distort;
    double y1=(double)cnt1;
    double xadd=(double)(picxsize-(cnt << 1))/picxsize;
    double yadd=(double)(picysize-(cnt1 << 1))/picysize;
    for (int y=0; y < picysize; y++) {
      double x1=(double)cnt;
      y1+=yadd;
      int ypos=y*picxsize;
      for (int x=0; x < picxsize; x++) {
	x1+=xadd;
	int x2=(int)x1;
	int y2=(int)y1;
        if (x2>0&&x2<picxsize&&y2>0&&y2<picysize) {
          int ypos2=y2*picxsize;
          int xadder=(x2-x) >> 1;
          int yadder=(y2-y) >> 1;
          int xadder1=3*(x2-x) >> 2;
          int yadder1=3*(y2-y) >> 2;
          int xadder2=(x2-x) >> 2;
          int yadder2=(y2-y) >> 2;
          int xadder3=3*(x2-x) >> 3;
          int yadder3=3*(y2-y) >> 3;
          int xadder4=5*(x2-x) >> 3;
          int yadder4=5*(y2-y) >> 3;
          int xadder5=7*(x2-x) >> 3;
          int yadder5=7*(y2-y) >> 3;
          int red1=(red[x+ypos]+red[x+xadder+(y+yadder)*picxsize]+red[x+xadder1+(y+yadder1)*picxsize]+
            red[x2+ypos2]+red[x+xadder2+(y+yadder2)*picxsize]+red[x+xadder3+(y+yadder3)*picxsize]+red[x+xadder4+(y+yadder4)*picxsize]+
            red[x+xadder5+(y+yadder5)*picxsize]) >> 3;
          int green1=(green[x+ypos]+green[x+xadder+(y+yadder)*picxsize]+green[x+xadder1+(y+yadder1)*picxsize]+
            green[x2+ypos2]+green[x+xadder2+(y+yadder2)*picxsize]+green[x+xadder3+(y+yadder3)*picxsize]+green[x+xadder4+(y+yadder4)*picxsize]+
            green[x+xadder5+(y+yadder5)*picxsize]) >> 3;
          int blue1=(blue[x+ypos]+blue[x+xadder+(y+yadder)*picxsize]+blue[x+xadder1+(y+yadder1)*picxsize]+
            blue[x2+ypos2]+blue[x+xadder2+(y+yadder2)*picxsize]+blue[x+xadder3+(y+yadder3)*picxsize]+blue[x+xadder4+(y+yadder4)*picxsize]+
            blue[x+xadder5+(y+yadder5)*picxsize]) >> 3;
          pix[x+y*picxsize]=(255 << 24)+(red1 << 16)+(green1 << 8)+blue1;
        } else pix[x+y*picxsize]=pix1[x+y*picxsize];
      }
    }
    if (pos==false) {
     cnt1+=2;
     xval+=2*xadd;
    } else {
     cnt1-=2;
     xval-=2*xadd;
   }
   timer++;
   if (timer>55) partnr=3;
   cnt=(int)xval;
   if (cnt1>25) pos=true;
   if (cnt1<8) pos=false;
  }

public void Opening_3() {
    int re1=0,bl1=0,gn1=0,nx = 0, ny = 0;
     for (int y=1; y < picysize-1; y++) {
        int ypos=y*picxsize;
        for (int x = 1; x < picxsize-1; x++) {
         if (cnt2==0) {
           nx=(difx[(x+1)+ypos]-difx[(x-1)+ypos]) << 1;
           ny=(difx[x+(y+1)*picxsize]-difx[x+(y-1)*picxsize]) << 1;
         }
         if (cnt2==1) {
           nx=(difx[(x+1)+ypos]-difx[(x-1)+ypos]);
           ny=(difx[x+(y+1)*picxsize]-difx[x+(y-1)*picxsize]);
         }
         if (cnt2>1) {
           nx=(difx[(x+1)+ypos]-difx[(x-1)+ypos]) >> (cnt2-1);
           ny=(difx[x+(y+1)*picxsize]-difx[x+(y-1)*picxsize]) >> (cnt2-1);
         }
         red[x+ypos]=255-((Math.abs(nx)+Math.abs(ny)));
         if (red[x+ypos]<0) red[x+ypos]=0;
      }
     }
     for (int y=1; y<picysize-1; y++) {
       int ypos=y*picxsize;
       for (int x=1; x<picxsize-1; x++) if (difx[x+ypos]>cnt1) {
         int x1=x+1;
         int x2=x+2;
         int x3=x+3;
         int y1=y-1;
         int y2=y-2;
         int y3=y-3;
         int x4=x+4;
         int y4=y-4;
         if (x1>picxsize-1) x1=picxsize-1;
         if (x2>picxsize-1) x2=picxsize-1;
         if (x3>picxsize-1) x3=picxsize-1;
         if (x4>picxsize-1) x4=picxsize-1;
         if (y1<0) y1=0;
         if (y2<0) y2=0;
         if (y3<0) y3=0;
         if (y4<0) y4=0;
         y1*=picxsize; y2*=picxsize; y3*=picxsize; y4*=picxsize;
         int difx1=(4*red[x+ypos]+red[x1+y1]+red[x2+y2]+red[x3+y3]+red[x4+y4]) >> 3;
         pix[x+ypos]=(255 << 24)+(difx1 << 16)+(difx1 << 8)+difx1;
        }
       else pix[x+ypos]=pix1[x+ypos];
    }
    timer++;
    if (timer>20) cnt1-=8;
    if (timer>70&&timer%3==0) cnt2++;
    if (cnt2>8) partnr=5;
  }

  public void Opening_4() {
    if (cnt==0) Pic_1();
    if (cnt==1) Pic_2();
    if (cnt==2) Pic_3();
  }

 public void Tunnel2() {
     if (timer>299) {
       for (int i1=1; i1<11; i1++) {
        sxpos[i1]=120+(int)(((timer-300) << 1)*Ctab[scnt[i1]]);
        sypos[i1]=100+(int)(((timer-300) << 1)*Stab[scnt[i1]]);
        for (int r=0; r<16; r++) {
          ClearCircle(sxpos[i1],sypos[i1],r,8);
          ClearCircle(sxpos[i1]+1,sypos[i1],r,8);
        }
        scnt[i1]=(scnt[i1]+4)%360;
       }
     }
     if (timer<300) {
       for (int y=0; y < 200; y++) {
            int ypos=y*240;
            for (int x=0; x <120; x++) {
              i=(dispic[x+ypos]-cnt)&127;
              i1=(difx[x+ypos]-cnt)&127;
              red[x+ypos]=(cloud[i1+(i << 7)]);
              red[(239-x)+ypos]=cloud[i1+(i << 7)];
            }
        }
       for (int y=1; y < 199; y++) {
          int ypos=y*240;
          for (int x = 1; x < 239; x++) {
           int nx=(red[(x+1)+ypos]-red[(x-1)+ypos]) << 1;
           int ny=(red[x+(y+1)*240]-red[x+(y-1)*240]) << 1;
           green[x+ypos]=255-((Math.abs(nx)+Math.abs(ny)));
           if (green[x+ypos]<0) green[x+ypos]=0;
        }
       }
     }
     for (int y=1; y<199; y++) {
       int ypos=y*240;
       for (int x=1; x<239; x++) {
         int x1=x+1;
         int x2=x+2;
         int x3=x+3;
         int y1=y-1;
         int y2=y-2;
         int y3=y-3;
         int x4=x+4;
         int y4=y-4;
         if (x1>239) x1=239;
         if (x2>239) x2=239;
         if (x3>239) x3=239;
         if (x4>239) x4=239;
         if (y1<0) y1=0;
         if (y2<0) y2=0;
         if (y3<0) y3=0;
         if (y4<0) y4=0;
         y1*=240; y2*=240; y3*=240; y4*=240;
         int sum1=(4*green[x+ypos]+green[x1+y1]+green[x2+y2]+green[x3+y3]+green[x4+y4]) >> 3;
         if (timer>299&&sum1>255) sum1=255;
         pix[x+ypos]=(255 << 24)+(sum1 << 16)+(sum1 << 8)+sum1;
        }
    }
    if (timer<300) cnt=(cnt+4)%256;
    if (timer>385) partnr=9;
  }

  public void Tunnel1() {
     for (int y=0; y < 200; y++) {
          int ypos=y*240;
          for (int x=0; x <120; x++) {
            i=(dispic[x+ypos]-cnt)&127;
            i1=(difx[x+ypos]-cnt)&127;
            int color=cloud[i1+(i << 7)];
            int color1=cloud[i+(i1 << 7)];
            pix[x+ypos]=(255 << 24)+(color << 16)+((color1 >> 1) << 8);
            pix[(239-x)+ypos]=(255 << 24)+(color << 16)+((color1 >> 1) << 8);
          }
      }
      cnt=(cnt+4)%256;
  }

  public void Part1() {
    if (timer<200) Tunnel1();
    timer++;
    if (timer>=200) Tunnel2();
  }

  public void Part2() {
    for (int y=0; y<picysize; y++) {
      int ypos=y*picxsize;
      for (int x=0; x<picxsize; x++) red[x+ypos]=0;
    }
    Calrotxmat(192,rotx);
    Calrotymat(0,roty);
    Calrotzmat(cnt,rotz);
    for (int i=0; i<maxverts; i++) {
      int ax=(roty.a1*pointx[i]+roty.a3*pointz2[i]) >> 7;
      int ay=(rotz.b2*pointy[i]-rotz.b1*ax) >> 7;
      int az=(roty.c3*pointz2[i]+roty.c1*pointx[i]) >> 7;
      px[i]=(rotz.a1*ax+rotz.a2*pointy[i]) >> 7;
      py[i]=(rotx.b2*ay+rotx.b3*az) >> 7;
      pz[i]=(rotx.c3*az-rotx.c2*ay) >> 7;
      if (pos==false) pointz[i]-=2; else pointz[i]+=2;
      pointz2[i]=pointz[i];
      if (timer<200) {
        if (pos1[0]==false) pointy[i]--; else pointy[i]++;
        if (pointz2[i]<-20) pointz2[i]=-20;
        if (pointz2[i]>60) pointz2[i]=60;
      }
    }
    Calrotxmat(192,rotx);
    Calrotymat(0,roty);
    for (int i=maxverts; i<maxverts+10; i++) {
      Calrotzmat((scnt[i-(maxverts)]+cnt)%256,rotz);
      int ax=(roty.a1*pointx[i]+roty.a3*pointz[i]) >> 7;
      int ay=(rotz.b2*pointy[i]-rotz.b1*ax) >> 7;
      int az=(roty.c3*pointz[i]+roty.c1*pointx[i]) >> 7;
      px[i]=(rotz.a1*ax+rotz.a2*pointy[i]) >> 7;
      py[i]=(rotx.b2*ay+rotx.b3*az) >> 7;
      pz[i]=(rotx.c3*az-rotx.c2*ay) >> 7;
      if (timer<200) {
        if (pos==false) pointz[i]-=2; else pointz[i]+=2;
        if (pos1[0]==false) pointy[i]--; else pointy[i]++;
      }
    }
   if (pos==false) cnter++; else cnter--;
   if (pos1[0]==false) cnter1++; else cnter1--;
   if (cnter>20) pos=true;
   if (cnter1>15) pos1[0]=true;
   if (cnter<-20) pos=false;
   if (cnter1<-15) pos1[0]=false;
  for (int i=0; i<maxface; i++) Tria3d(facelist[i],192);
  for (int i=8; i<maxverts-1; i++) Line3d(px[i],py[i],pz[i],px[i+1],py[i+1],pz[i+1]);
  for (int i=maxverts; i<maxverts+10; i++) Lens3d(px[i],py[i],pz[i],128);
   for (int y=1; y < picysize-1; y++) {
     int ypos=y*picxsize;
      for (int x = 1; x < picxsize-1; x++) {
       int nx=(red[(x+1)+ypos]-red[(x-1)+ypos]) << 2;
       int ny=(red[x+(y+1)*picxsize]-red[x+(y-1)*picxsize]) << 2;
       green[x+ypos]=255-((Math.abs(nx)+Math.abs(ny)));
       if (green[x+ypos]<0) green[x+ypos]=0;
      }
     }
     for (int y=1; y<picysize-1; y++) {
       int ypos=y*picxsize;
       for (int x=1; x<picxsize-1; x++) {
         int x1=x+1;
         int x2=x+2;
         int x3=x+3;
         int y1=y-1;
         int y2=y-2;
         int y3=y-3;
         int x4=x+4;
         int y4=y-4;
         if (x1>picxsize-1) x1=picxsize-1;
         if (x2>picxsize-1) x2=picxsize-1;
         if (x3>picxsize-1) x3=picxsize-1;
         if (x4>picxsize-1) x4=picxsize-1;
         if (y1<0) y1=0;
         if (y2<0) y2=0;
         if (y3<0) y3=0;
         if (y4<0) y4=0;
         y1*=picxsize; y2*=picxsize; y3*=picxsize; y4*=picxsize;
         int sum1=(4*green[x+ypos]+green[x1+y1]+green[x2+y2]+green[x3+y3]+green[x4+y4]) >> 3;
         pix[x+ypos]=(255 << 24)+(sum1 << 16)+(sum1 << 8)+sum1;
        }
    }
   cnt=(cnt+4)%256;
   timer++;
   if (timer<60) cameray-=2;
   if (timer>=200) cameray-=4;
   if (timer>60&&timer<200) {
      if (cnt1<360) camerax+=(int)(3*Stab[cnt1]);
      if (cnt1>360) camerax-=(int)(3*Stab[(cnt1)%360]);
      cnt1=(cnt1+8)%720;
   }
   if (cameray<-120) partnr=11;
 }

  public void Part3() {
    if (cnter<40&&timer<80) {
      for (int i2=0; i2<5; i2++)
        for (int i1=0; i1<5; i1++)
          for (int i=0; i<5; i++) { pointx[i+i1*5+i2*25]=-cnter+i*(cnter >> 1); pointy[i+i1*5+i2*25]=-cnter+i1*(cnter >> 1); pointz[i+i1*5+i2*25]=-cnter+i2*(cnter >> 1);
      }
      cnter+=2;
    }
    if (timer>80) {
      for (int i2=0; i2<5; i2++)
        for (int i1=0; i1<5; i1++)
          for (int i=0; i<5; i++) { pointx[i+i1*5+i2*25]=-cnter+i*(cnter >> 1); pointy[i+i1*5+i2*25]=-cnter+i1*(cnter >> 1); pointz[i+i1*5+i2*25]=-cnter+i2*(cnter >> 1);
      }
      cnter-=2;
    }
    Calrotxmat(0,rotx);
    Calrotymat(cnt,roty);
    Calrotzmat(cnt3,rotz);
    for (int i=0; i<125; i++) {
      int ax1=(roty.a1*pointx[i]+roty.a3*pointz[i]) >> 7;
      int ay1=(rotz.b2*pointy[i]-rotz.b1*ax1) >> 7;
      int az1=(roty.c3*pointz[i]+roty.c1*pointx[i]) >> 7;
      px[i]=(rotz.a1*ax1+rotz.a2*pointy[i]) >> 7;
      py[i]=(rotx.b2*ay1+rotx.b3*az1) >> 7;
      pz[i]=(rotx.c3*az1-rotx.c2*ay1) >> 7;
    }
    for (int i=0; i<cnt2; i++) {
      stars[i].setRotx(0);
      stars[i].setRoty(0);
      stars[i].setRotz(0);
      Calrotxmat(stars[i].phix,stars[i].rotx);
      Calrotymat(stars[i].phiy,stars[i].roty);
      Calrotzmat(stars[i].phiz,stars[i].rotz);
      int ax=(stars[i].roty.a1*stars[i].sx+stars[i].roty.a3*stars[i].sz) >> 7;
      int ay=(stars[i].rotz.b2*stars[i].sy-stars[i].rotz.b1*ax) >> 7;
      int az=(stars[i].roty.c3*stars[i].sz+stars[i].roty.c1*stars[i].sx) >> 7;
      stars[i].px=(stars[i].rotz.a1*ax+stars[i].rotz.a2*stars[i].sy) >> 7;
      stars[i].py=(stars[i].rotx.b2*ay+stars[i].rotx.b3*az) >> 7;
      stars[i].pz=(stars[i].rotx.c3*az-stars[i].rotx.c2*ay) >> 7;
      Set3dPixel2(stars[i].px,stars[i].py,stars[i].pz,255-Math.abs(stars[i].pz));
    }
    if (cnt2<250) cnt2+=125;
    cnt=(cnt+2)%256;
    cnt3=(cnt3+1)%256;
    for (int i=0; i<125; i++) {
      stars[cnt1] = new Particle(px[i],py[i],pz[i]);
      cnt1=(cnt1+1)%250;
    }
    for (int y=1; y<166; y++) {
      int ypos=y*200;
      for (int x=1; x<199; x++) {
         int nx=(red[(x+1)+ypos]-red[(x-1)+ypos]) << 1;
         int ny=(red[x+((y+1)*200)]-red[x+((y-1)*200)]) << 1;
         green[x+ypos]=255-((Math.abs(nx)+Math.abs(ny)));
         if (green[x+ypos]<0) green[x+ypos]=0;
       }
     }
    for (int y=1; y<166; y++) {
       int ypos=y*200;
       for (int x=1; x<199; x++) {
         int x1=x+1;
         int x2=x+2;
         int x3=x+3;
         int y1=y-1;
         int y2=y-2;
         int y3=y-3;
         int x4=x+4;
         int y4=y-4;
         if (x1>199) x1=199;
         if (x2>199) x2=199;
         if (x3>199) x3=199;
         if (x4>199) x4=199;
         if (y1<0) y1=0;
         if (y2<0) y2=0;
         if (y3<0) y3=0;
         if (y4<0) y4=0;
         y1*=200; y2*=200; y3*=200; y4*=200;
         int sum1=(4*green[x+ypos]+green[x1+y1]+green[x2+y2]+green[x3+y3]+green[x4+y4]) >> 3;
         pix[x+ypos]=(255 << 24)+(sum1 << 16)+(sum1 << 8)+sum1;
         red[x+ypos]-=32;
         if (red[x+ypos]<0) red[x+ypos]=0;
        }
    }
//    if (cameraz>50) cameraz--;
    timer++;
    if (timer>105) partnr=13;
  }

  public void Part4() {
    for (int y=0; y<picysize; y++) {
      int ypos=y*picxsize;
      for (int x=0; x<picxsize; x++) red[x+ypos]=0;
    }
    Calrotxmat(192,rotx);
    if (timer<100)  Calrotymat(0,roty); else Calrotymat(cnt2,roty);
    Calrotzmat(cnt,rotz);
    for (int i=0; i<(maxverts >> 1); i++) {
      int ax=(roty.a1*pointx[i]+roty.a3*pointz[i]) >> 7;
      int ay=(rotz.b2*pointy[i]-rotz.b1*ax) >> 7;
      int az=(roty.c3*pointz[i]+roty.c1*pointx[i]) >> 7;
      px[i]=(rotz.a1*ax+rotz.a2*pointy[i]) >> 7;
      py[i]=(rotx.b2*ay+rotx.b3*az) >> 7;
      pz[i]=(rotx.c3*az-rotx.c2*ay) >> 7;
    }
    Calrotxmat(192,rotx);
    if (timer<100)  Calrotymat(0,roty); else Calrotymat(cnt2,roty);
    Calrotzmat((cnt << 1)%256,rotz);
    for (int i=(maxverts >> 1); i<maxverts; i++) {
      int ax=(roty.a1*pointx[i]+roty.a3*pointz[i]) >> 7;
      int ay=(rotz.b2*pointy[i]-rotz.b1*ax) >> 7;
      int az=(roty.c3*pointz[i]+roty.c1*pointx[i]) >> 7;
      px[i]=(rotz.a1*ax+rotz.a2*pointy[i]) >> 7;
      py[i]=(rotx.b2*ay+rotx.b3*az) >> 7;
      pz[i]=(rotx.c3*az-rotx.c2*ay) >> 7;
    }
   for (int i=0; i<maxface; i++) {
     Calcnorm(facelist[i],normx,normy,normz,i);
   }
   for (int i=0; i<maxverts; i++) gnormx[i]=gnormy[i]=gnormz[i]=0;
   for (int i=0; i<maxface; i++) {
     gnormx[facelist[i].p]+=normx[facelist[i].nr];
     gnormy[facelist[i].p]+=normy[facelist[i].nr];
     gnormz[facelist[i].p]+=normz[facelist[i].nr];
     gnormx[facelist[i].p1]+=normx[facelist[i].nr];
     gnormy[facelist[i].p1]+=normy[facelist[i].nr];
     gnormz[facelist[i].p1]+=normz[facelist[i].nr];
     gnormx[facelist[i].p2]+=normx[facelist[i].nr];
     gnormy[facelist[i].p2]+=normy[facelist[i].nr];
     gnormz[facelist[i].p2]+=normz[facelist[i].nr];
    }
   for (int i=0; i<maxverts; i++) Normvek(gnormx,gnormy,gnormz,i);
   int cnt1=0;
   for (int i=0; i<maxface; i++) {
      if (normz[i]>0.0f) {
        double cosa=gnormx[facelist[i].p]*lightx+gnormy[facelist[i].p]*lighty+gnormz[facelist[i].p]*lightz;
        if (cosa>0.0f) facelist[i].clr=(int)(cosa*255); else facelist[i].clr=0;
        cosa=gnormx[facelist[i].p1]*lightx+gnormy[facelist[i].p1]*lighty+gnormz[facelist[i].p1]*lightz;
        if (cosa>0.0f) facelist[i].clr1=(int)(cosa*255); else facelist[i].clr1=0;
        cosa=gnormx[facelist[i].p2]*lightx+gnormy[facelist[i].p2]*lighty+gnormz[facelist[i].p2]*lightz;
        if (cosa>0.0f) facelist[i].clr2=(int)(cosa*255); else facelist[i].clr2=0;
        indx[cnt1].z=(int)(pz[facelist[i].p]+pz[facelist[i].p1]+pz[facelist[i].p2])/3;
        indx[cnt1].nr=i;
        cnt1++;
    }
  }
   quicksort(0,cnt1-1);
   for (int i=0; i<cnt1; i++) Shade_tria3d(facelist[indx[i].nr],120);
   for (int y=1; y < picysize-1; y++) {
     int ypos=y*picxsize;
      for (int x = 1; x < picxsize-1; x++) {
       int nx=(red[(x+1)+ypos]-red[(x-1)+ypos]) << 2;
       int ny=(red[x+(y+1)*picxsize]-red[x+(y-1)*picxsize]) << 2;
       green[x+ypos]=255-((Math.abs(nx)+Math.abs(ny)));
       if (green[x+ypos]<0) green[x+ypos]=0;
      }
     }
     for (int y=1; y<picysize-1; y++) {
       int ypos=y*picxsize;
       for (int x=1; x<picxsize-1; x++) {
         int x1=x+1;
         int x2=x+2;
         int x3=x+3;
         int y1=y-1;
         int y2=y-2;
         int y3=y-3;
         int x4=x+4;
         int y4=y-4;
         if (x1>picxsize-1) x1=picxsize-1;
         if (x2>picxsize-1) x2=picxsize-1;
         if (x3>picxsize-1) x3=picxsize-1;
         if (x4>picxsize-1) x4=picxsize-1;
         if (y1<0) y1=0;
         if (y2<0) y2=0;
         if (y3<0) y3=0;
         if (y4<0) y4=0;
         y1*=picxsize; y2*=picxsize; y3*=picxsize; y4*=picxsize;
         int sum1=(4*green[x+ypos]+green[x1+y1]+green[x2+y2]+green[x3+y3]+green[x4+y4]) >> 3;
         pix[x+ypos]=(255 << 24)+(sum1 << 16)+(sum1 << 8)+sum1;
        }
    }
    cnt=(cnt+4)%256;
    if (timer<80) {
      if (camerax<0) camerax++;
      if (cameray<0) cameray++;
    }
    timer++;
    if (timer>100) cnt2=(cnt2+2)%256;
    if (timer>140) { camerax+=2; cameray-=2; }
    if (timer>190) partnr=15;
  }

  public void Part5_1() {
    for (int y=0; y<picysize; y++) {
      int ypos=y*picxsize;
      for (int x=0; x<picxsize; x++) red[x+ypos]=0;
    }
    Calrotxmat(63,rotx);
    if (camerax<0) Calrotymat((127+cnt)%256,roty); else Calrotymat(127,roty);
    Calrotzmat(cnt,rotz);
    for (int i=0; i<maxverts; i++) {
      int ax=(roty.a1*pointx[i]+roty.a3*pointz[i]) >> 7;
      int ay=(rotz.b2*pointy[i]-rotz.b1*ax) >> 7;
      int az=(roty.c3*pointz[i]+roty.c1*pointx[i]) >> 7;
      px[i]=(rotz.a1*ax+rotz.a2*pointy[i]) >> 7;
      py[i]=(rotx.b2*ay+rotx.b3*az) >> 7;
      pz[i]=(rotx.c3*az-rotx.c2*ay) >> 7;
    }
   for (int i=0; i<maxface; i++) {
     Calcnorm(facelist[i],normx,normy,normz,i);
   }
   for (int i=0; i<maxverts; i++) gnormx[i]=gnormy[i]=gnormz[i]=0;
   for (int i=0; i<maxface; i++) {
     gnormx[facelist[i].p]+=normx[facelist[i].nr];
     gnormy[facelist[i].p]+=normy[facelist[i].nr];
     gnormz[facelist[i].p]+=normz[facelist[i].nr];
     gnormx[facelist[i].p1]+=normx[facelist[i].nr];
     gnormy[facelist[i].p1]+=normy[facelist[i].nr];
     gnormz[facelist[i].p1]+=normz[facelist[i].nr];
     gnormx[facelist[i].p2]+=normx[facelist[i].nr];
     gnormy[facelist[i].p2]+=normy[facelist[i].nr];
     gnormz[facelist[i].p2]+=normz[facelist[i].nr];
    }
   for (int i=0; i<maxverts; i++) Normvek(gnormx,gnormy,gnormz,i);
   int cnt1=0;
   for (int i=0; i<maxface; i++) {
      if (normz[i]>0.0f) {
        indx[cnt1].z=(int)(pz[facelist[i].p]+pz[facelist[i].p1]+pz[facelist[i].p2])/3;
        indx[cnt1].nr=i;
        facelist[i].nx=128+(int)(Math.abs(gnormx[facelist[i].p]*127));
        facelist[i].ny=128+(int)(Math.abs(gnormy[facelist[i].p]*127));
        facelist[i].nx1=128+(int)(Math.abs(gnormx[facelist[i].p1]*127));
        facelist[i].ny1=128+(int)(Math.abs(gnormy[facelist[i].p1]*127));
        facelist[i].nx2=128+(int)(Math.abs(gnormx[facelist[i].p2]*127));
        facelist[i].ny2=128+(int)(Math.abs(gnormy[facelist[i].p2]*127));
        cnt1++;
    }
  }
   quicksort(0,cnt1-1);
   for (int i=0; i<cnt1; i++) Texture_tria3d(facelist[indx[i].nr]);
   for (int y=1; y < picysize-1; y++) {
     int ypos=y*picxsize;
      for (int x = 1; x < picxsize-1; x++) {
       int nx=(red[(x+1)+ypos]-red[(x-1)+ypos]) << 2;
       int ny=(red[x+(y+1)*picxsize]-red[x+(y-1)*picxsize]) << 2;
       green[x+ypos]=255-((Math.abs(nx)+Math.abs(ny)));
       if (green[x+ypos]<0) green[x+ypos]=0;
      }
     }
     for (int y=1; y<picysize-1; y++) {
       int ypos=y*picxsize;
       for (int x=1; x<picxsize-1; x++) {
         int x1=x+1;
         int x2=x+2;
         int x3=x+3;
         int y1=y-1;
         int y2=y-2;
         int y3=y-3;
         int x4=x+4;
         int y4=y-4;
         if (x1>picxsize-1) x1=picxsize-1;
         if (x2>picxsize-1) x2=picxsize-1;
         if (x3>picxsize-1) x3=picxsize-1;
         if (x4>picxsize-1) x4=picxsize-1;
         if (y1<0) y1=0;
         if (y2<0) y2=0;
         if (y3<0) y3=0;
         if (y4<0) y4=0;
         y1*=picxsize; y2*=picxsize; y3*=picxsize; y4*=picxsize;
         int sum1=(4*green[x+ypos]+green[x1+y1]+green[x2+y2]+green[x3+y3]+green[x4+y4]) >> 3;
         pix[x+ypos]=(255 << 24)+(sum1 << 16)+(sum1 << 8)+sum1;
        }
    }
    cnt=(cnt+4)%256;
    if (camerax>0) camerax-=3; else camerax-=2;
    if (camerax<-160) partnr=17;
  }

   public void Part5() {
     if (timer<75) Cloud_1(); else { Cloud_2(); if (pos==false) cnt3+=4; else cnt3-=4; }
     if (cnt3>330) pos=true;
     if (cnt3<0) partnr=19;
     cnt1=(cnt1+2)%128;
     cnt2=(cnt2+4)%360;
     timer++;
   }

   public void Cloud_1() {
    for (int y=0; y<picysize; y++) {
      int ypos=y*picxsize;
      for (int x=0; x<picxsize; x++)
         red[x+ypos]=(int)(cloud[x%128+((y%128) << 7)]+cloud1[x%128+((y%128) << 7)]+cloud1[(x+cnt1)%128+((y%128) << 7)]+cloud1[(x+cnt)%128+(((y+cnt1)%128) << 7)]) >> 2;
    }
    for (int y=0; y<64; y++) { int ypos=(y << 6);
      for (int x=0; x<64; x++) if (pix1[x+ypos]>0) {
        int sypos=20+(y*3);
        int sxpos=(x << 2);
        int ylpos=sypos*picxsize;
        for (int i1=0; i1<360; i1+=36) {
          int x1=sxpos+(int)(8*Ctab[(i1+cnt2)%360]);
          int y1=(int)(8*Stab[(i1+cnt2)%360]);
          if (red[sxpos+ylpos]<cval) {
            X_line(sxpos,sypos,x1,sypos+y1,64);
          }
        }
      }
    }
    for (int y=0; y<picysize; y++) {
      int ypos=picxsize*y;
      for (int x=0; x<picxsize; x++) {
        int color=dispic[x+ypos];
        if (color>255) color=255;
        dispic[x+ypos]=color;
        int blue1=red[x+ypos];
        int green1=red[x+ypos];
        int red1=red[x+ypos];
        if (dispic[x+ypos]>0) {
            color=(3*color) >> 2;
            green1+=color;
            red1+=color;
            if (red1>255) red1=255;
            if (green1>255) green1=255;
          pix[x+ypos]=(255 << 24)+(red1 << 16)+(green1 << 8)+blue1;
        } else pix[x+ypos]=(255 << 24)+(red1 << 16)+(green1 << 8)+blue1;
        dispic[x+ypos]-=96;
        if (dispic[x+ypos]<0) dispic[x+ypos]=0;
        red[x+ypos]=0;
      }
   }
   if (cval<300) cval+=4;
 }

   public void Cloud_2() {
    for (int y=1; y<picysize-1; y++) {
      int ypos=y*picxsize;
      for (int x=1; x<picxsize-1; x++)   {
         int cldval=(int)(cloud[x%128+((y%128) << 7)]+cloud1[x%128+((y%128) << 7)]+cloud1[(x+cnt1)%128+((y%128) << 7)]+cloud1[(x+cnt)%128+(((y+cnt1)%128) << 7)]) >> 2;
         int nx=(difx[x+1+ypos]-difx[x-1+ypos]);
         int ny=(difx[x+(y+1)*picxsize]-difx[x+(y-1)*picxsize]);
         int light=Math.abs(cldval-nx)+Math.abs(cldval-ny);
         if (cldval<cnt3) color=(difx[x+ypos] >> 3)+(light >> 1); else color=cldval;
         if (color<0) color=0;
         if (color>255) color=255;
         pix[x+ypos]=(255 << 24)+(color << 16)+(color << 8)+color;
      }
    }
 }

   public void CheckPoint() {
     for (int i=0; i<25; i++) {
     if (sxpos[i]>0&&sxpos[i]<picxsize-1&&sypos[i]>0&&sypos[i]<picysize-1) {
       if (green[sxpos[i]+sypos[i]*picxsize]==0&&(green[sxpos[i]+1+sypos[i]*picxsize]>0||green[sxpos[i]-1+sypos[i]*picxsize]>0||green[sxpos[i]+(sypos[i]-1)*picxsize]>0||
        green[sxpos[i]+(sypos[i]-1)*picxsize]>0)) green[sxpos[i]+sypos[i]*picxsize]=223;
        sxpos[i]=(int)(Math.random()*240); sypos[i]=(int)(Math.random()*140);
     } else {
       sxpos[i]+=(-1+(int)(Math.random()*4));
       sypos[i]+=(-1+(int)(Math.random()*4));
     }
     if (sxpos[i]<0||sxpos[i]>picxsize-1) sxpos[i]=(int)(Math.random()*240);
     if (sypos[i]<0||sypos[i]>picysize-1) sypos[i]=(int)(Math.random()*140);
    }
  }

  public void Part6() {
     CheckPoint();
     for (int i=0; i<20; i++) { pointx[i]+=-1+(int)(Math.random()*3); pointy[i]-=py[i];
       int r1=pointz[i]+(200-pointy[i]) >> 4;
       Bubble(pointx[i],pointy[i],r1,128);
       if (pointy[i]<-20) {
        pointx[i]=(int)(Math.random()*240); pointy[i]=200+(int)(Math.random()*30);
        pointz[i]=(int)(Math.random()*5); py[i]=3+(int)(Math.random()*3);
       }
     }
     for (int y=0; y < picysize; y++) {
        int ypos=y*picxsize;
        for (int x = 0; x < picxsize; x++) {
            int cldvl=(int)(cloud[x%128+((y%128) << 7)]+cloud1[x%128+((y%128) << 7)]+cloud1[(x+cnt1)%128+((y%128) << 7)]+cloud1[(x+cnt)%128+(((y+cnt1)%128) << 7)]) >> 2;
            int brnfak = cldvl >> 1;
            int green1=green[x+ypos]-brnfak;
            int blue1=blue[x+ypos]+((3*cldvl) >> 2);
            if (blue1>255) blue1=255;
            if (blue1<0) blue1=0;
            if (green1<0) green1=0;
            int distort=-16+(int)(cldvl >> 4);
            int x1=x+distort;
            if (x1<0) x1=0;
            if (x1>picxsize-1) x1=picxsize-1;
            int y1=(y+distort);
            if (y1<0) y1=0;
            if (y1>picysize-1) y1=picysize-1;
            y1*=picxsize;
            pix1[x+ypos]=(255 << 24)+(green1 << 8)+blue1;
            blue[x+ypos]=0;
            pix[x+ypos]=pix1[x1+y1];
          }
     }
    cnt=(cnt+2)%256;
    cnt1=(cnt1+3)%256;
    timer++;
    if (timer>200) partnr=21;
  }

  public void EndPart() {
    for (int r=0; r<100; r++) {
      if (pos==false) cnt+=8; else cnt-=8;
      if (cnt>64) pos=true;
      if (cnt<0) pos=false;
      for (int i=0; i<2; i++) {
        int sx=sxpos[i]+(int)(30*Stab[scnt[i]]);
        int sy=sypos[i]+(int)(30*Ctab[scnt[i]]);
        Circle1(sx,sy,r,cnt);
        Circle1(sx,sy,r,cnt);
      }
    }
    scnt[0]=(scnt[0]+2)%360;
    scnt[1]=(scnt[1]+2)%360;
    for (int y=1; y<picysize-1; y++) {
      int ypos=y*picxsize;
      for (int x=1; x<picxsize-1; x++) {
        int nx=(red[x+1+ypos]-red[x-1+ypos]) << 1;
        int ny=(red[x+(y+1)*picxsize]-red[x+(y-1)*picxsize]) << 1;
        int color=pix1[x+ypos]-nx+pix1[x+ypos]-ny;
        if (color<0) color=0;
        if (color>255) color=255;
        blue[x+ypos]=color;
      }
    }
     for (int y=1; y<picysize-1; y++) {
      int ypos=y*picxsize;
      for (int x=1; x<picxsize-1; x++) {
         int nx=(blue[(x+1)+ypos]-blue[(x-1)+ypos]) << 1;
         int ny=(blue[x+((y+1)*picxsize)]-blue[x+((y-1)*picxsize)]) << 1;
         green[x+ypos]=255-((Math.abs(nx)+Math.abs(ny)));
         if (green[x+ypos]<0) green[x+ypos]=0;
       }
     }
    for (int y=1; y<picysize-1; y++) {
       int ypos=y*picxsize;
       for (int x=1; x<picxsize-1; x++) {
         int x1=x+1;
         int x2=x+2;
         int x3=x+3;
         int y1=y-1;
         int y2=y-2;
         int y3=y-3;
         int x4=x+4;
         int y4=y-4;
         if (x1>picxsize-1) x1=picxsize-1;
         if (x2>picxsize-1) x2=picxsize-1;
         if (x3>picxsize-1) x3=picxsize-1;
         if (x4>picxsize-1) x4=picxsize-1;
         if (y1<0) y1=0;
         if (y2<0) y2=0;
         if (y3<0) y3=0;
         if (y4<0) y4=0;
         y1*=picxsize; y2*=picxsize; y3*=picxsize; y4*=picxsize;
         int sum1=(4*green[x+ypos]+green[x1+y1]+green[x2+y2]+green[x3+y3]+green[x4+y4]) >> 3;
         pix[x+ypos]=(255 << 24)+(sum1 << 16)+(sum1 << 8)+sum1;
        }
    }
  }

  public void TextPart2() {
    offGraphics.setColor(Color.yellow);
    offGraphics.drawString(text[cnter],20,150);
  }

  public void TextPart1() {
    offGraphics.setColor(Color.blue);
    if (timer<200) text[2]=text[0];
    if (timer>=200) {
       text[2]=text[1].substring(0,cnt2);
       if (cnt2<15) text[3]=text[0].substring(cnt2,16); else text[3]="";
       text[2]=text[2]+text[3];
       if (cnt2<16) cnt2++;
    }
    if (timer<300) offGraphics.drawString(text[2],sxpos[0],60);
    if (pos1[0]==false) sxpos[0]-=4;
    if (sxpos[0]<=4) pos1[0]=true;
    if (pos1[0]==true) { sxpos[0]+=(int)(Stab[cnt1]*2); cnt1=(cnt1+8)%360; }
  }

  public void ShowEndPart() {
    for (int i=0; i<7; i++) {
     int sx=80+(int)(90*Ctab[scnt[i+2]]);
     int sy=80+(int)(90*Stab[scnt[i+2]]);
     offGraphics.drawImage(Shows[i],sx,sy,this);
     scnt[i+2]=(scnt[i+2]+4)%360;
   }
   offGraphics.drawImage(Img,sxpos[2],sypos[2],sxpos[3],sypos[3],Color.black,this);
   if (sxpos[2]<60) { sxpos[2]++; sypos[2]++; sxpos[3]-=2; sypos[3]-=2; }
   offGraphics.setColor(Color.green);
   for (int i=0; i<49; i++) if (pointy[i]>-10) {
     if (pointy[i]<220) offGraphics.drawString(text[i],1,pointy[i]);
     pointy[i]--;
   }
 }
  public void update(Graphics g) {
     Dimension d = size();
     if ( ( offGraphics == null) || (d.width !=offDimension.width) || (d.height!=offDimension.height) ) {
       offDimension = d;
       offImage = createImage(d.width,d.height);
       offGraphics = offImage.getGraphics();
      }
      offGraphics.setColor(c);
      offGraphics.fillRect(0,0,d.width,d.height);
      offGraphics.setColor(c);
     if (partnr!=6) Img.flush();
     switch (partnr) {
       case 0 : Opening_1();
       break;
       case 1 : LoadOp_2();
       break;
       case 2 : Opening_2();
       break;
       case 3 : LoadOp_3();
       break;
       case 4 : Opening_3();
       break;
       case 5 : Load_Op4();
       break;
       case 6 : Opening_4();
       break;
       case 7 : Load_Part1();
       break;
       case 8 : Part1();
       break;
       case 9 : Load_Part2();
       break;
       case 10 : Part2();
       break;
       case 11 : Load_Part3();
       break;
       case 12 : Part3();
       break;
       case 13 : Load_Part4();
       break;
       case 14 : Part4();
       break;
       case 15 : Load_Part5_1();
       break;
       case 16 : Part5_1();
       break;
       case 17 : Load_Part5();
       break;
       case 18 : Part5();
       break;
       case 19 : Load_Part6();
       break;
       case 20 : Part6();
       break;
       case 21 : Load_EndPart();
       break;
       case 22 : EndPart();
     }
     if (partnr!=6) Img = createImage(source);
     if (partnr==2) offGraphics.drawImage(Img,0,50,this);
     if (partnr>9&&partnr<18) offGraphics.drawImage(Img,0,0,240,200,Color.white,this);
     if (partnr!=2&&partnr!=3&&partnr!=6&&partnr!=7&&(partnr<10||partnr>17)&&partnr!=22) offGraphics.drawImage(Img,0,0,this);
     if (partnr==8) TextPart1();
     if (partnr==22) ShowEndPart();
     getAppletContext().showStatus("Coal from OtakInc");
     g.drawImage(offImage,0,0,this);
  }

  public void run() {
    long startTime = System.currentTimeMillis();
    while (killme != null) {
      frameNumber++;
      repaint();
      try {
	 startTime+=delay;
	 Thread.sleep(Math.max(0,startTime-System.currentTimeMillis()));
	 } catch (InterruptedException e) { break; }
    }
  }

 public void stop() {
    killme.stop();
    offGraphics = null;
    offImage = null;
//    killme.destroy();
    killme = null;
  }

}
