////////////////////////////////////////////////////////////////////////////// // C S E Logo // // A Realtime calculated & generated Java applet to show off the CSE // // logo in 3D. All code Copyright (C) 1996 by The Rasterman a.k.a. // // Carsten Haitzler. No responsability is taken for anything this // // Applet may or may not do on your system. You run this completely // // at your own risk. // // // // This Applet was developed completely under Linux. All praise be to Linus // // // ////////////////////////////////////////////////////////////////////////////// // Be warned. This applet can bring your machine down. Java has bugs. There // // is a memory leak, that when there isn't enough processing time left to // // do garbage collection, it keeps eating up more memory. This can be fatal // // to some machines/architechtures/operating systems. On others it is just // // an annoyance. I am not responsible for this. Java is still immature in // // its implementations, and is in no way prepared for the punishment I give // // languages. // ////////////////////////////////////////////////////////////////////////////// // This applet requires the GIF image bg.gif to be located in the same dir // // or Documentbase as the Page containing the applet itself. If it isn't a // // white background will be displayed instead. // // // // If you move your mouse pointer, you will find the display updating close // // to doubles or trebles. This is a product of java's horendous threading // // and timing ability. // // // // You can interact with the applet by clicking on the window to place the // // lightsource within its current "z" plane. when you release the button, // // the light will slowly continue its randomised parabolic curved motion as // // before. // // // ////////////////////////////////////////////////////////////////////////////// // Code style: // // You will notice I make NO USE of OO, inheritance or anything. there are // // no classes, nothing of the sort. I have programmed this in a very "C" // // style. I'm happy in C. I like it. I didnt like the idea of OO & Java // // being forced apon me in graphics, where it is not appropriate. Graphics // // is a low-level thing, and so C & assembly are much more suited to it. // // You will of course disagree, but I started my graphics programming on a // // C64 many many years ago.. and I peeked 7 poked memory registers. I wrote // // sprite movement code in hex machine code. using OO for graphics is so // // foreign to me, it's not funny. I banged hardware registers and created // // my own graphics co-processor lists on my amiga to just get it to display // // part of the video ram.. then manipulated that ram on a byte-by-byte // // level using cpu & blitter. Now this assignment allowed me the freedom // // to develop my own code form scratch, and so I did so. I programmed in // // the style I've become aquainted with for over a decade. it's worked // // flawlessly for all that time, and I see no need tio suddenly change it // // and as a result limit what I can do here, due to my unfamiliarity with // // OO and java. I've had enough of a pain with java already, without going // // and OOicising my code. In my assingment I concentrated on GRAPHICS... // // what this subject is REALLY about.. not java or OO (as it seems to have // // become). I worked on graphics code, to do visuals as best as possible // // under a slow and limited java VM. I believe that any marking of code // // on its style of using OO or not is a complete affront to graphics coding // // in general, and to computing. I have noticed that CSE love to turn out // // little neat coders who code just as they have been told to in lectures // // and allow almost no room for creativity and innovation. It reeks of a // // an old moudly suken ship. Java is a great idea.. but its too new and // // too immature for this. Graphics is about principles, not OO or Java. If // // I wanted to learn OO I would have gone and done OO the subject! // // Anyway.. enough of my rant. enjoy the code. I have commented as fully // // as I see fit for someone wiht half a brain, and a bit of geometric and // // graphics knowledge needs to know whats going on. // ////////////////////////////////////////////////////////////////////////////// // Import some classes import java.applet.*; import java.awt.*; import java.awt.image.*; import java.util.*; // The applet itself public class cse extends Applet implements Runnable { ////////////////////////////////////////////////////////////////////////////// // Global variables.. okay SHOOT ME! I've coded this in a very "C" ish style // I really wasnt in a mood for having 10 class files for the thing and having // to keep switching for development..... and seeing java doesnt give me my // beloved pointers... I'm being eviland using globals :-P Bite me :-) ////////////////////////////////////////////////////////////////////////////// int width; // width of window int height; // height of window Image buffer; // buffer image Image background; // background image Color[][][] coltab; // 4096 colour RGB tookup table Thread draw=null; // drawing thread int[] polyP1; // point 1 for each poly int[] polyP2; // point 2 for each poly int[] polyP3; // point 3.... int[] polyP4; // point 4.. int[] polylist; // list of poly indexes after sorting int flipped=0; // flag is we're drawing the flipped reflected cse logo double[] pointx; // array of point x,y & z coords double[] pointy; double[] pointz; double[] cubex; // array of coords of the centers of all the cubes double[] cubey; double[] cubez; double[] polyr; // array fo rgb colour values for each polygon .. ranges double[] polyg; // from 0-15 for each rgb element. double[] polyb; double[] polyi; // array of polygon brightnesses (intensities) double logox; // center coords for the logo itself double logoy; double logoz; double[] logoposx; // array fo keyframe positions for the logo. tweening double[] logoposy; // is done via parabolic curve functions to get a smooth double[] logoposz; // motion curve. double focus; // focal lenght of "camera" - distance to projection plane double zoom; // zoom factro on logo itself.... double tf; // our keyframe counter boolean lmove=false; // flag for when the lightsource is being dragged double lightx=-100; // lightsource coordinates double lighty=-100; double lightz=-100; double[] lightposx; // array fo keyframe positions for the light. tweening double[] lightposy; // is done via parabolic curve functions to get a smooth double[] lightposz; // motion curve. double waterz=30; // the height (or depth) of the reflective water plane ////////////////////////////////////////////////////////////////////////////// // Here are all the methods used for setting up things like data structers, // object & polygon data etc. ////////////////////////////////////////////////////////////////////////////// // Method that contains the hard-coded CSE logo itself and sets up the cube // coords, aswell as initalising the bube array, logopos arra, and the // initial key frame positions... further keyframes are generated randomly // on the fly..... void GenLogo() { // allocate some arrays cubex=new double[35]; cubey=new double[35]; cubez=new double[35]; logoposx=new double[5]; logoposy=new double[5]; logoposz=new double[5]; lightposx=new double[5]; lightposy=new double[5]; lightposz=new double[5]; // Daata for the coords of the cubes themselves. I dont need to go into // this now do I???? cubex[ 0]=-6;cubey[ 0]=-6;cubez[ 0]=-6; cubex[ 1]=-3;cubey[ 1]=-6;cubez[ 1]=-6; cubex[ 2]= 0;cubey[ 2]=-6;cubez[ 2]=-6; cubex[ 3]= 3;cubey[ 3]=-6;cubez[ 3]=-6; cubex[ 4]= 6;cubey[ 4]=-6;cubez[ 4]=-6; cubex[ 5]=-6;cubey[ 5]=-3;cubez[ 5]=-6; cubex[ 6]=-6;cubey[ 6]= 0;cubez[ 6]=-6; cubex[ 7]=-3;cubey[ 7]= 0;cubez[ 7]=-6; cubex[ 8]= 0;cubey[ 8]= 0;cubez[ 8]=-6; cubex[ 9]= 3;cubey[ 9]= 0;cubez[ 9]=-6; cubex[10]= 6;cubey[10]= 0;cubez[10]=-6; cubex[11]= 6;cubey[11]= 3;cubez[11]=-6; cubex[12]= 6;cubey[12]= 6;cubez[12]=-6; cubex[13]= 3;cubey[13]= 6;cubez[13]=-6; cubex[14]= 0;cubey[14]= 6;cubez[14]=-6; cubex[15]=-3;cubey[15]= 6;cubez[15]=-6; cubex[16]=-6;cubey[16]= 6;cubez[16]=-6; cubex[17]= 6;cubey[17]=-6;cubez[17]=-3; cubex[18]= 6;cubey[18]=-6;cubez[18]= 0; cubex[19]= 6;cubey[19]=-6;cubez[19]= 3; cubex[20]= 6;cubey[20]=-6;cubez[20]= 6; cubex[21]= 6;cubey[21]= 0;cubez[21]=-3; cubex[22]= 6;cubey[22]= 0;cubez[22]= 0; cubex[23]= 6;cubey[23]= 0;cubez[23]= 3; cubex[24]= 6;cubey[24]= 0;cubez[24]= 6; cubex[25]= 6;cubey[25]= 6;cubez[25]=-3; cubex[26]= 6;cubey[26]= 6;cubez[26]= 0; cubex[27]= 6;cubey[27]= 6;cubez[27]= 3; cubex[28]= 6;cubey[28]= 6;cubez[28]= 6; cubex[29]= 3;cubey[29]=-6;cubez[29]= 6; cubex[30]=-3;cubey[30]=-6;cubez[30]= 6; cubex[31]=-6;cubey[31]=-6;cubez[31]=-3; cubex[32]=-6;cubey[32]=-6;cubez[32]= 0; cubex[33]=-6;cubey[33]=-6;cubez[33]= 3; cubex[34]=-6;cubey[34]=-6;cubez[34]= 6; // initial logo starting positions logox=0*zoom; logoy=-9*zoom; logoz=30*zoom; // initial keyfram postions for the logo logoposx[0]=-10*zoom; logoposy[0]=-10*zoom; logoposz[0]= 30*zoom; logoposx[1]= 20*zoom; logoposy[1]=-50*zoom; logoposz[1]= 150*zoom; logoposx[2]=-15*zoom; logoposy[2]=-20*zoom; logoposz[2]= 50*zoom; logoposx[3]= 5*zoom; logoposy[3]=-9*zoom; logoposz[3]= 20*zoom; logoposx[4]=-3*zoom; logoposy[4]=-10*zoom; logoposz[4]= 28*zoom; // initial light keyframe positions lightposx[0]=-20*zoom; lightposy[0]=-15*zoom; lightposz[0]= 10*zoom; lightposx[1]= 40*zoom; lightposy[1]=-100*zoom; lightposz[1]= 20*zoom; lightposx[2]= 10*zoom; lightposy[2]=-50*zoom; lightposz[2]= 100*zoom; lightposx[3]=-40*zoom; lightposy[3]=-200*zoom; lightposz[3]= 300*zoom; lightposx[4]= 10*zoom; lightposy[4]=-10*zoom; lightposz[4]= 10*zoom; } // Method that takes the cube coords generated by GenLogo, and creates // induvidual polygons wiht the right coords of the points, and the right // colours for the cube sides.... void GenPolys() { pointx=new double[35*8]; // more arrays to allocate pointy=new double[35*8]; pointz=new double[35*8]; polyP1=new int[35*6]; polyP2=new int[35*6]; polyP3=new int[35*6]; polyP4=new int[35*6]; polyr=new double[35*6]; polyg=new double[35*6]; polyb=new double[35*6]; polyi=new double[35*6]; int j=0,k=0; // random variables for (int i=0;i<35;i++) // create the points, and the polygon info for { // each cube in the cube array..... pointx[j]=-1+cubex[i]; pointy[j]=-1+cubey[i]; pointz[j++]=-1+cubez[i]; pointx[j]= 1+cubex[i]; pointy[j]=-1+cubey[i]; pointz[j++]=-1+cubez[i]; pointx[j]= 1+cubex[i]; pointy[j]= 1+cubey[i]; pointz[j++]=-1+cubez[i]; pointx[j]=-1+cubex[i]; pointy[j]= 1+cubey[i]; pointz[j++]=-1+cubez[i]; pointx[j]=-1+cubex[i]; pointy[j]=-1+cubey[i]; pointz[j++]= 1+cubez[i]; pointx[j]= 1+cubex[i]; pointy[j]=-1+cubey[i]; pointz[j++]= 1+cubez[i]; pointx[j]= 1+cubex[i]; pointy[j]= 1+cubey[i]; pointz[j++]= 1+cubez[i]; pointx[j]=-1+cubex[i]; pointy[j]= 1+cubey[i]; pointz[j++]= 1+cubez[i]; polyP1[k]=j-8;polyP2[k]=j-7;polyP3[k]=j-6;polyP4[k++]=j-5; polyP1[k]=j-4;polyP2[k]=j-3;polyP3[k]=j-7;polyP4[k++]=j-8; polyP1[k]=j-1;polyP2[k]=j-2;polyP3[k]=j-3;polyP4[k++]=j-4; polyP1[k]=j-5;polyP2[k]=j-6;polyP3[k]=j-2;polyP4[k++]=j-1; polyP1[k]=j-7;polyP2[k]=j-3;polyP3[k]=j-2;polyP4[k++]=j-6; polyP1[k]=j-4;polyP2[k]=j-8;polyP3[k]=j-5;polyP4[k++]=j-1; } // adjust the point coords according to the zoom factor for(int i=0;i=0) // if the poly is visible.. calculate its brightnes { // same as above tmpx=lightx-(pointx[polyP2[i]]+logox); tmpy=lighty-(pointy[polyP2[i]]+logoy); tmpz=lightz-(pointz[polyP2[i]]+logoz); d=Math.sqrt(tmpx*tmpx+tmpy*tmpy+tmpz*tmpz); tmpx/=d; tmpy/=d; tmpz/=d; d=Math.sqrt(normalx*normalx+ normaly*normaly+ normalz*normalz); normalx/=d; normaly/=d; normalz/=d; polyi[i]=tmpx*normalx+tmpy*normaly+tmpz*normalz; if (polyi[i]<0) polyi[i]=0; } else { polyi[i]=-1; } } } // I am taking advatage of the fact cubes do not intesect, so I only // sort thecubes (not inducidual polys), and backfaceculling on polys // removes the need to sort polys on each cube... int[] clist=new int[35]; // first create the cubelist sort array for(int i=0;i<35;i++) // initialise the array with an arbitary { // arrangement of cubes clist[i]=i; } j=1; // set the "keep sorting flag" to 1. I use bubble sort. while(j!=0) // whilst the list is still unsorted { // go thought each pair of cube z values, and if needed j=0; for(int i=0;i<34;i++) { if (cubez[clist[i]](waterz-(16*zoom))) logoy=(waterz-(16*zoom)); // keyframe if (t<0.03) // coords to the viewspace volume (infact less), so the { // logo doesnt go flying off into space out of view. logoposx[t5]+=((Math.random()*6)-3)*zoom; // modify a keyframe logoposy[t5]+=((Math.random()*6)-3)*zoom; // 5 frames ahead logoposz[t5]+=((Math.random()*6)-3)*zoom; // randomly if (logoposz[t5]<15) // limit to the view volume here logoposz[t5]=((Math.random()*185)+15)*zoom; if (logoposz[t5]>200) logoposz[t5]=((Math.random()*185)+15)*zoom; if (logoposx[t5]>(logoposz[t5]*((double)(width>>2)/focus))) logoposx[t5]=((Math.random()* (logoposz[t5]*((double)(width>>1)/focus))) -(logoposz[t5]*((double)(width>>2)/focus))); if (logoposx[t5]<-(logoposz[t5]*((double)(width>>2)/focus))) logoposx[t5]=((Math.random()* (logoposz[t5]*((double)(width>>1)/focus))) -(logoposz[t5]*((double)(width>>2)/focus))); if (logoposy[t5]<(waterz-(16*zoom))) logoposy[t5]=-((Math.random()* (logoposz[t5]*((double)(height>>2)/focus)))); if (logoposy[t5]>-(logoposz[t5]*((double)(height>>2)/focus))) logoposy[t5]=-((Math.random()* (logoposz[t5]*((double)(height>>2)/focus)))); } } // This method does EXACTLY what the above method does, except it does it // to the lightsource, and the lightsource is moved around the logo // randomly..... (when the user isn't moving it by hand) void MoveLight(double t) { int t1,t2,t3,t4,t5; double a,b,c; double aa,bb,cc; t1=(5+(int)(t-1))%5; t2=(5+(int)(t))%5; t3=(5+(int)(t+1))%5; t4=(5+(int)(t+2))%5; t5=(5+(int)(t+3))%5; t=t%1; cc=lightposx[t2]; bb=2*lightposx[t3]-3*cc/2-lightposx[t4]/2; aa=lightposx[t3]-cc-bb; c=lightposx[t2]; b=(lightposx[t3]-lightposx[t1])/2; a=lightposx[t3]-b-c; lightx=(1-t)*(a*t*t+b*t+c)+(t)*(aa*t*t+bb*t+cc); cc=lightposy[t2]; bb=2*lightposy[t3]-3*cc/2-lightposy[t4]/2; aa=lightposy[t3]-cc-bb; c=lightposy[t2]; b=(lightposy[t3]-lightposy[t1])/2; a=lightposy[t3]-b-c; lighty=(1-t)*(a*t*t+b*t+c)+(t)*(aa*t*t+bb*t+cc); cc=lightposz[t2]; bb=2*lightposz[t3]-3*cc/2-lightposz[t4]/2; aa=lightposz[t3]-cc-bb; c=lightposz[t2]; b=(lightposz[t3]-lightposz[t1])/2; a=lightposz[t3]-b-c; lightz=(1-t)*(a*t*t+b*t+c)+(t)*(aa*t*t+bb*t+cc); if (lighty>(waterz-zoom)) lighty=(waterz-zoom); if (t<0.03) { lightposx[t5]=logoposx[t5]+((Math.random()*50)-25)*zoom; lightposy[t5]=logoposy[t5]+((Math.random()*120)-115)*zoom; lightposz[t5]=logoposz[t5]+((Math.random()*50)-25)*zoom; } } // This merely flips all points and the light around the water plane // fordrawing the reflection of the cubes in the water.... void FlipPoints() { if (flipped>0) flipped=0; // toggle the flipped flag else flipped=1; for (int i=0;i<(35*8);i++) // flip all the points { pointy[i]=waterz-pointy[i]; } lighty=waterz-lighty;// flip the light } ////////////////////////////////////////////////////////////////////////////// // Methods to actually draw stuff to the buffer for final transferal to the // window. ////////////////////////////////////////////////////////////////////////////// // This merely copies the backgorund image into the buffer void DrawClear(Graphics g) { g.drawImage(background,0,0,this); } // This draws the cubes in their "upright" position, above the water void DrawCubes(Graphics g) { int j; boolean lightdrawn=false; // we havent drawn the light yet SortPolys(); // go sort the polys and work out lighting and culling int[] sx=new int[4]; // new array int[] sy=new int[4]; for(int i=(35*6)-1;i>-1;i--) // go thouggh all polys { j=polylist[i]; // find the poly tio draw from the sorted list if (!lightdrawn) // if the light hasnt been drawn { // and the light is furthur away than the 1st point in the if (lightz>(pointz[polyP1[j]]+logoz)) // poly (hack) { // becakse that's good enough for a small poly DrawLight(g); // draw the light glow (a hack) lightdrawn=true; // and flag it as done } } if (polyi[j]>=0) // if the poly is visible (facing camera) { // doa perspective transfrom of the XYZ to screen X&Y sx[0]=(width>>1)+(int)(((pointx[polyP1[j]]+logox)*focus)/ (pointz[polyP1[j]]+logoz)); sy[0]=(height>>1)+(int)(((pointy[polyP1[j]]+logoy)*focus)/ (pointz[polyP1[j]]+logoz)); sx[1]=(width>>1)+(int)(((pointx[polyP2[j]]+logox)*focus)/ (pointz[polyP2[j]]+logoz)); sy[1]=(height>>1)+(int)(((pointy[polyP2[j]]+logoy)*focus)/ (pointz[polyP2[j]]+logoz)); sx[2]=(width>>1)+(int)(((pointx[polyP3[j]]+logox)*focus)/ (pointz[polyP3[j]]+logoz)); sy[2]=(height>>1)+(int)(((pointy[polyP3[j]]+logoy)*focus)/ (pointz[polyP3[j]]+logoz)); sx[3]=(width>>1)+(int)(((pointx[polyP4[j]]+logox)*focus)/ (pointz[polyP4[j]]+logoz)); sy[3]=(height>>1)+(int)(((pointy[polyP4[j]]+logoy)*focus)/ (pointz[polyP4[j]]+logoz)); g.setColor(coltab // set the colour to the birghtness & col [(int)(polyi[j]*polyr[i])] [(int)(polyi[j]*polyg[i])] [(int)(polyi[j]*polyb[i])]); g.fillPolygon(sx,sy,4); // draw the poly } } // if we havent draw the light yet.. it's infront of everything if (!lightdrawn) // so draw it (seeing we're using painters algo) { DrawLight(g); } sx=null; // give a hint for garbage collection to collect sy=null; } // This is EXACTLY the same as above.. except it flips the polys, draws // and then flips them back again, and it doesnt draw the light glow void DrawReflectedCubes(Graphics g) { int j; FlipPoints(); SortPolys(); int[] sx=new int[4]; int[] sy=new int[4]; for(int i=(35*6)-1;i>-1;i--) { j=polylist[i]; if (polyi[j]>=0) { sx[0]=(width>>1)+(int)(((pointx[polyP1[j]]+logox)*focus)/ (pointz[polyP1[j]]+logoz)); sy[0]=(height>>1)+(int)(((pointy[polyP1[j]]-logoy)*focus)/ (pointz[polyP1[j]]+logoz)); sx[1]=(width>>1)+(int)(((pointx[polyP2[j]]+logox)*focus)/ (pointz[polyP2[j]]+logoz)); sy[1]=(height>>1)+(int)(((pointy[polyP2[j]]-logoy)*focus)/ (pointz[polyP2[j]]+logoz)); sx[2]=(width>>1)+(int)(((pointx[polyP3[j]]+logox)*focus)/ (pointz[polyP3[j]]+logoz)); sy[2]=(height>>1)+(int)(((pointy[polyP3[j]]-logoy)*focus)/ (pointz[polyP3[j]]+logoz)); sx[3]=(width>>1)+(int)(((pointx[polyP4[j]]+logox)*focus)/ (pointz[polyP4[j]]+logoz)); sy[3]=(height>>1)+(int)(((pointy[polyP4[j]]-logoy)*focus)/ (pointz[polyP4[j]]+logoz)); g.setColor(coltab [(int)(polyi[j]*10)] [(int)(polyi[j]*8)] [(int)(polyi[j]*6)]); g.fillPolygon(sx,sy,4); } } sx=null; sy=null; FlipPoints(); } // This is one of the more intersting. It takes all the polys and does // a quick hack at a projection on the water plane, and draws them all // in black. void DrawShadowCubes(Graphics g) { int j; int[] sx=new int[4]; int[] sy=new int[4]; double a1,a2,a3,a4; double b1,b2,b3,b4; double c1,c2,c3,c4; double d; // before I go anywhare.. we're now drawing in black g.setColor(coltab[0][0][0]); for(int i=(35*6)-1;i>-1;i--) // loop through all oplys { j=polylist[i]; // get the poly from the polylist a1=pointx[polyP1[j]]+logox; // get some temp variables b1=pointz[polyP1[j]]+logoz; c1=pointy[polyP1[j]]+logoy; a2=pointx[polyP2[j]]+logox; b2=pointz[polyP2[j]]+logoz; c2=pointy[polyP2[j]]+logoy; a3=pointx[polyP3[j]]+logox; b3=pointz[polyP3[j]]+logoz; c3=pointy[polyP3[j]]+logoy; a4=pointx[polyP4[j]]+logox; b4=pointz[polyP4[j]]+logoz; c4=pointy[polyP4[j]]+logoy; if ((c1>lighty)&&(c2>lighty)&&(c3>lighty)&&(c4>lighty)) // if the { // poly is completely below the lightsource, then project it d=(lightx-a1)/(c1-lighty); // do the actual projection a1=(c1-waterz)*d+a1; d=(lightz-b1)/(c1-lighty); b1=(c1-waterz)*d+b1; d=(lightx-a2)/(c2-lighty); a2=(c2-waterz)*d+a2; d=(lightz-b2)/(c2-lighty); b2=(c2-waterz)*d+b2; d=(lightx-a3)/(c3-lighty); a3=(c3-waterz)*d+a3; d=(lightz-b3)/(c3-lighty); b3=(c3-waterz)*d+b3; d=(lightx-a4)/(c4-lighty); a4=(c4-waterz)*d+a4; d=(lightz-b4)/(c4-lighty); b4=(c4-waterz)*d+b4; if ((b1>1)&&(b2>1)&&(b3>1)&&(b4>1)) // if the porjected poly { // is infront of the camera (by more than 1 unit) sx[0]=(width>>1)+(int)((a1*focus)/(b1)); // perspective sy[0]=(height>>1)+(int)((waterz*focus)/(b1)); // trans sx[1]=(width>>1)+(int)((a2*focus)/(b2)); // and draw it sy[1]=(height>>1)+(int)((waterz*focus)/(b2)); sx[2]=(width>>1)+(int)((a3*focus)/(b3)); sy[2]=(height>>1)+(int)((waterz*focus)/(b3)); sx[3]=(width>>1)+(int)((a4*focus)/(b4)); sy[3]=(height>>1)+(int)((waterz*focus)/(b4)); g.fillPolygon(sx,sy,4); // draw the poly } } } sx=null; // give the garbage collector a hint to go collect the trash sy=null; } // this draws the reflection of the light on the waer surface. // it's simple.. but works.. :-) void DrawLightReflection(Graphics g) { int sx,sy; double w=6*zoom,h=2*zoom; double a,b; if (lightz<1) return; sx=(width>>1)+(int)((lightx*focus)/(lightz)); sy=(height>>1)+(int)((waterz*focus)/(lightz)); w=(w*focus)/(lightz); h=(h*focus)/(lightz); for(int i=0;i<(int)((800-lightz)/16);i++) { // draw a shole bunch of lines around the source randomly g.setColor(coltab[10+((i*5)/50)] // in different colours [8+((i*7)/50)] [((i*15)/50)]); a=(Math.random()*w)-(w/2);b=(Math.random()*h)-(h/2); g.drawLine(sx-(int)(a),sy-(int)(b),sx+(int)(a),sy+(int)(b)); } } // this draws the light glow itself. same as above, just the glow isnt // vertically squashed void DrawLight(Graphics g) { int sx,sy; double w=6*zoom,h=6*zoom; double a,b; if (lightz<1) return; sx=(width>>1)+(int)((lightx*focus)/(lightz)); sy=(height>>1)+(int)((lighty*focus)/(lightz)); w=(w*focus)/(lightz); h=(h*focus)/(lightz); for(int i=0;i<(int)((3200-lightz)/32);i++) { g.setColor(coltab[10+((i*5)/100)] [8+((i*7)/100)] [((i*15)/100)]); a=(Math.random()*w)-(w/2);b=(Math.random()*h)-(h/2); g.drawLine(sx-(int)(a),sy-(int)(b),sx+(int)(a),sy+(int)(b)); } } // Ahh.. famous rippling hack method... I'm just going a lot fo area copying // fast, cheap but effective. usign this, in conjuction with the background // image limits me to keeping the camera fixed..... void DrawRipples(Graphics g) { int yoffset; yoffset=height/2; for(int y=0;y>1); // adjust the x & y y-=(height>>1); lightx=(double)x*(lightz/focus); // get the new light x& y lighty=(double)y*(lightz/focus); // by projecting the screen x&y onto if (lighty>=waterz) lighty=waterz; // the current z light plane return true; // it does have bugs if lightz<0.. bit me :-) } // same as above.. keep tracking that mouse and creeatig new lightx&y public boolean mouseDrag(Event e, int x, int y) { x-=(width>>1); y-=(height>>1); lightx=(double)x*(lightz/focus); lighty=(double)y*(lightz/focus); if (lighty>=waterz) lighty=waterz; return true; } // thwe mouse is raised.... public boolean mouseUp(Event e, int x, int y) { // now set the 2 keyframes either side of where we were in the frame int t1,t2; // anim to the current x,y&z values of the light. // as a result the light will hover there for a bit, then get on with t1=((int)tf)%5; // moving on its merry way again. This isn't perfect. t2=((int)tf+1)%5; // it has minor bugs.. i should set more keyframes lightposx[t1]=lightx; // either side to these coords... but yet again lightposy[t1]=lighty; // diddums! bite me! :-) lightposz[t1]=lightz; lightposx[t2]=lightx; lightposy[t2]=lighty; lightposz[t2]=lightz; lmove=false; return true; } ////////////////////////////////////////////////////////////////////////////// // The actual method that gets things moving in the applet. ////////////////////////////////////////////////////////////////////////////// // The main method that is called after init & start. public void run() { MediaTracker tracker; // media tracker for tracking image loading Dimension d = this.size(); // get the window dimensions width=d.width; // record the window widht & height's in nicer globals height=d.height; Graphics gthis; // some graphics contexts.. this for the window Graphics gbuff; // and buff for the double buffered image int count=0; // framecount.. every 512 frames i will pause for a bit if (buffer==null) buffer=this.createImage(width,height); // if the // double buffer doesnt exist.. create it. if (background==null) // if the bg image doesnt exist { // load the image from the current dir/docbase background=this.getImage(this.getDocumentBase(),"bg.gif"); tracker = new MediaTracker(this); // track the loading tracker.addImage(background, 1); // add the image to the tracking if(tracker != null) // if the tracker loaded up okay { try {tracker.waitForID(1);} // wait for the image to load catch (InterruptedException e){;} if (tracker.isErrorID(1)) // if there was an error loading { background = null; // wipe the background image } } } gbuff = buffer.getGraphics(); gthis = this.getGraphics(); try {Thread.sleep(1000);} // wait for 1 second for things to settle down catch (InterruptedException e){;} tf=0; // set our keyframe counter tf to the 0'th one for(;;) // The infinite display loop { if(!lmove) MoveLight(tf); // move the light via curve path MoveLogo(tf+=0.03); // move the logo via square curve path via // "key frames"... and modify a key randomly if (tf>10) tf=0; // if w're pask key frame 10, start at 0 again RotateLogo(0.02,0.01,0.03); // Rotate the logo a bit DrawClear(gbuff); // Clear the buffer with the background image DrawLightReflection(gbuff); // Draw the lights reflection DrawShadowCubes(gbuff); // Draw the cube shadows DrawReflectedCubes(gbuff); // Draw the cubes Reflected in watar DrawRipples(gbuff); // Ripple the water surface DrawCubes(gbuff); // Draw the flying cube logo gthis.drawImage(buffer,0,0,this); // Copy image buffer to window try {Thread.sleep(20);}// seelp for 20ms catch (InterruptedException e){;} count ++; // increment out frame count if (count==512) // if we have reached 512 frames... { // we will pause for 1 second. thsi is to allow java to count=0; // garbae collect. if i don't do this it has try {Thread.sleep(1000);} // sucha bad memory leak it can catch (InterruptedException e){;} // eat through 200k/sec! } // so pasue for 1 second to allow garbage collection to } // catch up!.. bloody java! I'd expect better! } }