/* * Copyright (c) 1996 CONNIE K. PENG All Rights Reserved. * * Permission to use, copy, modify, and distribute this software * and its documentation for NON-COMMERCIAL purposes. * */ // This program is using left hand coordinator system public class ViewFrame { // following four are refering to world's coordinator Vector COP; // Center of projection Vector VFZ; // Projection direction unit vector Vector VFY; // Up direction unit vector Vector VFX; // Right direction unit vector // following are refering to viewer's coordinator, they are fixed. static Vector[] RP; // Plane Reference Point static Vector[] NV; // Normal Vector of Plane static int VD; // Viewing plane distance static int F; // Front plane distance static int B; // Back plane distance static float VW; // Viewing window width static float VH; // Viewing window height static Matrix F2S_Matrix; // Matrix to convert frame coord to canvas coord static Matrix S2F_Matrix; // Matrix to convert canvas coord to frame coord Matrix W2F_Matrix; // Matrix to convert world coord to frame coord Matrix F2W_Matrix; // Matrix to convert frame coord to world coord // initialize the ViewFrame public ViewFrame() { COP = new Vector(0.f, 0.f, -290.f); VD = 200; VW = 500; VH = 350; F = 20; B = 600; VFZ = new Vector(0.f, 0.f, (float)VD/100); VFZ.make_vector(); VFX = new Vector((VW/2)/100, 0.f, 0.f); VFX.make_vector(); VFY = new Vector(0.f, (float)(VH/2)/100, 0.f); VFY.make_vector(); NV = new Vector[6]; NV[0] = new Vector(0.f, 0.f, 1.f); // Hither Plane NV[0].make_vector(); NV[1] = new Vector(0.f, 0.f, -1.f); // Yon Plane NV[1].make_vector(); NV[2] = new Vector(0.f, -1.f, 1.f); // Top Plane NV[2].make_vector(); NV[3] = new Vector(0.f, 1.f, 1.f); // Bottom Plane NV[3].make_vector(); NV[4] = new Vector(1.f, 0.f, 1.f); // Left Plane NV[4].make_vector(); NV[5] = new Vector(-1.f, 0.f, 1.f); // Right Plane NV[5].make_vector(); RP = new Vector[6]; RP[0] = new Vector(0.f, 0.f, (float)F); // Hither Plane RP[1] = new Vector(0.f, 0.f, (float)B); // Yon Plane RP[2] = new Vector(0.f, 0.f, 0.f); // Top Plane RP[3] = new Vector(0.f, 0.f, 0.f); // Bottom Plane RP[4] = new Vector(0.f, 0.f, 0.f); // Left Plane RP[5] = new Vector(0.f, 0.f, 0.f); // Right Plane F2W_Matrix = new Matrix(); Frame2World(); W2F_Matrix = new Matrix(); World2Frame(); F2S_Matrix = new Matrix(); Frame2Screen(); S2F_Matrix = new Matrix(); Screen2Frame(); } // set F2W_Matrix public void Frame2World() { int i; for (i = 0; i < 4; i++) F2W_Matrix.element[i][0] = VFX.element[i]; for (i = 0; i < 4; i++) F2W_Matrix.element[i][1] = VFY.element[i]; for (i = 0; i < 4; i++) F2W_Matrix.element[i][2] = VFZ.element[i]; for (i = 0; i < 4; i++) F2W_Matrix.element[i][3] = COP.element[i]; } // calculate W2F_Matrix, which is a inverse of F2W_Matrix public void World2Frame() { Matrix m = new Matrix(F2W_Matrix); W2F_Matrix = m.inverse(); } // set F2S_Matrix public void Frame2Screen() { F2S_Matrix.reset(); F2S_Matrix.element[0][0] = (VW/2)/100; F2S_Matrix.element[1][1] = -(VH/2)/100; F2S_Matrix.element[0][3] = VW/2; F2S_Matrix.element[1][3] = VH/2; } // set S2F_Matrix public void Screen2Frame() { S2F_Matrix.reset(); S2F_Matrix.element[0][0] = 200 / VW; S2F_Matrix.element[1][1] = -200 / VH; S2F_Matrix.element[0][3] = -100; S2F_Matrix.element[1][3] = 100; } // translate the view frame public void Translate (Vector v) { COP.add(v); // recalcute F2W_Matrix and W2F_Matrix Frame2World(); World2Frame(); } // rotate the view frame along x axis public void RotateX (int degree) { Matrix m = new Matrix(); m.rotatex(degree); VFZ.multiply(m); VFY.multiply(m); VFX.multiply(m); Frame2World(); World2Frame(); } // rotate the view frame along y axis public void RotateY (int degree) { Matrix m = new Matrix(); m.rotatey(degree); VFZ.multiply(m); VFY.multiply(m); VFX.multiply(m); Frame2World(); World2Frame(); } // rotate the view frame along z axis public void RotateZ (int degree) { Matrix m = new Matrix(); m.rotatez(degree); VFZ.multiply(m); VFY.multiply(m); VFX.multiply(m); Frame2World(); World2Frame(); } // clipping the lines according to viewing volumn public byte Clipping (Vector start, Vector end) { byte retval = 0x00; Vector v1 = new Vector(); Vector v2 = new Vector(); Vector clip_ptr = new Vector(); // check for each plane, and do canonical view clipping for (int i = 0; i < 6; i++) { v1.set_element(start.element[0], start.element[1], start.element[2]); v1.sub(RP[i]); v2.set_element(end.element[0], end.element[1], end.element[2]); v2.sub(RP[i]); float dp1 = v1.dot_product(NV[i]); float dp2 = v2.dot_product(NV[i]); // both end point of line are out side of this clipping plane if (dp1 < 0 && dp2 < 0) return 0x04; // one end point is outside of the clipping plane, this point // needs to be clipped out if (dp1 < 0 || dp2 < 0) { float fraction = Math.abs(dp1) / (Math.abs(dp1) + Math.abs(dp2)); clip_ptr.set_element(end.element[0], end.element[1], end.element[2]); clip_ptr.sub(start); clip_ptr.scale(fraction); clip_ptr.add(start); // start point is clipped out, and is replaced by the new point if (dp1 < 0) { retval = (byte) (retval | 0x02); start.set_element(clip_ptr.element[0], clip_ptr.element[1], clip_ptr.element[2]); } // end point is clipped out, and is replaced by the new point else { retval = (byte) (retval | 0x01); end.set_element(clip_ptr.element[0], clip_ptr.element[1], clip_ptr.element[2]); } } } return retval; } }