//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void OverlayTextBox::render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software) { Mat4d ident; MatrixState matrixState(position, size, ident, ident); Vec2f textPos(0.0f, static_cast<float>(size.y())/2.0f); if (m_drawBorder || m_drawBackground) { renderBackgroundAndBorder(oglContext, position, size, software); textPos.x() = 4; // Allow for margin } Vec2ui textExtent = m_font->textExtent(m_text); textPos.y() -= (static_cast<float>(textExtent.y())/2.0f); // Set the text m_textDrawer->removeAllTexts(); m_textDrawer->addText(m_text, textPos); m_textDrawer->setTextColor(m_textColor); // Draw the text if (software) { m_textDrawer->renderSoftware(oglContext, matrixState); } else { m_textDrawer->render(oglContext, matrixState); } }
//-------------------------------------------------------------------------------------------------- /// Set up camera/viewport and render //-------------------------------------------------------------------------------------------------- void OverlayNavigationCube::render(OpenGLContext* oglContext, const Vec2i& position, const Vec2ui& size, bool software, const Mat4d& viewMatrix) { if (size.x() <= 0 || size.y() <= 0) { return; } if (m_axis.isNull()) { createAxisGeometry(software); } if (m_cubeGeos.size() == 0) { createCubeGeos(); // Create the shader for the cube geometry ShaderProgramGenerator gen("CubeGeoShader", ShaderSourceProvider::instance()); gen.configureStandardHeadlightColor(); m_cubeGeoShader = gen.generate(); m_cubeGeoShader->linkProgram(oglContext); } // Position the camera far enough away to make the axis and the text fit within the viewport Mat4d axisMatrix = viewMatrix; axisMatrix.setTranslation(Vec3d(0, 0, -2.0)); // Setup camera Camera cam; cam.setProjectionAsPerspective(40.0, 0.05, 100.0); cam.setViewMatrix(axisMatrix); cam.setViewport(position.x(), position.y(), size.x(), size.y()); // Setup viewport cam.viewport()->applyOpenGL(oglContext, Viewport::CLEAR_DEPTH); cam.applyOpenGL(); // Do the actual rendering // ----------------------------------------------- MatrixState matrixState(cam); if (software) { renderAxisImmediateMode(oglContext, matrixState); } else { renderAxis(oglContext, matrixState); } renderCubeGeos(oglContext, software, matrixState); renderAxisLabels(oglContext, software, matrixState); }
bool GeometryUtils::project(const Mat4d& projectionMultViewMatrix, const Vec2i& viewportPosition, const Vec2ui& viewportSize, const Vec3d& point, Vec3d* out) { CVF_ASSERT(out); Vec4d v = projectionMultViewMatrix * Vec4d(point, 1.0); if (v.w() == 0.0f) { return false; } v.x() /= v.w(); v.y() /= v.w(); v.z() /= v.w(); // map to range 0-1 out->x() = v.x()*0.5 + 0.5; out->y() = v.y()*0.5 + 0.5; out->z() = v.z()*0.5 + 0.5; // map to viewport out->x() = out->x() * viewportSize.x() + viewportPosition.x(); out->y() = out->y() * viewportSize.y() + viewportPosition.y(); return true; }
//-------------------------------------------------------------------------------------------------- /// Set up camera/viewport and render //-------------------------------------------------------------------------------------------------- void OverlayColorLegend::render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software) { if (size.x() <= 0 || size.y() <= 0) { return; } Camera camera; camera.setViewport(position.x(), position.y(), size.x(), size.y()); camera.setProjectionAsPixelExact2D(); camera.setViewMatrix(Mat4d::IDENTITY); camera.applyOpenGL(); camera.viewport()->applyOpenGL(oglContext, Viewport::CLEAR_DEPTH); // Get layout information // Todo: Cache this between renderings. Update only when needed. OverlayColorLegendLayoutInfo layout(position, size); layoutInfo(&layout); // Set up text drawer TextDrawer textDrawer(m_font.p()); setupTextDrawer(&textDrawer, &layout); // Do the actual rendering if (software) { renderLegendImmediateMode(oglContext, &layout); textDrawer.renderSoftware(oglContext, camera); } else { const MatrixState matrixState(camera); renderLegend(oglContext, &layout, matrixState); textDrawer.render(oglContext, camera); } CVF_CHECK_OGL(oglContext); }
//-------------------------------------------------------------------------------------------------- /// Set the size of the text box to fit the current text. /// /// The method will also add a bit of space for the border or background if enabled. //-------------------------------------------------------------------------------------------------- void OverlayTextBox::setSizeToFitText() { cvf::Vec2ui textSize = m_font->textExtent(m_text); // Add the size of an 'A' as the margin, same as used in the Text Drawer ref<Glyph> glyph = m_font->getGlyph(L'A'); Vec2ui size = Vec2ui(textSize.x() + glyph->width(), textSize.y() + glyph->height()); if (m_drawBorder) { size.x() += 4; size.y() += 4; } setPixelSize(size); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool OverlayScalarMapperLegend::pick(int oglXCoord, int oglYCoord, const Vec2i& position, const Vec2ui& size) { Recti oglRect(position, size.x(), size.y()); OverlayColorLegendLayoutInfo layoutInViewPortCoords(oglRect.min(), Vec2ui(oglRect.width(), oglRect.height())); layoutInfo(&layoutInViewPortCoords); Vec2i legendBarOrigin = oglRect.min(); legendBarOrigin.x() += static_cast<uint>(layoutInViewPortCoords.legendRect.min().x()); legendBarOrigin.y() += static_cast<uint>(layoutInViewPortCoords.legendRect.min().y()); Recti legendBarRect = Recti(legendBarOrigin, static_cast<uint>(layoutInViewPortCoords.legendRect.width()), static_cast<uint>(layoutInViewPortCoords.legendRect.height())); if ((oglXCoord > legendBarRect.min().x()) && (oglXCoord < legendBarRect.max().x()) && (oglYCoord > legendBarRect.min().y()) && (oglYCoord < legendBarRect.max().y())) { return true; } return false; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void Rendering::calculateOverlayItemLayout(OverlayItemRectMap* itemRectMap, OverlayItem::LayoutCorner corner, OverlayItem::LayoutDirection direction) { const int border = 3; const Vec2i vpSize = Vec2i(static_cast<int>(m_camera->viewport()->width()), static_cast<int>(m_camera->viewport()->height())); const Vec2i vpPos = Vec2i(m_camera->viewport()->x(), m_camera->viewport()->y()); Vec2i cursor(0,0); switch (corner) { case OverlayItem::TOP_LEFT: cursor.set(border, vpSize.y() - border); break; case OverlayItem::TOP_RIGHT: cursor.set(vpSize.x() - border, vpSize.y() - border); break; case OverlayItem::BOTTOM_LEFT: cursor.set(border, border); break; case OverlayItem::BOTTOM_RIGHT: cursor.set(vpSize.x() - border, border); break; default: cursor.set(border,border); } cursor += vpPos; // Adjust based on other already placed items OverlayItemRectMap::iterator it; for (it = itemRectMap->begin(); it != itemRectMap->end(); ++it) { Recti rect = it->second; if (rect.contains(cursor) && (direction == OverlayItem::VERTICAL)) { if (corner == OverlayItem::BOTTOM_LEFT || corner == OverlayItem::BOTTOM_RIGHT) { cursor.y() += rect.height() + border; } else { cursor.y() -= rect.height() + border; } } } size_t numOverlayItems = m_overlayItems.size(); size_t i; for (i = 0; i < numOverlayItems; i++) { OverlayItemLayout item = m_overlayItems.at(i); if ((item.corner == corner) && (item.direction == direction)) { CVF_ASSERT(item.overlayItem.notNull()); // Find this position and size Vec2i position = cursor; Vec2ui size = item.overlayItem->sizeHint(); if ((corner == OverlayItem::TOP_RIGHT) || (corner == OverlayItem::BOTTOM_RIGHT)) { position.x() -= size.x(); } if ((corner == OverlayItem::TOP_LEFT) || (corner == OverlayItem::TOP_RIGHT)) { position.y() -= size.y(); } // Store the position in the map Recti rect(position.x(), position.y(), static_cast<int>(size.x()), static_cast<int>(size.y())); (*itemRectMap)[item.overlayItem.p()] = rect; // Find next position, moving the cursor if (direction == OverlayItem::HORIZONTAL) { if ((corner == OverlayItem::TOP_LEFT) || (corner == OverlayItem::BOTTOM_LEFT)) { cursor.x() += (size.x() + border); } else { cursor.x() -= (size.x() + border); } } else if (direction == OverlayItem::VERTICAL) { if ((corner == OverlayItem::BOTTOM_LEFT) || (corner == OverlayItem::BOTTOM_RIGHT)) { cursor.y() += (size.y() + border); } else { cursor.y() -= (size.y() + border); } } else { CVF_FAIL_MSG("Unhandled OverlayItem::LayoutDirection"); } } } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void OverlayImage::render(OpenGLContext* oglContext, const Vec2i& position, const Vec2ui& size, bool software) { CVF_CALLSITE_OPENGL(oglContext); Camera projCam; projCam.setViewport(position.x(), position.y(), size.x(), size.y()); projCam.setProjectionAsPixelExact2D(); projCam.setViewMatrix(Mat4d::IDENTITY); // Turn off depth test RenderStateDepth depth(false, RenderStateDepth::LESS, false); depth.applyOpenGL(oglContext); float vertexArray[12]; float textureCoords[] = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; projCam.viewport()->applyOpenGL(oglContext, Viewport::DO_NOT_CLEAR); if (software) { // Create a POW2 texture for software rendering if needed if (m_image.notNull() && m_pow2Image.isNull() && (!Math::isPow2(m_image->width()) || !Math::isPow2(m_image->height()))) { m_pow2Image = new TextureImage; m_pow2Image->allocate(Math::roundUpPow2(m_image->width()), Math::roundUpPow2(m_image->height())); m_pow2Image->fill(Color4ub(Color3::BLACK)); for (uint y = 0; y < m_image->height(); ++y) { for (uint x = 0; x < m_image->width(); ++x) { m_pow2Image->setPixel(x, y, m_image->pixel(x, y)); } } } if (ShaderProgram::supportedOpenGL(oglContext)) { ShaderProgram::useNoProgram(oglContext); } #ifndef CVF_OPENGL_ES RenderStateMaterial_FF mat; mat.enableColorMaterial(true); mat.applyOpenGL(oglContext); RenderStateLighting_FF light(false); light.applyOpenGL(oglContext); if (m_textureBindings.isNull()) { // Use fixed function texture setup ref<Texture2D_FF> texture = new Texture2D_FF(m_pow2Image.notNull() ? m_pow2Image.p() : m_image.p()); texture->setWrapMode(Texture2D_FF::CLAMP); texture->setMinFilter(Texture2D_FF::NEAREST); texture->setMagFilter(Texture2D_FF::NEAREST); texture->setupTexture(oglContext); texture->setupTextureParams(oglContext); ref<RenderStateTextureMapping_FF> textureMapping = new RenderStateTextureMapping_FF(texture.p()); textureMapping->setTextureFunction(m_blendMode == TEXTURE_ALPHA ? RenderStateTextureMapping_FF::MODULATE : RenderStateTextureMapping_FF::DECAL); m_textureBindings = textureMapping; } #endif // Adjust texture coordinates if (m_pow2Image.notNull()) { float xMax = static_cast<float>(m_image->width())/static_cast<float>(m_pow2Image->width()); float yMax = static_cast<float>(m_image->height())/static_cast<float>(m_pow2Image->height()); textureCoords[2] = xMax; textureCoords[4] = xMax; textureCoords[5] = yMax; textureCoords[7] = yMax; } projCam.applyOpenGL(); } else { glBindBuffer(GL_ARRAY_BUFFER, 0); glEnableVertexAttribArray(ShaderProgram::VERTEX); glEnableVertexAttribArray(ShaderProgram::TEX_COORD_2F_0); glVertexAttribPointer(ShaderProgram::VERTEX, 3, GL_FLOAT, GL_FALSE, 0, vertexArray); glVertexAttribPointer(ShaderProgram::TEX_COORD_2F_0, 2, GL_FLOAT, GL_FALSE, 0, textureCoords); if (m_shaderProgram.isNull()) { ShaderProgramGenerator gen("OverlayImage_Shader", ShaderSourceProvider::instance()); gen.addVertexCode(ShaderSourceRepository::vs_MinimalTexture); if (m_blendMode == GLOBAL_ALPHA) { gen.addFragmentCode(ShaderSourceRepository::src_TextureGlobalAlpha); } else { gen.addFragmentCode(ShaderSourceRepository::src_Texture); } gen.addFragmentCode(ShaderSourceRepository::fs_Unlit); m_shaderProgram = gen.generate(); m_shaderProgram->linkProgram(oglContext); } if (m_shaderProgram->useProgram(oglContext)) { MatrixState projMatrixState(projCam); m_shaderProgram->clearUniformApplyTracking(); m_shaderProgram->applyFixedUniforms(oglContext, projMatrixState); } if (m_texture->textureOglId() == 0) { m_texture->setupTexture(oglContext); } if (m_textureBindings.isNull()) { cvf::RenderStateTextureBindings* textureBindings = new cvf::RenderStateTextureBindings; textureBindings->addBinding(m_texture.p(), m_sampler.p(), "u_texture2D"); m_textureBindings = textureBindings; } } float offset = 0.0f; Vec3f min(offset, offset, 0.0f); Vec3f max(static_cast<float>(size.x()) + offset, static_cast<float>(size.y()) + offset, 0.0f); // Setup the vertex array float* v1 = &vertexArray[0]; float* v2 = &vertexArray[3]; float* v3 = &vertexArray[6]; float* v4 = &vertexArray[9]; v1[0] = min.x(); v1[1] = min.y(); v1[2] = 0.0f; v2[0] = max.x(); v2[1] = min.y(); v2[2] = 0.0f; v3[0] = max.x(); v3[1] = max.y(); v3[2] = 0.0f; v4[0] = min.x(); v4[1] = max.y(); v4[2] = 0.0f; if (m_blendMode != NO_BLENDING) { RenderStateBlending blend; blend.configureTransparencyBlending(); blend.applyOpenGL(oglContext); } m_textureBindings->applyOpenGL(oglContext); if (software) { #ifndef CVF_OPENGL_ES glColor4f(1.0f, 1.0f, 1.0f, m_blendMode == GLOBAL_ALPHA ? m_alpha : 1.0f); glBegin(GL_TRIANGLE_FAN); glTexCoord2f(textureCoords[0], textureCoords[1]); glVertex3fv(v1); glTexCoord2f(textureCoords[2], textureCoords[3]); glVertex3fv(v2); glTexCoord2f(textureCoords[4], textureCoords[5]); glVertex3fv(v3); glTexCoord2f(textureCoords[6], textureCoords[7]); glVertex3fv(v4); glEnd(); #endif } else { if (m_blendMode == GLOBAL_ALPHA) { UniformFloat alphaUniform("u_alpha", m_alpha); m_shaderProgram->applyUniform(oglContext, alphaUniform); } glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } if (m_blendMode != NO_BLENDING) { RenderStateBlending blend; blend.applyOpenGL(oglContext); } RenderStateDepth resetDepth; resetDepth.applyOpenGL(oglContext); if (software) { #ifndef CVF_OPENGL_ES RenderStateTextureMapping_FF resetTextureMapping; resetTextureMapping.applyOpenGL(oglContext); #endif } if (!software) { glDisableVertexAttribArray(ShaderProgram::VERTEX); glDisableVertexAttribArray(ShaderProgram::TEX_COORD_2F_0); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void OverlayItems::addOverlayItemsVariousTypes() { // Setup the overlay items { ref<OverlayAxisCross> overlay = new OverlayAxisCross(m_camera.p(), new FixedAtlasFont(FixedAtlasFont::STANDARD)); overlay->setLayout(OverlayItem::VERTICAL, OverlayItem::BOTTOM_LEFT); m_renderSequence->firstRendering()->addOverlayItem(overlay.p()); } // Image overlay - Global Alpha { ref<TextureImage> img = cvfu::ImageJpeg::loadImage(m_testDataDir + "CeetronLogoDiffuse.jpg"); ref<OverlayImage> overlay = new OverlayImage(img.p()); overlay->setGlobalAlpha(0.7f); overlay->setBlending(cvf::OverlayImage::GLOBAL_ALPHA); overlay->setLayout(OverlayItem::VERTICAL, OverlayItem::BOTTOM_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(overlay.p()); } // Image overlay - Opaque small { ref<TextureImage> img = cvfu::ImageJpeg::loadImage(m_testDataDir + "CeetronLogoDiffuse.jpg"); ref<OverlayImage> overlay = new OverlayImage(img.p()); overlay->setPixelSize(cvf::Vec2ui(img->width()/2, img->height()/2)); overlay->setLayout(OverlayItem::VERTICAL, OverlayItem::BOTTOM_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(overlay.p()); } // Image overlay - Texture Alpha { ref<TextureImage> img = cvfu::ImageJpeg::loadImage(m_testDataDir + "CeetronLogoDiffuse.jpg"); // Create alpha values, as we cannot ready any format with alpha... for (cvf::uint y = 0; y < img->height(); ++y) { for (cvf::uint x = 0; x < img->width(); ++x) { cvf::Color4ub pixel = img->pixel(x, y); if (pixel.r() >= 245 && pixel.g() >= 245 && pixel.b() >= 245) { pixel.a() = 0; img->setPixel(x, y, pixel); } } } ref<OverlayImage> overlay = new OverlayImage(img.p()); overlay->setBlending(cvf::OverlayImage::TEXTURE_ALPHA); overlay->setLayout(OverlayItem::VERTICAL, OverlayItem::BOTTOM_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(overlay.p()); } ref<OverlayTextBox> tb1 = new OverlayTextBox(new FixedAtlasFont(FixedAtlasFont::STANDARD)); tb1->setText("This is the first text box"); tb1->setTextColor(Color3f(Color3::WHITE)); tb1->setLayout(OverlayItem::VERTICAL, OverlayItem::BOTTOM_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(tb1.p()); ref<OverlayTextBox> tb2 = new OverlayTextBox(new FixedAtlasFont(FixedAtlasFont::LARGE)); tb2->setText("This is LARGE text"); tb2->setDrawBackground(true); tb2->setDrawBorder(true); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::BOTTOM_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); ref<Font> font = new FixedAtlasFont(FixedAtlasFont::LARGE); ref<Font> fontStd = new FixedAtlasFont(FixedAtlasFont::STANDARD); { ref<OverlayTextBox> tb2 = new OverlayTextBox(font.p()); String text = "Lower Die"; tb2->setText(text); tb2->setSizeToFitText(); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::BOTTOM_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } { ref<OverlayTextBox> tb2 = new OverlayTextBox(font.p()); String text = "Billet"; tb2->setText(text); tb2->setSizeToFitText(); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::BOTTOM_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } { ref<OverlayTextBox> tb2 = new OverlayTextBox(font.p()); String text = "Upper Die - hard coded"; Vec2ui size = font->textExtent(text); size.x() += 10; size.y() += 10; tb2->setText(text); tb2->setPixelSize(size); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::BOTTOM_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } { ref<OverlayTextBox> tb2 = new OverlayTextBox(font.p()); String text = "Example View Title here"; tb2->setText(text); tb2->setTextColor(Color3f(0,0,0)); tb2->setDrawBorder(false); tb2->setDrawBackground(false); tb2->setSizeToFitText(); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::TOP_LEFT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } { ref<OverlayTextBox> tb2 = new OverlayTextBox(fontStd.p()); String text = "An example view description here"; tb2->setText(text); tb2->setDrawBorder(false); tb2->setSizeToFitText(); tb2->setDrawBackground(false); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::TOP_LEFT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } { ref<OverlayTextBox> tb2 = new OverlayTextBox(font.p()); String text = "Only background"; tb2->setText(text); tb2->setDrawBorder(false); tb2->setSizeToFitText(); tb2->setBackgroundColor(Color3::CRIMSON); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::TOP_LEFT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } { ref<OverlayTextBox> tb2 = new OverlayTextBox(font.p()); String text = "Only border"; tb2->setText(text); tb2->setDrawBackground(false); tb2->setSizeToFitText(); tb2->setBorderColor(Color3::GOLD); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::TOP_LEFT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } { ref<OverlayTextBox> tb2 = new OverlayTextBox(font.p()); String text = "Multi line overlay text\nLarge font"; tb2->setText(text); tb2->setSizeToFitText(); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::TOP_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } { ref<OverlayTextBox> tb2 = new OverlayTextBox(fontStd.p()); String text = "Multi line overlay text\nStandard font\nHard coded size"; Vec2ui size = fontStd->textExtent(text); size.x() += 10; size.y() += 50; tb2->setPixelSize(size); tb2->setText(text); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::TOP_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } { ref<OverlayTextBox> tb2 = new OverlayTextBox(fontStd.p()); String text = "Single line size to fit with border text GujYg"; tb2->setText(text); tb2->setSizeToFitText(); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::TOP_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } { ref<OverlayTextBox> tb2 = new OverlayTextBox(fontStd.p()); String text = "Single line size to fit no border text GujYg"; tb2->setDrawBorder(false); tb2->setText(text); tb2->setSizeToFitText(); tb2->setLayout(OverlayItem::VERTICAL, OverlayItem::TOP_RIGHT); m_renderSequence->firstRendering()->addOverlayItem(tb2.p()); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void OverlayTextBox::renderBackgroundAndBorder(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software) { CVF_CALLSITE_OPENGL(oglContext); // Prepare 2D pixel exact projection to draw texts Camera projCam; projCam.setViewport(position.x(), position.y(), size.x(), size.y()); projCam.setProjectionAsPixelExact2D(); projCam.setViewMatrix(Mat4d::IDENTITY); // Turn off depth test RenderStateDepth depth(false, RenderStateDepth::LESS, false); depth.applyOpenGL(oglContext); ref<ShaderProgram> backgroundShader; float vertexArray[12]; projCam.viewport()->applyOpenGL(oglContext, Viewport::DO_NOT_CLEAR); if (software) { if (ShaderProgram::supportedOpenGL(oglContext)) { ShaderProgram::useNoProgram(oglContext); } #ifndef CVF_OPENGL_ES RenderStateMaterial_FF mat; mat.enableColorMaterial(true); mat.applyOpenGL(oglContext); RenderStateLighting_FF light(false); light.applyOpenGL(oglContext); #endif projCam.applyOpenGL(); } else { glBindBuffer(GL_ARRAY_BUFFER, 0); glEnableVertexAttribArray(ShaderProgram::VERTEX); glVertexAttribPointer(ShaderProgram::VERTEX, 3, GL_FLOAT, GL_FALSE, 0, vertexArray); backgroundShader = oglContext->resourceManager()->getLinkedUnlitColorShaderProgram(oglContext); if (backgroundShader->useProgram(oglContext)) { MatrixState projMatrixState(projCam); backgroundShader->clearUniformApplyTracking(); backgroundShader->applyFixedUniforms(oglContext, projMatrixState); } } Vec3f min(1.0f, 1.0f, 0.0f); Vec3f max(static_cast<float>(size.x() - 1), static_cast<float>(size.y() - 1), 0.0f); // Setup the vertex array float* v1 = &vertexArray[0]; float* v2 = &vertexArray[3]; float* v3 = &vertexArray[6]; float* v4 = &vertexArray[9]; v1[0] = min.x(); v1[1] = min.y(); v1[2] = 0.0f; v2[0] = max.x(); v2[1] = min.y(); v2[2] = 0.0f; v3[0] = max.x(); v3[1] = max.y(); v3[2] = 0.0f; v4[0] = min.x(); v4[1] = max.y(); v4[2] = 0.0f; if (m_drawBackground) { if (software) { #ifndef CVF_OPENGL_ES glColor4fv(m_backgroundColor.ptr()); glBegin(GL_TRIANGLE_FAN); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glVertex3fv(v4); glEnd(); #endif } else { // Draw background UniformFloat backgroundColor("u_color", Color4f(m_backgroundColor)); backgroundShader->applyUniform(oglContext, backgroundColor); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } if (m_drawBorder) { if (software) { #ifndef CVF_OPENGL_ES glColor3fv(m_borderColor.ptr()); glBegin(GL_LINE_LOOP); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glVertex3fv(v4); glEnd(); #endif } else { UniformFloat borderColor("u_color", Color4f(m_borderColor)); backgroundShader->applyUniform(oglContext, borderColor); RenderStateLine line(static_cast<float>(3)); line.applyOpenGL(oglContext); // Draw border glDrawArrays(GL_LINE_LOOP, 0, 4); RenderStateLine resetLine; resetLine.applyOpenGL(oglContext); } } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void Rendering::calculateOverlayItemLayoutForSchemeAndCorner(OverlayItemRectMap* itemRectMap, OverlayItem::LayoutScheme layoutScheme, OverlayItem::AnchorCorner anchorCorner) { CVF_ASSERT(layoutScheme == OverlayItem::HORIZONTAL || layoutScheme == OverlayItem::VERTICAL); const int border = 3; const Vec2i vpSize = Vec2i(static_cast<int>(m_camera->viewport()->width()), static_cast<int>(m_camera->viewport()->height())); const Vec2i vpPos = Vec2i(m_camera->viewport()->x(), m_camera->viewport()->y()); Vec2i cursor(0,0); switch (anchorCorner) { case OverlayItem::TOP_LEFT: cursor.set(border, vpSize.y() - border); break; case OverlayItem::TOP_RIGHT: cursor.set(vpSize.x() - border, vpSize.y() - border); break; case OverlayItem::BOTTOM_LEFT: cursor.set(border, border); break; case OverlayItem::BOTTOM_RIGHT: cursor.set(vpSize.x() - border, border); break; default: cursor.set(border,border); } cursor += vpPos; // Adjust starting cursor position based on other already placed items in this anchor corner // The assumption here is that for each corner, the horizontal layout has already been added to the map if (layoutScheme == OverlayItem::VERTICAL) { OverlayItemRectMap::iterator it; for (it = itemRectMap->begin(); it != itemRectMap->end(); ++it) { const OverlayItem* placedItem = it->first; const Recti placedItemRect = it->second; if (placedItem->anchorCorner() == anchorCorner && placedItemRect.contains(cursor)) { if (anchorCorner == OverlayItem::BOTTOM_LEFT || anchorCorner == OverlayItem::BOTTOM_RIGHT) { cursor.y() += placedItemRect.height() + border; } else { cursor.y() -= placedItemRect.height() + border; } } } } const size_t numOverlayItems = m_overlayItems.size(); for (size_t i = 0; i < numOverlayItems; i++) { OverlayItem* item = m_overlayItems.at(i); if ((item->anchorCorner() == anchorCorner) && (item->layoutScheme() == layoutScheme)) { // Find this position and size Vec2i position = cursor; Vec2ui size = item->sizeHint(); if ((anchorCorner == OverlayItem::TOP_RIGHT) || (anchorCorner == OverlayItem::BOTTOM_RIGHT)) { position.x() -= size.x(); } if ((anchorCorner == OverlayItem::TOP_LEFT) || (anchorCorner == OverlayItem::TOP_RIGHT)) { position.y() -= size.y(); } // Store the position in the map Recti rect(position.x(), position.y(), static_cast<int>(size.x()), static_cast<int>(size.y())); (*itemRectMap)[item] = rect; // Find next position, moving the cursor if (layoutScheme == OverlayItem::HORIZONTAL) { if ((anchorCorner == OverlayItem::TOP_LEFT) || (anchorCorner == OverlayItem::BOTTOM_LEFT)) { cursor.x() += (size.x() + border); } else { cursor.x() -= (size.x() + border); } } else if (layoutScheme == OverlayItem::VERTICAL) { if ((anchorCorner == OverlayItem::BOTTOM_LEFT) || (anchorCorner == OverlayItem::BOTTOM_RIGHT)) { cursor.y() += (size.y() + border); } else { cursor.y() -= (size.y() + border); } } else { CVF_FAIL_MSG("Unhandled OverlayItem::LayoutDirection"); } } } }