bool Bface::view_intersect( CNDCpt& p, // Screen point at which to do intersect Wpt& nearpt, // Point on face visually nearest to p double& dist, // Distance from nearpt to ray from camera double& d2d, // Distance in pixels nearpt to p Wvec& n // "normal" at nearpt in world coordinates ) const { // (Bsimplex virtual method): // Intersection w/ ray from given screen point -- returns the point // on the Bface that is nearest to the given screen space point. // Note: the returned "near point" and "normal" are both // transformed to world space. // Get "eye point" for computing distance. // Not sure if this is the same as cam->from(), // but it seems to be the way it's done in other // intersection code. Wpt eye = XYpt(p); // Make object-space ray: Wline ray = mesh()->inv_xform()*Wline(p); // ray in object space Wpt hit; // Try for exact intersection: double d; if (ray_intersect(ray, hit, d)) { // Direct hit nearpt = mesh()->xform()*hit; dist = nearpt.dist(eye); d2d = PIXEL(nearpt).dist(PIXEL(p)); n = (mesh()->inv_xform().transpose()*norm()).normalized(); return true; } Wpt hit1, hit2, hit3; double d1 = DBL_MAX, d2 = DBL_MAX, d3 = DBL_MAX; Wvec n1, n2, n3; _e1->view_intersect(p, hit1, d, d1, n1); _e2->view_intersect(p, hit2, d, d2, n2); _e3->view_intersect(p, hit3, d, d3, n3); // Rename so d1 represents closest hit if (d1 > d2) { swap(d1, d2); swap(hit1, hit2); swap(n1, n2); } if (d1 > d3) { swap(d1, d3); swap(hit1, hit3); swap(n1, n3); } nearpt = mesh()->xform()*hit1; dist = nearpt.dist(eye); d2d = PIXEL(nearpt).dist(PIXEL(p)); n = n1; return true; }
void SKY_BOX::update_position() //centers the sky box around the camera { Wpt eye = VIEW::eye(); if (eye.dist_sqrd(xform().origin()) > 0) { //only update when really needed set_xform(Wtransf(eye)); err_adv(debug, "SKY_BOX::update_position: updated skybox"); } }
Wpt QuadtreeNode::farthest_pt(Wpt& p) { Wpt ret = _v1; double max_dist = ret.dist(p); if (_v2.dist(p) > max_dist) { ret = _v2; max_dist = ret.dist(p); } if (_v3.dist(p) > max_dist) { ret = _v3; } return ret; }
void TEXT2D::draw_debug(const char* str, Wpt &pos, CVIEWptr& view) { if (view->rendering() == RCOLOR_ID || view->grabbing_screen()) return; if (!_dl.valid(view)) initialize(view); // GL initialization glPushAttrib(GL_ENABLE_BIT); // (GL_ENABLE_BIT) // No lighting glDisable(GL_LIGHTING); // Color //glColor3dv(COLOR::white.data()); glRasterPos3dv(pos.data()); glPushAttrib (GL_LIST_BIT); // (GL_LIST_BIT) glListBase(_dl.dl(view)); glCallLists(strlen(str), GL_UNSIGNED_BYTE, (GLubyte *) str); glPopAttrib (); // (GL_LIST_BIT) glEnable(GL_LIGHTING); glPopAttrib(); // (GL_ENABLE_BIT) glFlush(); }
void Bpoint::draw_axes() { const double PIX_LEN = 30; const double len = world_length(loc(), PIX_LEN); Wtransf xf = map()->xf(); Wpt o = xf * Wpt::Origin(); Wpt x = xf * Wpt(len,0,0); Wpt y = xf * Wpt(0,len,0); Wpt z = xf * Wpt(0,0,len); GLfloat w = GLfloat(1.0 * VIEW::peek()->line_scale()); GL_VIEW::init_line_smooth(w, GL_CURRENT_BIT); glDisable(GL_LIGHTING); // GL_ENABLE_BIT glBegin(GL_LINES); // draw x, y, z in red, yellow, blue GL_COL(Color::red, 1); // GL_CURRENT_BIT glVertex3dv(o.data()); glVertex3dv(x.data()); GL_COL(Color::yellow, 1); // GL_CURRENT_BIT glVertex3dv(o.data()); glVertex3dv(y.data()); GL_COL(Color::blue, 1); // GL_CURRENT_BIT glVertex3dv(o.data()); glVertex3dv(z.data()); glEnd(); GL_VIEW::end_line_smooth(); }
bool Bedge::view_intersect( CNDCpt& p, // Screen point at which to do intersect Wpt& nearpt, // Point on edge visually nearest to p double& dist, // Distance from nearpt to ray from camera double& d2d, // Distance in pixels nearpt to p Wvec& n // "normal" at nearpt in world space ) const { // (Bsimplex virtual method): // Intersection w/ ray from given screen point -- returns the point // on the Bedge that is nearest to the given screen space point. // Note: the returned "near point" and "normal" are both // transformed to world space. // Find nearest point on the edge in screen-space, and make a 3D // ray out of it (world space, not object space): Wline ray(NDCline(_v1->ndc(), _v2->ndc()).project_to_seg(p)); // Working in world space (applying mesh xf to verts), find // nearest point on the edge to the ray: nearpt = Wline(_v1->wloc(), _v2->wloc()).project_to_seg(ray); // Compute world and screen distances dist = nearpt.dist(ray.point()); d2d = PIXEL(nearpt).dist(PIXEL(ray.point())); // Return a "normal" vector: Wvec n1; if (nfaces() == 2) n1 = norm(); else if (nfaces() == 1) n1 = get_face()->norm(); else n1 = (ray.point() - nearpt).normalized(); // Transform the normal properly: n = (_mesh->inv_xform().transpose()*n1).normalized(); return 1; }
//! Given an initial slash gesture (or delayed slash) near the //! center of an existing straight Bcurve, set up the widget to //! do a sweep cross-ways to the Bcurve: bool SWEEP_LINE::setup(CGESTUREptr& slash, double dur) { static bool debug = Config::get_var_bool("DEBUG_SWEEP_SETUP",false) || debug_all; err_adv(debug, "SWEEP_LINE::setup"); // check the gesture if (!(slash && slash->straightness() > 0.99)) { err_adv(debug, "SWEEP_LINE::setup: gesture is bad"); return false; } // find the (straight) Bcurve near slash start _curve = Bcurve::hit_ctrl_curve(slash->start()); if (!(_curve && _curve->is_straight())) { err_adv(debug, "SWEEP_LINE::setup: no straight curve at start"); return false; } // find endpoints Bpoint *b1 = _curve->b1(), *b2 = _curve->b2(); assert(b1 && b2); // straight curve must have endpoints // curve cannot be connected to other curves if (b1->vert()->degree() != 1 || b2->vert()->degree() != 1) { err_adv(debug, "SWEEP_LINE::setup: curve is not isolated"); return false; } // ensure the gesture starts near the center of the straight line Bcurve: { PIXEL a = b1->vert()->pix(); PIXEL b = b2->vert()->pix(); double t = (slash->start() - a).tlen(b-a); if (t < 0.35 || t > 0.65) { err_adv(debug, "SWEEP_LINE::setup: gesture not near center of line"); return false; } } // find the plane to work in _plane = check_plane(shared_plane(b1, b2)); if (!_plane.is_valid()) { err_adv(debug, "SWEEP_LINE::setup: no valid plane"); return false; } // check that slash is perpendicular to line Wpt a = b1->loc(); // endpoint at b1 Wpt b = b2->loc(); // endpoint at b2 Wvec t = b - a; // vector from endpt a to endpt b Wpt o = a + t/2; // center of straight line curve Wvec n = cross(_plane.normal(), t); // direction across line ab Wvec slash_vec = endpt_vec(slash, _plane); const double ALIGN_ANGLE_THRESH = 15; double angle = rad2deg(slash_vec.angle(n)); if (angle > 90) { angle = 180 - angle; n = -n; } if (angle > ALIGN_ANGLE_THRESH) { err_adv(debug, "SWEEP_LINE::setup: slash is not perpendicular to line"); err_adv(debug, " angle: %f", angle); return false; } // compute guideline endpoint: Wpt endpt = o + n.normalized()*a.dist(b); return SWEEP_BASE::setup(_curve->mesh(), o, endpt, dur); }
/********************************************************************** * ZcrossTexture: **********************************************************************/ int ZcrossTexture::draw(CVIEWptr& v) { if (_ctrl) return _ctrl->draw(v); // Ensure zcross strips are current, and get them _patch->mesh()->build_zcross_strips(); // Get a reference for low-overhead: //const ZcrossPath& zx_sils = _patch->zx_sils(); //needs to have a current sils (simon) const ZcrossPath& zx_sils = _patch->cur_zx_sils(); // Stop now, before making partial GL calls, if nothing is going on if (zx_sils.empty()) return 1; // Set line width, (optionally) enable antialiasing, and save GL state GLfloat w = float(v->line_scale()*_width); static bool antialias = Config::get_var_bool("ANTIALIAS_SILS",true,true); static bool drawback = Config::get_var_bool("DRAW_BACKFACING",false,true); if (antialias) { // push attributes, enable line smoothing, and set line width GL_VIEW::init_line_smooth(w, GL_CURRENT_BIT); } else { // push state, set line width glPushAttrib(GL_LINE_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT); glLineWidth(w); // GL_LINE_BIT } glDisable(GL_BLEND); glDisable(GL_LIGHTING); // GL_ENABLE_BIT GL_COL(_color, alpha()); // GL_CURRENT_BIT // right now we're only doing OpenGL, ignoring CB int n = zx_sils.num(); bool started = false; bool lvis = false; bool vis = false; static bool nodots = Config::get_var_bool("ZX_NO_DOTS",false,true); static bool nocolor = Config::get_var_bool("ZX_NO_COLOR",false,true); //XXX - Hack. Not good when a loop isn't closed. // But I'm in a hurry to close proper loops... static bool closed = Config::get_var_bool("ZX_CLOSED",false,true); srand48(0); if (!nocolor) glColor3d ( drand48(), drand48(), drand48() ); else glColor3d ( 0.0, 0.0, 0.0 ); Wpt wp; if (!nodots) { glPointSize(5.0); glBegin ( GL_POINTS ) ; for ( int k =0 ; k < n; k++ ) { glColor3d ( 0.0 , 0.0 , 1.0 ); if ( zx_sils.face(k) == NULL ) glColor3d ( 1.0, 0, 0 ); glVertex3dv ( zx_sils.point(k).data() ); } glEnd(); } if ( !drawback ) { for (int i=0; i < n; i++) { vis = zx_sils.grad(i); // start new line strip if needed: if ( vis ) { //we are in a visible section of the curve if (!started ) { if ( zx_sils.face(i) ) { glBegin(GL_LINE_STRIP); zx_sils.face(i)->bc2pos ( zx_sils.bc(i) , wp ); glVertex3dv( wp.data()); started = true; } } else { if ( zx_sils.face(i) && i < n-1 ) { zx_sils.face(i)->bc2pos ( zx_sils.bc(i) , wp ); glVertex3dv( wp.data()); } else { zx_sils.face(i-1)->bc2pos ( zx_sils.bc(i) , wp ); glVertex3dv( wp.data()); glEnd(); started = false; } } } else if ( lvis && started ) { //this point is not visible, but the last one was. zx_sils.face(i-1)->bc2pos ( zx_sils.bc(i-1) , wp ); glVertex3dv( wp.data()); glEnd(); started=false; } lvis = vis; //if the face was null, we started a new loop if ( !zx_sils.face(i) ) { if (!nocolor) glColor3d ( drand48(), drand48(), drand48() ); else glColor3d ( 0.0, 0.0, 0.0); } } } else { //draw using barycentric values Wpt first; for (int i=0; i < n; i++) { vis = true; if ( vis ) { //we are in a visible section of the curve if (!started ) { if ( zx_sils.face(i) ) { glBegin(GL_LINE_STRIP); zx_sils.face(i)->bc2pos ( zx_sils.bc(i) , wp ); if (!nocolor) { if ( !zx_sils.grad(i) ) glColor3d( 1.0, 0.0 ,0.0 ); else glColor3d( 0.0 , 0.0, 1.0 ); } else { glColor3d( 0.0 , 0.0, 0.0 ); } first = wp; glVertex3dv( wp.data()); started = true; } } else { if (!nocolor) { if ( !zx_sils.grad(i) ) glColor3d( 1.0, 0.0 ,0.0 ); else glColor3d( 0.0 , 0.0, 1.0 ); } else glColor3d( 0.0 , 0.0, 0.0 ); if ( zx_sils.face(i) && i < n-1 ) { zx_sils.face(i)->bc2pos ( zx_sils.bc(i) , wp ); glVertex3dv( zx_sils.point(i).data()); } else { zx_sils.face(i-1)->bc2pos ( zx_sils.bc(i) , wp ); glVertex3dv( zx_sils.point(i-1).data()); if (closed) glVertex3dv( first.data()); glEnd(); started = false; } } } else if ( lvis && started ) { //this point is not visible, but the last one was. zx_sils.face(i-1)->bc2pos ( zx_sils.bc(i-1) , wp ); glVertex3dv( zx_sils.point(i-1).data()); glEnd(); started=false; } lvis = vis; } } // Restore GL state: if (antialias) GL_VIEW::end_line_smooth(); else glPopAttrib(); return 1; }