From: <Awa...@ao...> - 2004-08-10 14:41:34
|
included in this email is a modifed routine to plot thick curves without twisting ... (This code can replace the same routine in curve.cpp) The only modification is to the code which calculates the orthogonal vectors which span the plane at the intersection of line segments. The modification constructs orthogonal vectors which span the first plane (perpendicular to the first line segment) and then parallel transports these vectors along the curve. regards Andrew Wadsley ### start of code void curve::thickline( rView& view) { // double* v, double* color, double radius, int count const int MAX_SEGMENTS = 1024; const int curve_around = 4; static vertex projected[MAX_SEGMENTS * curve_around ]; static float light[MAX_SEGMENTS * curve_around * 3]; int step = (count + MAX_SEGMENTS-1) / MAX_SEGMENTS; vertex *pr = projected; float *lt = light; float *cost = curve_sc; float *sint = cost + curve_around; //Vector lastx(0,1,0), lasty(0,0,1); vector x, y, lastx, lasty; vector lastB, B; float tmp; int npoints = 0; // pos and color iterators const double* v_i = (double*)( data(pos)); const double* c_i = (double*)( data(color)); for(size_t corner=0; corner < count/step; ++corner, v_i += step*3, c_i += step*3) { // The vector to which v_i currently points towards. vector current( v_i[0], v_i[1], v_i[2] ); view.ext_point( current); /* To construct the circle of vertices around a point on the curve, * I need an orthonormal basis of the plane of the circle. A and B, * normalized vectors pointing toward the next and from the previous * points on the curve, are vectors in the plane of the *curve* at * this point. The cross product and the difference of these vectors * are orthogonal and lie in the appropriate plane. * Then parallel transport the last frame to this plane */ if (corner && (corner+1 < count/step)) { // Any point except the first and last. vector next( v_i[3], v_i[4], v_i[5]); // The next vector in pos vector prev( v_i[-3], v_i[-2], v_i[-1]); // The previous vector in pos vector A = next - current; B = current - prev; if ( !B ) B = lastB; x = A-B; y = A.cross(B); if (!x || !y) { x = lastx; y = lasty; B = lastB; } else { vector pz = x.cross(y); pz = pz.norm(); tmp = pz.dot(lastx)/pz.dot(B); x = lastx - B * tmp; tmp = pz.dot(lasty)/pz.dot(B); y = lasty - B * tmp; } } else if (corner) { // The last point vector prev( v_i[-3], v_i[-2], v_i[-1]); B = current - prev; if ( !B ) B = lastB; x = B.cross(vector(0,1,0)); if (!x) x = B.cross(vector(1,0,0)); y = B.cross(x); if (!x || !y) { x = lastx; y = lasty; B = lastB; } else { vector pz = x.cross(y); pz = pz.norm(); tmp = pz.dot(lastx)/pz.dot(B); x = lastx - B * tmp; tmp = pz.dot(lasty)/pz.dot(B); y = lasty - B * tmp; } } else { // The first point vector next( v_i[3], v_i[4], v_i[5]); B = next - current; x = B.cross(vector(0,1,0)); if (!x) x = B.cross(vector(1,0,0)); y = B.cross(x); if (!x || !y ) { x = vector(1,0,0); y = vector(0,0,1); B = vector(0,1,0); } } x = x.norm(); y = y.norm(); lastx = x; lasty = y; lastB = B; float lx[2], ly[2]; for(int li=0; li < view.lights.n_lights; li++) { lx[li] = view.lights.L[li].dot( x ); ly[li] = view.lights.L[li].dot( y ); } x = x * radius; y = y * radius; // Manipulate colors when we are in stereo mode. rgb rendered_color( static_cast<float>(c_i[0]), static_cast<float>(c_i[1]), static_cast<float>(c_i[2])); if (view.anaglyph) { if (view.coloranaglyph) { rendered_color = rendered_color.unsaturate(); } else { rendered_color.r = rendered_color.g = rendered_color.b = rendered_color.grayscale(); } } npoints++; for (int a=0; a < curve_around; a++) { float c = cost[a]; float s = sint[a]; float illum = view.lights.ambient; for(int li=0; li < view.lights.n_lights; li++) { float dot = c*lx[li] + s*ly[li]; if (dot > 0.0) illum += dot; } view.wct.project(current + x*c + y*s, *pr++); *(lt++) = illum * rendered_color.r; *(lt++) = illum * rendered_color.g; *(lt++) = illum * rendered_color.b; } } glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glShadeModel(GL_SMOOTH); int *ind = curve_slice; for(int a=0; a<curve_around; a++) { int ai = a; if (a == curve_around-1) { ind += 256; ai = 0; } for(int i=0; i<npoints; i+=127) { glVertexPointer(4, GL_DOUBLE, sizeof(vertex), & projected[i*curve_around + ai].x); glColorPointer (3, GL_FLOAT, sizeof(float)*3, & light[(i*curve_around + ai)*3] ); if (npoints-i < 128) glDrawElements(GL_TRIANGLE_STRIP, 2*(npoints-i), GL_UNSIGNED_INT, ind); else glDrawElements(GL_TRIANGLE_STRIP, 256, GL_UNSIGNED_INT, ind); } } } ### end of code |