00001 /* 00002 File: Clipper.cc 00003 00004 Function: Clips homogeneous coordinates to the unit cube 00005 between [0 0 0] and [1 1 1]. 00006 00007 Author: Andrew Willmott 00008 00009 Notes: 00010 */ 00011 00012 #include "gcl/Clipper.h" 00013 #include "cl/String.h" 00014 00015 #define DBG_COUT if (0) cerr 00016 00041 Clipper::Clipper() 00042 { 00043 lastOutcode = 0; 00044 lastP = vl_0; 00045 } 00046 00047 Void Clipper::ClipPoint(const HPoint &p, Bool draw) 00048 { 00049 Int outcode; 00050 BdryCoords bc; 00051 00052 // calc BC for [-1, 1] x [-1, 1] x [0, 1] 00053 // bc is -ve if: 00054 bc[0] = p[3] + p[0]; // x < -1 00055 bc[1] = p[3] - p[0]; // x > 1 00056 bc[2] = p[3] + p[1]; // y < -1 00057 bc[3] = p[3] - p[1]; // y > 1 00058 bc[4] = p[2]; // z < 0 00059 bc[5] = p[3] - p[2]; // z > 1 00060 00061 // should replace this with non-branching code where possible 00062 outcode = 0; 00063 if (bc[0] < 0) outcode |= 0x01; 00064 if (bc[1] < 0) outcode |= 0x02; 00065 if (bc[2] < 0) outcode |= 0x04; 00066 if (bc[3] < 0) outcode |= 0x08; 00067 if (bc[4] < 0) outcode |= 0x10; 00068 if (bc[5] < 0) outcode |= 0x20; 00069 00070 DBG_COUT << String().Printf("outcode = %02x", outcode) << endl; 00071 00072 // do the clipping 00073 00074 if (!draw) 00075 { 00076 // move if we're inside the clip volume 00077 if (outcode == 0) 00078 ViewPoint(p, draw); 00079 } 00080 else 00081 { 00082 if ((outcode & lastOutcode) == 0) 00083 // we have at least one endpoint inside all planes 00084 if ((outcode | lastOutcode) == 0) 00085 // both are inside: trivial accept 00086 ViewPoint(p, draw); 00087 else 00088 { 00089 Int i, clip = outcode | lastOutcode, mask = 1; 00090 GCLReal alpha, alpha0 = 0.0, alpha1 = 1.0; 00091 00092 DBG_COUT << String().Printf("clipping: clip = %02x", clip) << endl; 00093 00094 // must clip line segment to the volume. 00095 00096 // step through each plane 00097 for (i = 0; i < 6; i++, mask <<= 1) 00098 { 00099 if (mask & clip) 00100 // we straddled this boundary 00101 { 00102 // find the alpha of the intersection with this plane 00103 alpha = lastBC[i] / (lastBC[i] - bc[i]); 00104 if (lastOutcode & mask) 00105 // heading in: clip alpha0 00106 alpha0 = Max(alpha0, alpha); 00107 else 00108 // heading out: clip alpha1 00109 alpha1 = Min(alpha1, alpha); 00110 } 00111 } 00112 00113 DBG_COUT << "alpha0 = " << alpha0 << " alpha1 = " << alpha1 << endl; 00114 00115 if (lastOutcode) 00116 // heading in, so move to entry point 00117 ViewPoint(lastP + alpha0 * (p - lastP), false); 00118 if (outcode) 00119 // heading out, so draw to exit point 00120 ViewPoint(lastP + alpha1 * (p - lastP), true); 00121 else 00122 // terminate inside clipping volume, so just draw! 00123 ViewPoint(p, true); 00124 } 00125 } 00126 00127 lastOutcode = outcode; 00128 lastBC[0] = bc[0]; 00129 lastBC[1] = bc[1]; 00130 lastBC[2] = bc[2]; 00131 lastBC[3] = bc[3]; 00132 lastBC[4] = bc[4]; 00133 lastBC[5] = bc[5]; 00134 lastP = p; 00135 }