void label::gl_render( const view& scene) { if (text_changed) { boost::shared_ptr<font> texmap_font = font::find_font( font_description, int(font_size)); if (text.empty()) text_layout = texmap_font->lay_out( L" " ); else text_layout = texmap_font->lay_out( text); text_changed = false; } // Compute the width of the text box. vector extents = text_layout->extent( scene ); double box_width = extents.x + 2.0*border; // Compute the positions of the text in the text box, and the height of the // text box. The text positions are relative to the lower left corner of // the text box. double box_height = extents.y + 2.0*border; vector text_pos( border, box_height - border); clear_gl_error(); vector label_pos = pos.scale(scene.gcfvec); tmatrix lst = tmatrix().gl_projection_get() * tmatrix().gl_modelview_get(); { tmatrix translate; translate.w_column( label_pos); lst = lst * translate; } vector origin = (lst * vertex(vector(), 1.0)).project(); // It is very important to make sure that the texture is positioned // accurately at a screen pixel location, to avoid artifacts around the texture. double kx = scene.view_width/2.0; double ky = scene.view_height/2.0; if (origin.x >= 0) { origin.x = ((int)(kx*origin.x+0.5))/kx; } else { origin.x = -((int)(-kx*origin.x+0.5))/kx; } if (origin.y >= 0) { origin.y = ((int)(ky*origin.y+0.5))/ky; } else { origin.y = -((int)(-ky*origin.y+0.5))/ky; } double halfwidth = (int)(0.5*box_width+0.5); double halfheight = (int)(0.5*box_height+0.5); rgb stereo_linecolor = linecolor; if (scene.anaglyph) if (scene.coloranaglyph) stereo_linecolor = linecolor.desaturate(); else stereo_linecolor = linecolor.grayscale(); displaylist list; list.gl_compile_begin(); { stereo_linecolor.gl_set(1.0f); // Zero out the existing matrices, rendering will be in screen coords. gl_matrix_stackguard guard; tmatrix identity; identity.gl_load(); glMatrixMode( GL_PROJECTION); { //< Zero out the projection matrix, too gl_matrix_stackguard guard2; identity.gl_load(); glTranslated( origin.x, origin.y, origin.z); glScaled( 1.0/kx, 1.0/ky, 1.0); // At this point, all further translations are in direction of label space. if (space && (xoffset || yoffset)) { // Move the origin away from the body. vector space_offset = vector(xoffset, yoffset).norm() * std::fabs(space); glTranslated( space_offset.x, space_offset.y, space_offset.z); } // Optionally draw the line, and move the origin to the bottom left // corner of the text box. if (xoffset || yoffset) { if (line_enabled) { glBegin( GL_LINES); vector().gl_render(); vector(xoffset, yoffset).gl_render(); glEnd(); } if (std::fabs(xoffset) > std::fabs(yoffset)) { glTranslated( xoffset + ((xoffset > 0) ? 0 : -2.0*halfwidth), yoffset - halfheight, 0); } else { glTranslated( xoffset - halfwidth, yoffset + ((yoffset > 0) ? 0 : -2.0*halfheight), 0); } } else { glTranslated( -halfwidth, -halfheight, 0.0); } if (opacity) { // Occlude objects behind the label. rgba( background[0], background[1], background[2], opacity).gl_set(); glBegin( GL_QUADS); vector().gl_render(); vector( 2.0*halfwidth, 0).gl_render(); vector( 2.0*halfwidth, 2.0*halfheight).gl_render(); vector( 0, 2.0*halfheight).gl_render(); glEnd(); } if (box_enabled) { // Draw a box around the text. stereo_linecolor.gl_set(1.0f); glBegin( GL_LINE_LOOP); vector().gl_render(); vector( 2.0*halfwidth, 0).gl_render(); vector( 2.0*halfwidth, 2.0*halfheight).gl_render(); vector( 0, 2.0*halfheight).gl_render(); glEnd(); } // Render the text itself. color.gl_set(1.0f); text_layout->gl_render(scene, text_pos); } glMatrixMode( GL_MODELVIEW); } // Pops the matrices back off the stack list.gl_compile_end(); check_gl_error(); scene.screen_objects.insert( std::make_pair(pos, list)); }
const tvector4 tvector4::WAxis = vector4(0,0,0,1); const tvector4 tvector4::opXAxis = vector4(-1,0,0,0); const tvector4 tvector4::opYAxis = vector4(0,-1,0,0); const tvector4 tvector4::opZAxis = vector4(0,0,-1,0); const tvector4 tvector4::opWAxis = vector4(0,0,0,-1); /////////////////////////////////////////////////////////////////////////////////////////////////// const tcolor tcolor::black (0, 0, 0, 0); const tcolor tcolor::white (1, 1, 1, 1); const tcolor tcolor::red (1, 0, 0, 1); const tcolor tcolor::green (0, 1, 0, 1); const tcolor tcolor::blue (0, 0, 1, 1); tmatrix tmatrix::identity = tmatrix(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1); tquaternion tquaternion::identity = tquaternion(0,0,0,1); /////////////////////////////////////////////////////////////////////////////////////////////////// tvector3 tvector3::vecLimitDeviationAngleUtility (const bool insideOrOutside, const tvector3& source, const float cosineOfConeAngle, const tvector3& basis) { // immediately return zero length input vectors float sourceLength = source.Length(); if (sourceLength == 0) return source; // measure the angular diviation of "source" from "basis" const tvector3 direction = source / sourceLength;