void CameraController::frame( const Imath::Box3f &box, const Imath::V3f &viewDirection, const Imath::V3f &upVector ) { // make a matrix to centre the camera on the box, with the appropriate view direction M44f cameraMatrix = rotationMatrixWithUpDir( V3f( 0, 0, -1 ), viewDirection, upVector ); M44f translationMatrix; translationMatrix.translate( box.center() ); cameraMatrix *= translationMatrix; // translate the camera back until the box is completely visible M44f inverseCameraMatrix = cameraMatrix.inverse(); Box3f cBox = transform( box, inverseCameraMatrix ); Box2f screenWindow = m_data->screenWindow->readable(); if( m_data->projection->readable()=="perspective" ) { // perspective. leave the field of view and screen window as is and translate // back till the box is wholly visible. this currently assumes the screen window // is centred about the camera axis. float z0 = cBox.size().x / screenWindow.size().x; float z1 = cBox.size().y / screenWindow.size().y; m_data->centreOfInterest = std::max( z0, z1 ) / tan( M_PI * m_data->fov->readable() / 360.0 ) + cBox.max.z + m_data->clippingPlanes->readable()[0]; cameraMatrix.translate( V3f( 0.0f, 0.0f, m_data->centreOfInterest ) ); } else { // orthographic. translate to front of box and set screen window // to frame the box, maintaining the aspect ratio of the screen window. m_data->centreOfInterest = cBox.max.z + m_data->clippingPlanes->readable()[0] + 0.1; // 0.1 is a fudge factor cameraMatrix.translate( V3f( 0.0f, 0.0f, m_data->centreOfInterest ) ); float xScale = cBox.size().x / screenWindow.size().x; float yScale = cBox.size().y / screenWindow.size().y; float scale = std::max( xScale, yScale ); V2f newSize = screenWindow.size() * scale; screenWindow.min.x = cBox.center().x - newSize.x / 2.0f; screenWindow.min.y = cBox.center().y - newSize.y / 2.0f; screenWindow.max.x = cBox.center().x + newSize.x / 2.0f; screenWindow.max.y = cBox.center().y + newSize.y / 2.0f; } m_data->transform->matrix = cameraMatrix; m_data->screenWindow->writable() = screenWindow; }
void CameraController::track( const Imath::V2f &p ) { V2i resolution = m_data->resolution->readable(); Box2f screenWindow = m_data->screenWindow->readable(); V2f d = p - m_data->motionStart; V3f translate( 0.0f ); translate.x = -screenWindow.size().x * d.x/(float)resolution.x; translate.y = screenWindow.size().y * d.y/(float)resolution.y; if( m_data->projection->readable()=="perspective" && m_data->fov ) { translate *= tan( M_PI * m_data->fov->readable() / 360.0f ) * (float)m_data->centreOfInterest; } M44f t = m_data->motionMatrix; t.translate( translate ); m_data->transform->matrix = t; }
void CameraController::dolly( const Imath::V2f &p ) { V2i resolution = m_data->resolution->readable(); V2f dv = V2f( (p - m_data->motionStart) ) / resolution; float d = dv.x - dv.y; if( m_data->projection->readable()=="perspective" ) { // perspective m_data->centreOfInterest = m_data->motionCentreOfInterest * expf( -1.9f * d ); M44f t = m_data->motionMatrix; t.translate( V3f( 0, 0, m_data->centreOfInterest - m_data->motionCentreOfInterest ) ); m_data->transform->matrix = t; } else { // orthographic Box2f screenWindow = m_data->motionScreenWindow; V2f centreNDC = V2f( m_data->motionStart ) / resolution; V2f centre( lerp( screenWindow.min.x, screenWindow.max.x, centreNDC.x ), lerp( screenWindow.max.y, screenWindow.min.y, centreNDC.y ) ); float newWidth = m_data->motionScreenWindow.size().x * expf( -1.9f * d ); newWidth = std::max( newWidth, 0.01f ); float scale = newWidth / screenWindow.size().x; screenWindow.min = (screenWindow.min - centre) * scale + centre; screenWindow.max = (screenWindow.max - centre) * scale + centre; m_data->screenWindow->writable() = screenWindow; } }
void BackdropNodeGadget::doRender( const Style *style ) const { // this is our bound in gadget space Box2f bound = boundPlug()->getValue(); // but because we're going to draw our contents at an arbitrary scale, // we need to compute a modified bound which will be in the right place // following scaling. const Backdrop *backdrop = static_cast<const Backdrop *>( node() ); const float scale = backdrop->scalePlug()->getValue(); bound.min /= scale; bound.max /= scale; glPushMatrix(); glScalef( scale, scale, scale ); const Box3f titleCharacterBound = style->characterBound( Style::HeadingText ); const float titleBaseline = bound.max.y - g_margin - titleCharacterBound.max.y; if( IECoreGL::Selector::currentSelector() ) { // when selecting we render in a simplified form. // we only draw a thin strip around the edge of the backdrop // to allow the edges to be grabbed for dragging, and a strip // at the top to allow the title header to be grabbed for moving // around. leaving the main body of the backdrop as a hole is // necessary to allow the GraphGadget to continue to perform // drag selection on the nodes on top of the backdrop. const float width = hoverWidth() / scale; style->renderSolidRectangle( Box2f( bound.min, V2f( bound.min.x + width, bound.max.y ) ) ); // left style->renderSolidRectangle( Box2f( V2f( bound.max.x - width, bound.min.y ), bound.max ) ); // right style->renderSolidRectangle( Box2f( bound.min, V2f( bound.max.x, bound.min.y + width ) ) ); // bottom style->renderSolidRectangle( Box2f( V2f( bound.min.x, bound.max.y - width ), bound.max ) ); // top style->renderSolidRectangle( Box2f( V2f( bound.min.x, titleBaseline - g_margin ), bound.max ) ); // heading } else { // normal drawing mode style->renderBackdrop( bound, getHighlighted() ? Style::HighlightedState : Style::NormalState ); const std::string title = backdrop->titlePlug()->getValue(); if( title.size() ) { Box3f titleBound = style->textBound( Style::HeadingText, title ); glPushMatrix(); glTranslatef( bound.center().x - titleBound.size().x / 2.0f, titleBaseline, 0.0f ); style->renderText( Style::HeadingText, title ); glPopMatrix(); } if( m_hovered ) { style->renderHorizontalRule( V2f( bound.center().x, titleBaseline - g_margin / 2.0f ), bound.size().x - g_margin * 2.0f, Style::HighlightedState ); } Box2f textBound = bound; textBound.min += V2f( g_margin ); textBound.max = V2f( textBound.max.x - g_margin, titleBaseline - g_margin ); if( textBound.hasVolume() ) { std::string description = backdrop->descriptionPlug()->getValue(); style->renderWrappedText( Style::BodyText, description, textBound ); } } glPopMatrix(); }
MeshPrimitivePtr MeshPrimitive::createPlane( const Box2f &b, const Imath::V2i &divisions ) { V3fVectorDataPtr pData = new V3fVectorData; std::vector<V3f> &p = pData->writable(); // add vertices float xStep = b.size().x / (float)divisions.x; float yStep = b.size().y / (float)divisions.y; for ( int i = 0; i <= divisions.y; ++i ) { for ( int j = 0; j <= divisions.x; ++j ) { p.push_back( V3f( b.min.x + j * xStep, b.min.y + i * yStep, 0 ) ); } } IntVectorDataPtr vertexIds = new IntVectorData; IntVectorDataPtr verticesPerFace = new IntVectorData; std::vector<int> &vpf = verticesPerFace->writable(); std::vector<int> &vIds = vertexIds->writable(); FloatVectorDataPtr sData = new FloatVectorData; FloatVectorDataPtr tData = new FloatVectorData; std::vector<float> &s = sData->writable(); std::vector<float> &t = tData->writable(); float sStep = 1.0f / (float)divisions.x; float tStep = 1.0f / (float)divisions.y; // add faces int v0, v1, v2, v3; for ( int i = 0; i < divisions.y; ++i ) { for ( int j = 0; j < divisions.x; ++j ) { v0 = j + (divisions.x+1) * i; v1 = j + 1 + (divisions.x+1) * i;; v2 = j + 1 + (divisions.x+1) * (i+1); v3 = j + (divisions.x+1) * (i+1); vpf.push_back( 4 ); vIds.push_back( v0 ); vIds.push_back( v1 ); vIds.push_back( v2 ); vIds.push_back( v3 ); s.push_back( j * sStep ); s.push_back( (j+1) * sStep ); s.push_back( (j+1) * sStep ); s.push_back( j * sStep ); t.push_back( 1 - i * tStep ); t.push_back( 1 - i * tStep ); t.push_back( 1 - (i+1) * tStep ); t.push_back( 1 - (i+1) * tStep ); } } MeshPrimitivePtr result = new MeshPrimitive( verticesPerFace, vertexIds, "linear", pData ); result->variables["s"] = PrimitiveVariable( PrimitiveVariable::FaceVarying, sData ); result->variables["t"] = PrimitiveVariable( PrimitiveVariable::FaceVarying, tData ); return result; }
void TexViewerModule::draw(Box2f viewport, Box2f screen_viewport, float scale, unsigned int recurse) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glBoxToBox(viewport, screen_viewport); Vector2f s = size(); glBegin(GL_QUADS); glColor3f(0.0f, 0.0f, 0.0f); glVertex2f(-0.5f*s.x, -0.5f*s.y); glVertex2f( 0.5f*s.x, -0.5f*s.y); glVertex2f( 0.5f*s.x, 0.5f*s.y); glVertex2f(-0.5f*s.x, 0.5f*s.y); glEnd(); if (tex_out().tex != 0) { glDisable(GL_BLEND); glUseProgramObjectARB(scale_bias_shader->handle); glUniform1fARB(glGetUniformLocationARB(scale_bias_shader->handle, "scale"), 1.0f); glUniform1fARB(glGetUniformLocationARB(scale_bias_shader->handle, "bias"), 0.5f); glColor3f(1.0f, 1.0f, 1.0f); glEnable(GL_TEXTURE_RECTANGLE_ARB); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex_out().tex); #ifdef ATI_HACK set_nearest(); #else set_linear(); //no ATI_HACK #endif float px_size = 2.0f / Graphics::screen_y * viewport.size().x / screen_viewport.size().x * tex_out().height / size().y; glBegin(GL_QUADS); glColor3f(0.0f, 0.0f, 0.0f); glTexCoord2f(0-0.5f * px_size, 0-0.5f * px_size); glMultiTexCoord2f(GL_TEXTURE1_ARB, 0+0.5f * px_size, 0+0.5f * px_size); if (rotate) { glVertex2f(-0.5f*s.x, -0.5f*s.y); } else { glVertex2f(-0.5f*s.x, 0.5f*s.y); } glTexCoord2f(tex_out().width-0.5f * px_size, 0-0.5f * px_size); glMultiTexCoord2f(GL_TEXTURE1_ARB, tex_out().width+0.5f * px_size, 0+0.5f * px_size); if (rotate) { glVertex2f(-0.5f*s.x, 0.5f*s.y); } else { glVertex2f( 0.5f*s.x, 0.5f*s.y); } glTexCoord2f(tex_out().width-0.5f * px_size, tex_out().height-0.5f * px_size); glMultiTexCoord2f(GL_TEXTURE1_ARB, tex_out().width+0.5f * px_size, tex_out().height+0.5f * px_size); if (rotate) { glVertex2f( 0.5f*s.x, 0.5f*s.y); } else { glVertex2f( 0.5f*s.x, -0.5f*s.y); } glTexCoord2f(0-0.5f * px_size, tex_out().height-0.5f * px_size); glMultiTexCoord2f(GL_TEXTURE1_ARB, 0+0.5f * px_size, tex_out().height+0.5f * px_size); if (rotate) { glVertex2f( 0.5f*s.x, -0.5f*s.y); } else { glVertex2f(-0.5f*s.x, -0.5f*s.y); } glEnd(); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glDisable(GL_TEXTURE_RECTANGLE_ARB); glUseProgramObjectARB(0); glEnable(GL_BLEND); } else { glBegin(GL_LINES); glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(-0.4f*s.x, -0.4f*s.y); glVertex2f( 0.4f*s.x, 0.4f*s.y); glVertex2f( 0.4f*s.x, -0.4f*s.y); glVertex2f(-0.4f*s.x, 0.4f*s.y); glEnd(); } glBegin(GL_LINE_LOOP); glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(-0.5f*s.x, -0.5f*s.y); glVertex2f( 0.5f*s.x, -0.5f*s.y); glVertex2f( 0.5f*s.x, 0.5f*s.y); glVertex2f(-0.5f*s.x, 0.5f*s.y); glEnd(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); Graphics::gl_errors("TexViewer::draw"); }
void LayersDialog::draw(Box2f viewport, Box2f screen_viewport, float scale, unsigned int recurse) { if (!subpixel_shader.ref) { Graphics::ShaderObjectRef frag = Graphics::get_shader_object("ll_shaders/ll_subpixel.glsl", GL_FRAGMENT_SHADER_ARB); assert(frag.ref); subpixel_shader = Graphics::get_program_object(frag); assert(subpixel_shader.ref); glUseProgramObjectARB(subpixel_shader->handle); glUniform1iARB(glGetUniformLocationARB(subpixel_shader->handle, "image"), 0); glUseProgramObjectARB(0); } glMatrixMode(GL_PROJECTION); glPushMatrix(); glBoxToBox(viewport, screen_viewport); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glBegin(GL_QUADS); glColor3f(0.4f, 0.2f, 0.2f); glVertex2f(-size().x*0.5f, -size().y*0.5f); glVertex2f( size().x*0.5f, -size().y*0.5f); glVertex2f( size().x*0.5f, size().y*0.5f); glVertex2f(-size().x*0.5f, size().y*0.5f); glEnd(); if (!layering()) { glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); return; } vector< DialogBin > const &bins = layering()->bins; const float dialog_tween = layering()->dialog_tween; const unsigned int width = layering()->width; const unsigned int height = layering()->height; vector< GLuint > const &textures = layering()->textures; for (unsigned int b = 0; b < bins.size(); ++b) { float alpha = bins[b].active?1.0f:0.3f; Box2f box = bins[b].get_box(dialog_tween); glBegin(GL_QUADS); glColor4f(0.5f, 0.5f, 0.6f, alpha * 0.8f); glVertex2f(box.min.x, box.min.y); glVertex2f(box.max.x, box.min.y); glColor4f(0.9f, 0.85f, 0.83f, alpha * 0.8f); glVertex2f(box.max.x, box.max.y); glVertex2f(box.min.x, box.max.y); glEnd(); Box2f tex = bins[b].get_tex_box(dialog_tween); Vector3f show = bins[b].get_show(dialog_tween, make_vector(width * 0.5f, height * 0.5f, width * 0.5f)); show += bins[b].zoom_out * (make_vector(0.5f * width, 0.5f * height, 0.5f * width) - show); if (bins[b].layer < textures.size()) { float px_size = 2.0f / Graphics::screen_y * viewport.size().x / screen_viewport.size().x * show.z / (tex.max.y - tex.min.y); glUseProgramObjectARB(subpixel_shader->handle); glUniform1fARB(glGetUniformLocationARB(subpixel_shader->handle, "px_size"), px_size); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textures[bins[b].layer]); } glColor4f(1.0f, 1.0f, 1.0f, alpha); glBegin(GL_QUADS); glTexCoord2f(show.x-show.z,show.y-show.z); glVertex2f(tex.min.x, tex.min.y); glTexCoord2f(show.x+show.z,show.y-show.z); glVertex2f(tex.max.x, tex.min.y); glTexCoord2f(show.x+show.z,show.y+show.z); glVertex2f(tex.max.x, tex.max.y); glTexCoord2f(show.x-show.z,show.y+show.z); glVertex2f(tex.min.x, tex.max.y); glEnd(); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glUseProgramObjectARB(0); //arrows: float s = box.size().y * (1.0f / 3.0f); glEnable(GL_POLYGON_SMOOTH); glBegin(GL_TRIANGLES); glColor4f(1.0f, 1.0f, 1.0f, 0.5f * alpha * bins[b].arrows); glVertex2f(box.max.x - s * 1.5f, box.max.y - 0.25 * s); glVertex2f(box.max.x - s * 0.75f, box.max.y - 1.25 * s); glVertex2f(box.max.x - s * 2.25f, box.max.y - 1.25 * s); glVertex2f(box.max.x - s * 1.5f, box.min.y + 0.25 * s); glVertex2f(box.max.x - s * 0.75f, box.min.y + 1.25 * s); glVertex2f(box.max.x - s * 2.25f, box.min.y + 1.25 * s); glEnd(); glDisable(GL_POLYGON_SMOOTH); glBegin(GL_LINES); glColor4f(1.0f, 1.0f, 1.0f, 0.5f * alpha * bins[b].arrows); glVertex2f(tex.max.x + box.size().x * 0.05f, box.center().y); glVertex2f(box.max.x - box.size().x * 0.05f, box.center().y); glEnd(); } glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); }