import java.applet.*; import java.awt.*; import java.io.*; import java.net.*; import java.awt.event.*; import java.lang.*; public class TriMatTest extends Applet implements MouseListener, MouseMotionListener { static int CHUNKSIZE = 100; static int CLIPFAC = 5; Raster raster; Image screen; Buffer buffer; int vertices; Vertex3D vertList[]; Triangle3D triList[]; Triangle3D viewList[]; Triangle3D frontList[]; Triangle3D projList[]; Triangle3D clipList[]; Triangle3D scrList[]; int axesVtcs; Matrix3D axesView; Point3D axesList[]; Point3D tranAxesList[]; int triangles; int frontTris; int clipTris; float state = 0; float near = -1; float far = -200; Matrix3D eyeMod; Matrix3D prj; Matrix3D scr; float eyex, eyey, eyez; float lookatx, lookaty, lookatz; float upx, upy, upz; float initEyex, initEyey, initEyez; float initLookatx, initLookaty, initLookatz; float fov; Light lightList[]; int lights; Surface surfaceList[]; int surfaces; public void init( ) { raster = new Raster(getSize().width, getSize().height); buffer = new Buffer(getSize().width, getSize().height); raster.fill(getBackground()); screen = raster.toImage(this); this.addMouseListener(this); this.addMouseMotionListener(this); eyex = 0; eyey = 0; eyez = -10; lookatx = 0; lookaty = 0; lookatz = 0; upx = 0; upy = 1; upz = 0; fov = 30; lightList = new Light[CHUNKSIZE]; lights = 0; surfaceList = new Surface[CHUNKSIZE]; surfaces = 0; axesList = new Point3D[CHUNKSIZE]; axesVtcs = 0; vertList = new Vertex3D[CHUNKSIZE]; vertices = 0; triList = new Triangle3D[CHUNKSIZE]; triangles= 0; String filename = getParameter("datafile"); showStatus("Reading "+filename); InputStream is = null; try { is = new URL(getDocumentBase(), filename).openStream(); ReadInput(is); is.close(); } catch (IOException e) { showStatus("Error reading "+filename); } initEyex=eyex; initEyey=eyey; initEyez=eyez; initLookatx=lookatx; initLookaty=lookaty; initLookatz=lookatz; showStatus(" triangles " +triangles ); // for( int i=0; i 1) { pix = (int) Long.parseLong(st.sval.substring(1), 8); } else pix = Integer.parseInt(st.sval); return pix; } // // extend the triangle array if needed private void growList() { // Drawable newList[] = new Drawable[triList.length+CHUNKSIZE]; Triangle3D newList[] = new Triangle3D[triList.length+CHUNKSIZE]; System.arraycopy(triList, 0, newList, 0, triList.length); triList = newList; CHUNKSIZE = (3*CHUNKSIZE)/2; } public void ReadInput(InputStream is) throws IOException { // System.out.println(" READING INPUT" ); Reader rdr = new BufferedReader(new InputStreamReader(is)); StreamTokenizer st = new StreamTokenizer(rdr); configureParser(st); scan: while (true) { switch (st.nextToken()) { default: break scan; case StreamTokenizer.TT_WORD: if (st.sval.equals("c")) { float x = (float) getNumber(st); float y = (float) getNumber(st); float z = (float) getNumber(st); //int clr = getColor(st); int clr = (int) getNumber(st) ; if (axesVtcs == axesList.length) { Point3D newList[] = new Point3D[axesList.length+CHUNKSIZE]; System.arraycopy(axesList, 0, newList, 0, axesList.length); axesList = newList; } axesList[axesVtcs++] = new Point3D(x, y, z, 1, clr); } else if (st.sval.equals("v")) { // System.out.println(" READING VERTICES" ); float x = (float) getNumber(st); float y = (float) getNumber(st); float z = (float) getNumber(st); if (vertices == vertList.length) { Vertex3D newList[] = new Vertex3D[vertList.length+CHUNKSIZE]; System.arraycopy(vertList, 0, newList, 0, vertList.length); vertList = newList; } // System.out.println(" vertices " +vertices ); vertList[vertices++] = new Vertex3D(x, y, z, 1); } else if (st.sval.equals("f")) { // System.out.println(" READING FACES" ); int faceTris = 0; int v0 = (int) getNumber(st); int v1 = (int) getNumber(st); while (st.nextToken() == StreamTokenizer.TT_NUMBER) { st.pushBack(); int v2 = (int) getNumber(st); if (v2 == v0) continue; if (triangles == triList.length) growList(); // VERTICES IN VERLIST NUMBERED FROM 0 ONWARDS // System.out.println(" triangles " +triangles ); triList[triangles] = new Triangle3D(vertList[v0], vertList[v1], vertList[v2]); if (surfaces == 0) { surfaceList[surfaces] = new Surface(0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 5.0f); surfaces++; } // System.out.println(" IN TRI SETsurfaces " + surfaces ); triList[triangles].setSurface(surfaceList[surfaces-1]); // triList[triangles].printSurface(); v1 = v2; faceTris +=1; triangles +=1; } st.pushBack(); } else if (st.sval.equals("la")) { // ambient light source float r = (float) getNumber(st); float g = (float) getNumber(st); float b = (float) getNumber(st); lightList[lights] = new Light(Light.AMBIENT, 0, 0, 0, r, g, b); lights += 1; } else if (st.sval.equals("ld")) { // directional light source float r = (float) getNumber(st); float g = (float) getNumber(st); float b = (float) getNumber(st); float x = (float) getNumber(st); float y = (float) getNumber(st); float z = (float) getNumber(st); lightList[lights] = new Light(Light.DIRECTIONAL, x, y, z, r, g, b); lights += 1; } else if (st.sval.equals("lp")) { // point light source float r = (float) getNumber(st); float g = (float) getNumber(st); float b = (float) getNumber(st); float x = (float) getNumber(st); float y = (float) getNumber(st); float z = (float) getNumber(st); lightList[lights] = new Light(Light.POINT, x, y, z, r, g, b); lights += 1; } else if (st.sval.equals("surf")) { // System.out.println(" READING SURFACES" ); float r = (float) getNumber(st); float g = (float) getNumber(st); float b = (float) getNumber(st); float ka = (float) getNumber(st); float kd = (float) getNumber(st); float ks = (float) getNumber(st); float ns = (float) getNumber(st); // System.out.println("IN SETTING SURF surfaces " + surfaces ); surfaceList[surfaces] = new Surface(r, g, b, ka, kd, ks, ns); surfaces += 1; } else if (st.sval.equals("eye")) { eyex = (float) getNumber(st); eyey = (float) getNumber(st); eyez = (float) getNumber(st); } else if (st.sval.equals("look")) { lookatx = (float) getNumber(st); lookaty = (float) getNumber(st); lookatz = (float) getNumber(st); } else if (st.sval.equals("up")) { upx = (float) getNumber(st); upy = (float) getNumber(st); upz = (float) getNumber(st); } else if (st.sval.equals("fov")) { fov = (float) getNumber(st); } else { System.err.println("ERROR: line "+st.lineno()+": unexpected token :"+st.sval); break scan; } break; } //if (vertices % 100 == 0)showStatus("vertices = " + (vertices+1)); showStatus("triangles = " + triangles); } is.close(); if (st.ttype != StreamTokenizer.TT_EOF) { throw new IOException(st.toString()); } } public void paint(Graphics g) { g.drawImage(screen, 0, 0, this); } public void update(Graphics g) { paint(g); } int oldx, oldy; // public void mousePressed( MouseEvent e){;} public void mousePressed( MouseEvent e ) { System.out.println("IN MOUSE PRESSED"); int x=e.getX(); int y=e.getY(); if (e.isMetaDown()) { System.out.println("Reset eyeMod matrix"); eyex=initEyex; eyey=initEyey; eyez=initEyez; lookatx=initLookatx; lookaty=initLookaty; lookatz=initLookatz; eyeMod.loadIdentity(); //NO CHANGE TO UP - CAN FAIL HERE!! eyeMod.lookAt(eyex, eyey, eyez, lookatx, lookaty, lookatz, upx, upy, upz); prj.loadIdentity(); float t = (float) Math.sin(Math.PI*(fov/2)/180); float s = (t*getSize().height)/getSize().width; prj.perspective(-t, t, -s, s, near, far); axesView.toOriginalMat(); axesView.perspective(-t, t, -s, s, near, far); axesView.lookAt(eyex, eyey, eyez, lookatx, lookaty, lookatz, upx, upy, upz); drawObject(); repaint(); } oldx = x; oldy = y; return ; } public void mouseMoved( MouseEvent e ) { ; } public void mouseReleased( MouseEvent e ) { ; } public void mouseEntered( MouseEvent e ) { ; } public void mouseExited( MouseEvent e ) { ;} public void mouseClicked( MouseEvent e ) { ; } //public void mouseDragged( MouseEvent e) { ; } // public void mousePressed( MouseEvent e) // { // System.out.println("IN MOUSE DRAGGED"); // eyeMod.loadIdentity(); // eyex = 10 + (float)( 5*Math.sin(Math.PI/4*state )); // eyey = 10; // eyez = 10+ (float)(5*Math.cos(Math.PI/4*state)); // eyeMod.lookAt(eyex, eyey, eyez, lookatx, lookaty, lookatz, upx, upy, upz); // float t = (float) Math.sin(Math.PI*(fov/2)/180); // float s = (t*getSize().height)/getSize().width; // prj.loadIdentity(); // prj.perspective(-t, t, -s, s, near, far); // axesView.toOriginalMat(); // axesView.perspective(-t, t, -s, s, near, far); // axesView.lookAt(eyex, eyey, eyez, lookatx, lookaty, lookatz, upx, upy, upz); // state ++; // drawObject(); // repaint(); // return ; // } public void mouseDragged( MouseEvent e) { System.out.println("IN MOUSE DRAGGED"); int x=e.getX(); int y=e.getY(); if (e.isMetaDown()) { System.out.println("Resetting eyeMod matrix"); } else { float ax = lookatx - eyex; float ay = lookaty - eyey; float az = lookatz - eyez; float t = (float) (getSize().width / (2*Math.tan(((fov * Math.PI)/180)/2))); Matrix3D r = new Matrix3D( ); t = (float) (Math.atan((double)(x - oldx)/t)); r.rotate(upx, upy, upz, t); eyex = eyex + ax*(oldy - y)/getSize().height; eyey = eyey + ay*(oldy - y)/getSize().height; eyez = eyez + az*(oldy - y)/getSize().height; lookatx = r.getElem(0,0)*ax + r.getElem(1,0)*ay + r.getElem(2,0)*az; lookaty = r.getElem(0,1)*ax + r.getElem(1,1)*ay + r.getElem(2,1)*az; lookatz = r.getElem(0,2)*ax + r.getElem(1,2)*ay + r.getElem(2,2)*az; lookatx += eyex; lookaty += eyey; lookatz += eyez; eyeMod.loadIdentity(); eyeMod.lookAt(eyex, eyey, eyez, lookatx, lookaty, lookatz, upx, upy, upz); t = (float) Math.sin(Math.PI*(fov/2)/180); float s = (t*getSize().height)/getSize().width; prj.loadIdentity(); prj.perspective(-t, t, -s, s, near, far); axesView.toOriginalMat(); axesView.perspective(-t, t, -s, s, near, far); axesView.lookAt(eyex, eyey, eyez, lookatx, lookaty, lookatz, upx, upy, upz); oldx = x; oldy = y; drawObject(); repaint(); } return ; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// // public void setViewLine(float eyex,float eyey, float eyez, float lookatx, float lookaty, float lookatz, float upx, float upy, float upz) { // prj.lookAt(eyex, eyey, eyez, lookatx, lookaty, lookatz, upx, upy, upz); // axesView.setTo( scrPrj ); // axesView.transform(axesList, tranAxesList, 0, axesVtcs); // } void drawObject( ) { tranAxesList = new Point3D[axesList.length]; for (int i = 0; i < axesVtcs; i++) tranAxesList[i] = new Point3D(); axesView.transform(axesList, tranAxesList, 0, axesVtcs); viewList = new Triangle3D[ triangles ]; eyeMod.transform( triList, viewList, 0, triangles); // for( int i=0; i< triangles; i++ ) { // System.out.println(" PRINTING VIEWLIST " + i); // viewList[i].printVertices(); // // viewList[i].printColorInterpol(); // } frontList = new Triangle3D[ triangles]; showStatus("Backface Culling..."); frontTris = backFaceCull( viewList, frontList, 0, triangles ); //NOTE: frontList.length= triangles but only frontTris have allocated memory // for( int i=0; i< frontTris; i++ ) { // System.out.println(" PRINTING FRONTLIST " + i); // frontList[i].printVertices(); // // frontList[i].printColorInterpol(); // } showStatus("Illuminating..."); for( int i=0; i< frontTris; i++ ) { showStatus(" Illuminating triangle " + i); frontList[i].illuminate( lightList, lights ); // frontList[i].printColorInterpol(); } // for( int i=0; i< frontTris; i++ ) { // System.out.println(" PRINTING ILLUMINATED FRONTLIST " + i); // frontList[i].printVertices(); // // frontList[i].printColorInterpol(); // } clipList = new Triangle3D[ CLIPFAC * frontTris]; showStatus("Clipping hither and yon..."); clipTris = clip( frontList, clipList, 0, frontTris, near, far ); // System.out.println(" BACK IN TRIMATTEST.JAVA" ); // for( int i=0; i < clipTris; i++ ) { // System.out.println(" PRINTING CLIPLIST " + i); // clipList[i].printVertices(); // // clipList[i].printColorInterpol(); // } if( clipTris>0) { projList = new Triangle3D[ clipTris ]; showStatus("Canonical-Projecting triangles..."); prj.transform( clipList, projList, 0, clipTris); // for( int i=0; i< clipTris; i++ ) { // System.out.println(" PRINTING PROJLIST " + i); // projList[i].printVertices(); // // projList[i].printColorInterpol(); // } // PROJ NEEDS TO BE DEHOMOGIZED BECAUSE THE SCREEN TRANSFORMATION ASSUMES THAT THE POINTS // ARE IN A CANONICAL CUBE for( int i=0; i < clipTris; i++ ) { projList[i].deHomogenize(); } // for( int i=0; i< clipTris; i++ ) { // System.out.println(" PRINTING PROJLISTDEHOMO " + i); // projList[i].printVertices(); // // projList[i].printColorInterpol(); // } scr = new Matrix3D(raster); scrList = new Triangle3D[ clipTris]; // System.out.println(" PRINTING SCR "); // scr.printCompMat(); showStatus("Displaying triangles..."); scr.transform( projList, scrList, 0, clipTris); // THIS DEHOMOGIZATION NOT NECESSARY BECAUSE PROJLIST IS ALREADY IN DEHOMOG FORMAT for( int i=0; i < clipTris; i++ ) { scrList[i].deHomogenize(); } // for( int i=0; i < clipTris; i++ ) { // System.out.println(" PRINTING SCRLIST " + i); // scrList[i].printVertices(); // // scrList[i].printColorInterpol(); // } }else { showStatus(" Zero triangles to be rendered "); } buffer.initZ(); renderScene( clipTris, scrList ); screen = raster.toImage(this); // DELETE ALL TRIANGLE LISTS NOW }//DRAWOBJECT void renderScene( int nTris, Triangle3D[] all ){ int ix, iy; float iz, iw; int w, h; w = raster.getWidth(); h = raster.getHeight(); raster.fill(getBackground()); for (int i = 0; i < axesVtcs; i++) { if( tranAxesList[i].getCoord(3) !=0){ ix = (int) (tranAxesList[i].getCoord(0) / tranAxesList[i].getCoord(3)); iy = (int) (tranAxesList[i].getCoord(1) / tranAxesList[i].getCoord(3)); iz = tranAxesList[i].getCoord(2) /tranAxesList[i].getCoord(3) ; iw = tranAxesList[i].getCoord(3) /tranAxesList[i].getCoord(3) ; if (ix >= 0 && iy >= 0 && ix < w && iy < h){ raster.setPixel(axesList[i].getColor(), ix, iy); } } } if( nTris>0) { for( int i=0; i < nTris; i++ ) { showStatus("Rasterizing triangle " + i); all[i].draw(raster, buffer); } } else { showStatus(" ERROR: Zero triangles to be rendered "); } }//RENDERSCENE public int backFaceCull( Triangle3D[] all, Triangle3D[] front, int start, int length ) { int frontTris=0; for( int t=start; t<(start+length); t++ ) { Vector3D normToTri = new Vector3D(); all[t].getNormal( normToTri ); if( normToTri.getV(2) >= 0 ){ //all[t].triangleSetup(); front[ frontTris ] = new Triangle3D( all[t].getVtx3D(0), all[t].getVtx3D(1), all[t].getVtx3D(2) ); front[frontTris].setSurface( all[t].getSurface() ); front[frontTris].setFlatColor( all[t].getFlatColor() ); frontTris++; } else { showStatus("Culling triangle " + t); } } //FOR T return frontTris; }//BACKFACE CULL public int clip( Triangle3D[] all, Triangle3D[] clipList, int start, int length, float near, float far ) { // System.out.println("IN TRIMATTESTCLIP" ); // INCLUDE DE-HOMOGENIZING OF ALL HERE int clipTris = 0; int iClipTris; Plane3D[] H = new Plane3D[2]; //POINTS INSIDE THE PLANE ARE IN POSITIVE HALFPLANES H[0] = new Plane3D( 0, 0, -1, near); H[1] = new Plane3D( 0, 0, 1, -far); // System.out.println("Printing Planes" ); // H[0].print(); // H[1].print(); for( int t=start; t<(start+length); t++ ) { showStatus("clipping triangle " + t ); iClipTris= all[t].clipTri3D( clipList, clipTris, H, 2, CLIPFAC ); for( int i=0; i x) ) { ltBreak = vtxSortY[1]; return; } if( (vtxSortY[1] !=vtxSortX[0])&&(edge[vtxSortY[1]].findXAtGivenY(y) < x ) ) { rtBreak = vtxSortY[1]; return; } return; } //ISNOBREAKPOINT //this will always return first the edge closer to x=0 and then the one further away public void getActiveEdges( ) { //System.out.println("IN GETACTIVEEDGES(void)" ); if( noseNegY >= 0 ) { activeEdge[0] = getEdgeNo( noseNegY+1 ); activeEdge[1] = getEdgeNo( noseNegY-1 ); return; } if( nosePosY >= 0 ) { activeEdge[0] = getEdgeNo( nosePosY-1 ); activeEdge[1] = getEdgeNo( nosePosY+1 ); return; } return; }//GETACTIVEEDGES //this will always return first the edge closer to x=0 and then the one further away public void getActiveEdges( boolean isBeforeBreak) { //System.out.println("IN GETACTIVEEDGES(isBeforeBreak)" ); if( ltBreak >= 0) { if( isBeforeBreak ) { activeEdge[0] = getEdgeNo( ltBreak-1 ); activeEdge[1] = getEdgeNo( ltBreak ); } else { activeEdge[0] = getEdgeNo( ltBreak+1 ); activeEdge[1] = getEdgeNo( ltBreak ); } return; } if( rtBreak >= 0) { if( isBeforeBreak ) { activeEdge[0] = getEdgeNo( rtBreak ); activeEdge[1] = getEdgeNo( rtBreak+1 ); } else { activeEdge[0] = getEdgeNo( rtBreak ); activeEdge[1] = getEdgeNo( rtBreak-1 ); } return; } return; }//GETACTIVEEDGES //returns edge number between 0 and 2, irrespective of "int someNo" public int getEdgeNo( int someNo ){ if( someNo >= 3 ) return( getEdgeNo(someNo-3) ); if( someNo < 0 ) return( getEdgeNo(someNo+3) ); return someNo; } public int getVertexNo(int someNo ){ if( someNo >= 3 ) return( getVertexNo(someNo-3) ); if( someNo < 0 ) return( getVertexNo(someNo+3) ); return someNo; } /* Accounts for vertex nos not 0,1,2 */ public Vertex3D getVtx3D(int someNo ){ return v[getVertexNo(someNo)]; } //*********************************************************************// public void draw( Raster r) { //System.out.println("IN TRIANGLE3D.DRAW" ); /** TRIANGLE HAS TO BE SET UP BEFORE ANY MAJOR FUNCTIONS LIKE DRAWING, CLIPPING */ this.triangleSetup( ); if( noseNegY >= 0){ getActiveEdges(); drawSpan( activeEdge, v[ getVertexNo(noseNegY) ], v[ getVertexNo(noseNegY-1) ], r ); } if( nosePosY >= 0){ getActiveEdges(); drawSpan( activeEdge, v[ getVertexNo(nosePosY+1) ], v[ getVertexNo(nosePosY) ], r ); } if( ltBreak >= 0){ getActiveEdges(true); drawSpan( activeEdge, v[ getVertexNo(ltBreak+1) ], v[ getVertexNo(ltBreak) ], r ); getActiveEdges(false); drawSpan( activeEdge, v[ getVertexNo(ltBreak) ], v[ getVertexNo(ltBreak-1) ], r ); } if( rtBreak >= 0){ getActiveEdges(true); drawSpan( activeEdge, v[ getVertexNo(rtBreak-1) ], v[ getVertexNo(rtBreak) ], r ); getActiveEdges(false); drawSpan( activeEdge, v[ getVertexNo(rtBreak) ], v[ getVertexNo(rtBreak+1) ], r ); } }//DRAW // interface methods public void drawLine( Raster r ){;} public void drawLine( Raster r, float[] alpha, float[] red, float[] green, float[] blue) {;} protected void drawSpan( int[] aE, Vertex3D vStart, Vertex3D vFinish, Raster r) { //System.out.println("IN TRIANGLE.DRAWSPAN......" ); int h = r.getHeight(); int w = r.getWidth(); int pix; int aE0 = aE[0]; int aE1 = aE[1]; //System.out.println( " aE0=" + aE0 +" aE1=" + aE1 ); int x, y; y = (int)(vStart.getCoord(1)+0.5); int yFinish = (int)(vFinish.getCoord(1)+0.5); //System.out.println( " yStart=" + y +" yFinish=" + yFinish ); while( y <= yFinish ) { int xFloor = (int)( -( (edge[aE0].getC()+(edge[aE0].getB() *(float)y) )/ (edge[aE0].getA()) ) + 0.5 ); int xCeil = (int)( -( (edge[aE1].getC()+(edge[aE1].getB() *(float)y) )/ (edge[aE1].getA()) ) ); //System.out.println( " y=" + y +"*************" ); //System.out.println( "xFloor =" + xFloor +"xCeil =" + xCeil ); for( x=xFloor; x<=xCeil; x++ ) { //System.out.println( " x=" + x ); pix = flatClr; //CHANGE THIS AFTER INTERPOLATION // System.out.println( " pix=" + pix +"*************" ); if (x >= 0 && y >= 0 && x < w && y < h){ r.setPixel( pix, x, y); } } y++; } }//DRAWSPAN //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!// public void draw( Raster r, Buffer buf) { this.triangleSetup(); if( noseNegY >= 0){ getActiveEdges(); drawSpan( activeEdge, v[ getVertexNo(noseNegY) ], v[ getVertexNo(noseNegY-1) ], r, buf ); } if( nosePosY >= 0){ getActiveEdges(); drawSpan( activeEdge, v[ getVertexNo(nosePosY+1) ], v[ getVertexNo(nosePosY) ], r, buf ); } if( ltBreak >= 0){ getActiveEdges(true); drawSpan( activeEdge, v[ getVertexNo(ltBreak+1) ], v[ getVertexNo(ltBreak) ], r, buf ); getActiveEdges(false); drawSpan( activeEdge, v[ getVertexNo(ltBreak) ], v[ getVertexNo(ltBreak-1) ], r, buf ); } if( rtBreak >= 0){ getActiveEdges(true); drawSpan( activeEdge, v[ getVertexNo(rtBreak-1) ], v[ getVertexNo(rtBreak) ], r, buf ); getActiveEdges(false); drawSpan( activeEdge, v[ getVertexNo(rtBreak) ], v[ getVertexNo(rtBreak+1) ], r, buf ); } }//DRAW protected void drawSpan( int[] aE, Vertex3D vStart, Vertex3D vFinish, Raster r, Buffer buf) { // System.out.println("IN INTERPOLATEDTRIANGLE.DRAWSPAN......" ); int pix; float z; int h = r.getHeight(); int w = r.getWidth(); // System.out.println( " w=" + w +" h=" + h ); int aE0 = aE[0]; int aE1 = aE[1]; // System.out.println( " ae0=" + aE0 +" aE1=" + aE1 ); int x, y; y = (int)(vStart.getCoord(1)+0.5); int yFinish = (int)(vFinish.getCoord(1)+0.5); // System.out.println( " yStart=" + y +" yFinish=" + yFinish ); while( y <= yFinish ) { int xFloor = (int)( -( (edge[aE0].getC()+(edge[aE0].getB() *(float)y) )/ (edge[aE0].getA()) ) + 0.5 ); int xCeil = (int)( -( (edge[aE1].getC()+(edge[aE1].getB() *(float)y) )/ (edge[aE1].getA()) ) ); //System.out.println( " y=" + y +"*************" ); //System.out.println( "xFloor =" + xFloor +"xCeil =" + xCeil ); for( x=xFloor; x<=xCeil; x++ ) { //System.out.println( "x =" + x ); z = this.getZBuf(x, y); if (x >= 0 && y >= 0 && x < w && y < h){ if( buf.getZBuf(x, y) >= z ) { pix = flatClr; //System.out.println( " x=" + x +" y=" + y + " pix=" + pix ); r.setPixel( pix, x, y); buf.setZBuf( z, x, y ); } } } y++; } }//DRAWSPAN protected float getZBuf( int x, int y) { return (zEqn[0]*x + zEqn[1]*y + zEqn[2] ); } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!// protected void planeEqn(float eqn[], int p0, int p1, int p2){ //System.out.println("IN PLANE EQN" ); float Ap, Bp, Cp; if (scale <= 0) { scale = (double)1. / ((double) twiceArea); } double sp0 = scale * p0; double sp1 = scale * p1; double sp2 = scale * p2; Ap = (float)(edge[2].getA()*sp2 + edge[0].getA()*sp0 + edge[1].getA()*sp1); Bp = (float)(edge[2].getB()*sp2 + edge[0].getB()*sp0 + edge[1].getB()*sp1); Cp = (float)(edge[2].getC()*sp2 + edge[0].getC()*sp0 + edge[1].getC()*sp1); eqn[0] = Ap; eqn[1] = Bp; eqn[2] = Cp; return; }//PLANEEQN protected void planeEqn(float eqn[], float p0, float p1, float p2){ //System.out.println("IN PLANE EQN" ); float Ap, Bp, Cp; if (scale <= 0) { scale = (double)1. / ((double) twiceArea); } double sp0 = scale * p0; double sp1 = scale * p1; double sp2 = scale * p2; Ap = (float)(edge[2].getA()*sp2 + edge[0].getA()*sp0 + edge[1].getA()*sp1); Bp = (float)(edge[2].getB()*sp2 + edge[0].getB()*sp0 + edge[1].getB()*sp1); Cp = (float)(edge[2].getC()*sp2 + edge[0].getC()*sp0 + edge[1].getC()*sp1); eqn[0] = Ap; eqn[1] = Bp; eqn[2] = Cp; return; }//PLANEEQN //*********************************************************************/ public void getNormal( Vector3D normal ) { Vector3D edge2 = new Vector3D(( this.v[1].getCoord(0) - this.v[0].getCoord(0) ), ( this.v[1].getCoord(1) - this.v[0].getCoord(1) ), ( this.v[1].getCoord(2) - this.v[0].getCoord(2) ) ); Vector3D edge0 = new Vector3D(( this.v[2].getCoord(0) - this.v[1].getCoord(0) ), ( this.v[2].getCoord(1) - this.v[1].getCoord(1) ), ( this.v[2].getCoord(2) - this.v[1].getCoord(2) ) ); edge2.crossProd( edge0, normal ); normal.normalize(); } public void setSurface( Surface surf ) { surface = surf; //THIS IS A POINTER hasSurface = true; } public Surface getSurface( ) { return surface; } public void printSurface() { System.out.println(" PRINTING SURFACE" ); System.out.println(" r= " + surface.getClrFac(0)+ " g= " + surface.getClrFac(1) + " b= " + surface.getClrFac(2) ); System.out.println(" ka= " + surface.getKa() +" kd= " + surface.getKd() + " ks= " + surface.getKs() + " ns= " + surface.getNs() ); } void illuminate( Light[] ltList, int nLights ) { // for( int i=0; i0) { for( int i=0; i< length; i++) { ary[i] /=fac; } } else System.err.println("ERROR:Triangle3D.scaleToRGBCube: fac not>0 "); } protected void scaleClrFac( float[] ary, int length){ boolean repeat = false; for( int i=0; i< length; i++) { if(ary[i]>1) repeat=true; } if(repeat){ for( int i=0; i< length; i++){ if(ary[i]>1) ary[i] -= 1; } scaleClrFac( ary, length ); } else return; } protected void arrange( float[] ary, int length){ for( int i=1; i< length; i++) { for( int j=0; j< i; j++) { if( ary[i] 0) { Vertex3D[] outVtx = new Vertex3D[CLIPFAC]; // System.out.println("CLIPPING AGAINS PLANE = " + i ); // for( int j=0; j0) { s = in[ inLength-1]; for( int j=0; j0) )||( (normDist0>0)&&(normDist1<0) ) ) { res.setCoord(0, (v0.getCoord(0) + fac*( v1.getCoord(0) - v0.getCoord(0) ) ) ); res.setCoord(1, (v0.getCoord(1) + fac*( v1.getCoord(1) - v0.getCoord(1) ) ) ); res.setCoord(2, (v0.getCoord(2) + fac*( v1.getCoord(2) - v0.getCoord(2) ) ) ); res.setCoord(3, 1 ); // System.out.println("res.getCoord0="+ res.getCoord(0)+"res.getCoord1="+ res.getCoord(1) ); // System.out.println("res.color=" + this.setColor(res.getCoord(0),res.getCoord(1)) ); // SINCE RES.W = 1, RES.X AND RES.Y CAN BE DIRECTLY INPUT TO THIS.SETCOLOR(X,Y) res.setColor( flatClr ); } else { System.err.println("ERROR: Triangle3D.intersect(): line and plane do not intersect OR line is on plane" ); } } //INTERSECT /** =0 DOESNOT MAKE SENSE FOR FLOATS */ protected boolean isInside( Vertex3D v, Plane3D H ) { if((H.dot(v)>0)||(!isNotZero(H.dot(v)))) return true; else return false; } //***********************************************************************// protected boolean isNotZero( float f ) { if ( Math.abs(f) >= (1>>FRACBITS) ) return true; else return false; } protected boolean isPosZero( float f ) { if ( (f>0)&&( Math.abs(f) < (1>>FRACBITS)) ) return true; else return false; } protected boolean isNegZero( float f ) { if ( (f<0)&&( Math.abs(f) < (1>>FRACBITS)) ) return true; else return false; } public boolean isPointInside(float x, float y) { int flag = 0; for( int i=0; i<3; i++ ) { if( edge[i].evaluateAt(x,y)>=0 ) flag+=1; } if( flag==3 ) return true; else return false; } public void printVertices() { for( int i=0; i<3; i++ ) { System.out.println(" Vertex no.= " + i ); System.out.println(" x= " + v[i].getCoord(0)+ " y= " + v[i].getCoord(1) + " z= " + v[i].getCoord(2) + " w= " + v[i].getCoord(3)+ " color= " + v[i].getColor() ); } } public void deHomogenize() { for( int i=0; i<3; i++ ) { if( isNotZero(v[i].getCoord(3)) ){ for( int j=0; j<4; j++ ) { v[i].setCoord( j, (v[i].getCoord(j) / v[i].getCoord(3)) ); } } if( isPosZero(v[i].getCoord(3)) ){ System.err.println( "WARNING: Triangle3D.deHomogenize( ).isPosZero(v[i].getCoord(3) is accessed" ); v[i].setCoord( 3, 0 ); } if( isNegZero(v[i].getCoord(3)) ){ System.err.println( "WARNING: Triangle3D.deHomogenize( ).isNegZero(v[i].getCoord(3) is accessed" ); for( int j=0; j<3; j++ ) { v[i].setCoord( j, -v[i].getCoord(j) ); } v[i].setCoord( 3, 0 ); } } } } // CLASS TRIANGLE3D $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ++++++++++++++++++++++++==================+++++++++++++++========++++++++=== class Light { public static final int AMBIENT = 0; public static final int DIRECTIONAL = 1; public static final int POINT = 2; protected int lightType; /** the position of a point light or the direction to a directional light intensity of the light source */ protected Vector3D direction; protected Point3D ptPos; protected float[] rgbFac; ///////////// CONSTRUCTORS //////////////// public Light(int type, float xval, float yval , float zval, float r, float g, float b) { lightType = type; rgbFac = new float[3]; rgbFac[0]=r; rgbFac[1]=g; rgbFac[2]=b; if (lightType == DIRECTIONAL) { direction = new Vector3D( xval, yval, zval ); direction.normalize(); } if (lightType == POINT) { ptPos = new Point3D( xval, yval, zval, 1 ); } } //////////////// METHODS /////////////////////////// public int getLtType() { return lightType; } public float getIFac(int i) { return rgbFac[i] ; } public Vector3D getDirection() { return direction; } public void print() { System.out.println(" PRINTING LIGHT" ); System.out.println(" lttype= " + lightType); System.out.println(" r= " + rgbFac[0]+ " g= " + rgbFac[1] + " b= " + rgbFac[2] ); if (lightType == DIRECTIONAL) { direction.print(); } } } //LIGHT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,,,<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))) class Surface { protected float clrFac[]; protected float ka, kd, ks, ns; public Surface(float sr, float sg, float sb, float ska, float skd, float sks, float sns){ clrFac= new float[3]; clrFac[0] = sr; clrFac[1] = sg; clrFac[2] = sb; ka = ska; kd = skd; ks = sks; ns = sns; } public float getClrFac( int i) { return clrFac[i]; } public float getKa( ) { return ka; } public float getKd( ) { return kd; } public float getKs( ) { return ks; } public float getNs( ) { return ns; } }// SURFACE ########################################################################### @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ import java.awt.*; public class Buffer { protected int width; protected int height; protected float z[]; protected final static int ZBITS = 16 ; ///////////////////////// CONSTRUCTORS /////////////////// /** * This constructor creates an uninitialized * Buffer Object of a given size (w x h). */ public Buffer(int w, int h) { width = w; height = h; z = new float[w*h]; initZ(); } ////////////////////////// METHODS //////////////////// /** * Returns the size of z-buffer */ public final int getZSize( ) { return z.length; } /** * Returns zMax */ public final int getZmax( ) { return ((1<