Upgraded visualization libraries

Major refactoring of color legend framework
Added discrete log color legend
p4#: 18989
This commit is contained in:
Magne Sjaastad
2012-10-02 10:17:52 +02:00
parent 082560b2a5
commit 9c1ce7591e
163 changed files with 8917 additions and 3214 deletions

View File

@@ -31,7 +31,6 @@ cvfFramebufferObject.h
cvfGeometryBuilderDrawableGeo.h
cvfGlyph.h
cvfHitDetail.h
cvfLegendScalarMapper.h
cvfLibRender.h
cvfMatrixState.h
cvfOglRc.h
@@ -42,8 +41,11 @@ cvfOpenGLContextGroup.h
cvfOpenGLResourceManager.h
cvfOpenGLTypes.h
cvfOverlayAxisCross.h
cvfOverlayScalarMapperLegend.h
cvfOverlayColorLegend.h
cvfOverlayImage.h
cvfOverlayItem.h
cvfOverlayNavigationCube.h
cvfOverlayTextBox.h
cvfPrimitiveSet.h
cvfPrimitiveSetDirect.h
@@ -53,11 +55,23 @@ cvfPrimitiveSetIndexedUShort.h
cvfPrimitiveSetIndexedUShortScoped.h
cvfRenderbufferObject.h
cvfRenderState.h
cvfRenderStateBlending.h
cvfRenderStateColorMask.h
cvfRenderStateCullFace.h
cvfRenderStateDepth.h
cvfRenderStateFrontFace.h
cvfRenderStateLine.h
cvfRenderStatePoint.h
cvfRenderStatePolygonMode.h
cvfRenderStatePolygonOffset.h
cvfRenderStateSet.h
cvfRenderStateStencil.h
cvfRenderStateTextureBindings.h
cvfRenderStateTracker.h
cvfRenderState_FF.h
cvfSampler.h
cvfScalarMapper.h
cvfScalarMapperRangeBased.h
cvfScalarMapperContinuousLog.h
cvfScalarMapperContinuousLinear.h
cvfScalarMapperDiscreteLinear.h
@@ -95,7 +109,6 @@ cvfFontManager.cpp
cvfGeometryBuilderDrawableGeo.cpp
cvfGlyph.cpp
cvfHitDetail.cpp
#cvfLegendScalarMapper.cpp
cvfMatrixState.cpp
cvfOglRc.cpp
cvfOpenGLCapabilities.cpp
@@ -104,7 +117,11 @@ cvfOpenGLContextGroup.cpp
cvfOpenGLResourceManager.cpp
cvfOpenGL.cpp
cvfOverlayAxisCross.cpp
cvfOverlayScalarMapperLegend.cpp
cvfOverlayColorLegend.cpp
cvfOverlayImage.cpp
cvfOverlayItem.cpp
cvfOverlayNavigationCube.cpp
cvfOverlayTextBox.cpp
cvfPrimitiveSet.cpp
cvfPrimitiveSetDirect.cpp
@@ -114,10 +131,22 @@ cvfPrimitiveSetIndexedUIntScoped.cpp
cvfPrimitiveSetIndexedUShortScoped.cpp
cvfRenderbufferObject.cpp
cvfRenderState.cpp
cvfRenderState_FF.cpp
cvfRenderStateBlending.cpp
cvfRenderStateColorMask.cpp
cvfRenderStateCullFace.cpp
cvfRenderStateDepth.cpp
cvfRenderStateFrontFace.cpp
cvfRenderStateLine.cpp
cvfRenderStatePoint.cpp
cvfRenderStatePolygonMode.cpp
cvfRenderStatePolygonOffset.cpp
cvfRenderStateSet.cpp
cvfRenderStateStencil.cpp
cvfRenderStateTextureBindings.cpp
cvfRenderStateTracker.cpp
cvfRenderState_FF.cpp
cvfScalarMapper.cpp
cvfScalarMapperRangeBased.cpp
cvfScalarMapperContinuousLog.cpp
cvfScalarMapperContinuousLinear.cpp
cvfScalarMapperDiscreteLinear.cpp

View File

@@ -268,23 +268,56 @@ void Camera::setProjectionAsPixelExact2D()
/// the view to. The relativeDistance parameter specifies the distance from the camera to the
/// center of the bounding box
//--------------------------------------------------------------------------------------------------
void Camera::fitView(const BoundingBox& boundingBox, const Vec3d& dir, const Vec3d& up, double relativeDistance)
void Camera::fitView(const BoundingBox& boundingBox, const Vec3d& dir, const Vec3d& up, double distanceScaleFactor)
{
double boxRadius = boundingBox.radius();
CVF_ASSERT(projection() == PERSPECTIVE);
// Determine needed distance from center of model to eye point
double fovY = m_fieldOfViewYDeg;
double fovX = m_fieldOfViewYDeg*aspectRatio();
// TODO! !!! !! !!
CVF_UNUSED(distanceScaleFactor);
// The return values are the complete angle in degrees, get half in radians
fovX = Math::toRadians(fovX/2);
fovY = Math::toRadians(fovY/2);
cvf::Vec3d corners[8];
boundingBox.cornerVertices(corners);
// Use the largest distance
double dist1 = (fovX != 0) ? boxRadius*relativeDistance/Math::sin(fovX) : -1;
double dist2 = (fovY != 0) ? boxRadius*relativeDistance/Math::sin(fovY) : -1;
cvf::Vec3d upNorm = up.getNormalized();
cvf::Vec3d right = dir^up;
right.normalize();
cvf::Vec3d boxEyeNorm = (-dir).getNormalized();
double dist = CVF_MAX(dist1, dist2);
cvf::Plane planeTop;
planeTop.setFromPointAndNormal(boundingBox.center(), up);
cvf::Plane planeSide;
planeSide.setFromPointAndNormal(boundingBox.center(), right);
// m_fieldOfViewYDeg is the complete angle in degrees, get half in radians
double fovY = Math::toRadians(m_fieldOfViewYDeg/2.0);
double fovX = Math::atan(Math::tan(fovY)*aspectRatio());
double dist = 0;
for (size_t i = 0; i < 8; ++i)
{
cvf::Vec3d centerToCorner = corners[i] - boundingBox.center();
// local horizontal plane
cvf::Vec3d centerToCornerTop = planeTop.projectPoint(centerToCorner);
double rightCoord = centerToCornerTop*right;
double distRight = Math::abs(rightCoord/Math::tan(fovX));
distRight += centerToCornerTop*boxEyeNorm;
// local vertical plane
cvf::Vec3d centerToCornerSide = planeSide.projectPoint(centerToCorner);
double upCoord = centerToCornerSide*upNorm;
double distUp = Math::abs(upCoord/Math::tan(fovY));
distUp += (centerToCornerSide*boxEyeNorm);
// Adjust for the distance scale factor
distRight /= distanceScaleFactor;
distUp /= distanceScaleFactor;
dist = CVF_MAX(dist, distRight);
dist = CVF_MAX(dist, distUp);
}
// Avoid distances of 0 when model has no extent
if (!(dist > 0))
@@ -293,19 +326,68 @@ void Camera::fitView(const BoundingBox& boundingBox, const Vec3d& dir, const Vec
}
// Use old view direction, but look towards model center
Vec3d eye = boundingBox.center()- dir*dist;
Vec3d eye = boundingBox.center()- dir.getNormalized()*dist;
// Will update cached values
setFromLookAt(eye, boundingBox.center(), up);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Camera::fitViewOrtho(const BoundingBox& boundingBox, double eyeDist, const Vec3d& dir, const Vec3d& up, double adjustmentFactor)
{
// Algorithm:
// Project all points into the viewing plan. Find the distance along the right and up vector.
// Set the height of the frustum to this distance.
cvf::Vec3d corners[8];
boundingBox.cornerVertices(corners);
cvf::BoundingBox projBox;
cvf::Plane viewPlane;
viewPlane.setFromPointAndNormal(boundingBox.center(), -dir);
cvf::Vec3d upNorm = up.getNormalized();
cvf::Vec3d right = up^dir;
right.normalize();
double rightMin = cvf::UNDEFINED_DOUBLE_THRESHOLD;
double rightMax = -cvf::UNDEFINED_DOUBLE_THRESHOLD;
double upMin = cvf::UNDEFINED_DOUBLE_THRESHOLD;
double upMax = -cvf::UNDEFINED_DOUBLE_THRESHOLD;
for (size_t i = 0; i < 8; ++i)
{
cvf::Vec3d cornerInPlane = viewPlane.projectPoint(corners[i]);
cvf::Vec3d cornerVec = cornerInPlane-boundingBox.center();
double rightCoord = cornerVec*right;
rightMin = CVF_MIN(rightMin, rightCoord);
rightMax = CVF_MAX(rightMax, rightCoord);
double upCood = cornerVec*upNorm;
upMin = CVF_MIN(upMin, upCood);
upMax = CVF_MAX(upMax, upCood);
}
double deltaRight = rightMax - rightMin;
double deltaUp = upMax - upMin;
double newHeight = CVF_MAX(deltaUp, deltaRight/aspectRatio())/adjustmentFactor;
setProjectionAsOrtho(newHeight, m_nearPlane, m_farPlane);
Vec3d eye = boundingBox.center()- eyeDist*dir.getNormalized();
setFromLookAt(eye, boundingBox.center(), up);
}
//--------------------------------------------------------------------------------------------------
/// Set the front and back clipping planes close to the given bounding box (perspective projection)
///
/// Note that this will setup a perspective projection with the new clipping planes.
//--------------------------------------------------------------------------------------------------
void Camera::setClipPlanesFromBoundingBoxPerspective(const BoundingBox& boundingBox, double minNearPlaneDistance)
void Camera::setClipPlanesFromBoundingBox(const BoundingBox& boundingBox, double minNearPlaneDistance)
{
CVF_ASSERT(minNearPlaneDistance > 0);
@@ -321,7 +403,14 @@ void Camera::setClipPlanesFromBoundingBoxPerspective(const BoundingBox& bounding
if (nearPlane < minNearPlaneDistance) nearPlane = minNearPlaneDistance;
if (farPlane <= nearPlane) farPlane = nearPlane + 1.0;
setProjectionAsPerspective(m_fieldOfViewYDeg, nearPlane, farPlane);
if (projection() == PERSPECTIVE)
{
setProjectionAsPerspective(m_fieldOfViewYDeg, nearPlane, farPlane);
}
else
{
setProjectionAsOrtho(m_frontPlaneFrustumHeight, nearPlane, farPlane);
}
}
@@ -469,6 +558,42 @@ ref<Ray> Camera::rayFromWinCoord(int winCoordX, int winCoordY) const
}
//--------------------------------------------------------------------------------------------------
/// Construct a plane from a line specified in window coordinates
///
/// The plane will be constructed so that the specified line lies in the plane, and the plane
/// normal will be pointing left when moving along the line from start to end.
/// The coordinates (winCoordStart & winCoordEnd) are assumed to be in the window coordinate system
/// where <0,0> is in the top left corner.
//--------------------------------------------------------------------------------------------------
ref<Plane> Camera::planeFromLineWinCoord(Vec2i winCoordStart, Vec2i winCoordEnd) const
{
// Unproject works in OpenGL coord system with (0,0) in lower left corner, so flip the y-coordinates
winCoordStart.y() = static_cast<int>(m_viewport->height()) - winCoordStart.y();
winCoordEnd.y() = static_cast<int>(m_viewport->height()) - winCoordEnd.y();
Vec3d s0(0, 0, 0);
Vec3d e0(0, 0, 0);
Vec3d e1(0, 0, 0);
bool unprojOk = true;
unprojOk &= unproject(Vec3d(winCoordStart.x(), winCoordStart.y(), 0), &s0);
unprojOk &= unproject(Vec3d(winCoordEnd.x(), winCoordEnd.y(), 0), &e0);
unprojOk &= unproject(Vec3d(winCoordEnd.x(), winCoordEnd.y(), 1), &e1);
if (!unprojOk)
{
return NULL;
}
ref<Plane> plane = new Plane;
if (!plane->setFromPoints(s0, e0, e1))
{
return NULL;
}
return plane;
}
//--------------------------------------------------------------------------------------------------
/// Computes the maximum pixel area that the projected bounding box will occupy with the current camera settings.
///
@@ -684,7 +809,7 @@ void Camera::updateCachedValues()
// Update the cached frustum
m_cachedViewFrustum = computeViewFrustum();
// Update the front plane pixel size (height)
CVF_ASSERT(m_viewport.notNull());
uint vpWidth = m_viewport->width();
@@ -709,7 +834,7 @@ void Camera::updateCachedValues()
//--------------------------------------------------------------------------------------------------
Frustum Camera::computeViewFrustum() const
{
// See also
// See:
// http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf
// http://zach.in.tu-clausthal.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html

View File

@@ -63,8 +63,10 @@ public:
void setProjectionAsUnitOrtho();
void setProjectionAsPixelExact2D();
void fitView(const BoundingBox& boundingBox, const Vec3d& dir, const Vec3d& up, double relativeDistance = 1.0);
void setClipPlanesFromBoundingBoxPerspective(const BoundingBox& boundingBox, double minNearPlaneDistance = 0.01);
void fitView(const BoundingBox& boundingBox, const Vec3d& dir, const Vec3d& up, double coverageFactor = 0.9);
void fitViewOrtho(const BoundingBox& boundingBox, double eyeDist, const Vec3d& dir, const Vec3d& up, double coverageFactor = 0.9);
void setClipPlanesFromBoundingBox(const BoundingBox& boundingBox, double minNearPlaneDistance = 0.01);
const Mat4d& viewMatrix() const;
const Mat4d& invertedViewMatrix() const;
@@ -84,6 +86,7 @@ public:
const Viewport* viewport() const;
ref<Ray> rayFromWinCoord(int winCoordX, int winCoordY) const;
ref<Plane> planeFromLineWinCoord(Vec2i winCoordStart, Vec2i winCoordEnd) const;
bool unproject(const Vec3d& coord, Vec3d* out) const;
bool project(const Vec3d& point, Vec3d* out) const;

View File

@@ -30,10 +30,13 @@
#include "cvfGlyph.h"
#include "cvfCamera.h"
#include "cvfShaderProgram.h"
#include "cvfRenderState.h"
#include "cvfViewport.h"
#include "cvfGeometryUtils.h"
#include "cvfMatrixState.h"
#include "cvfRenderStatePoint.h"
#include "cvfRenderStateDepth.h"
#include "cvfRenderStatePolygonOffset.h"
#include "cvfRenderStateBlending.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
@@ -273,7 +276,7 @@ void DrawableText::renderText(OpenGLContext* oglContext, ShaderProgram* shaderPr
nudgeShader->clearUniformApplyTracking();
nudgeShader->applyFixedUniforms(oglContext, matrixState);
Point point(Point::PROGRAM_SIZE);
RenderStatePoint point(RenderStatePoint::PROGRAM_SIZE);
point.applyOpenGL(oglContext);
}
else
@@ -284,27 +287,27 @@ void DrawableText::renderText(OpenGLContext* oglContext, ShaderProgram* shaderPr
}
#ifndef CVF_OPENGL_ES
Material_FF mat;
RenderStateMaterial_FF mat;
mat.enableColorMaterial(true);
Lighting_FF noLight(false);
RenderStateLighting_FF noLight(false);
noLight.applyOpenGL(oglContext);
#endif
}
Depth visibleCheckDepthRS(true, Depth::LEQUAL, false);
RenderStateDepth visibleCheckDepthRS(true, RenderStateDepth::LEQUAL, false);
visibleCheckDepthRS.applyOpenGL(oglContext);
PolygonOffset po;
RenderStatePolygonOffset po;
po.enablePointMode(true);
po.setFactor(-3.0f);
po.setUnits(-3.0f);
po.applyOpenGL(oglContext);
Blending addBlend;
RenderStateBlending addBlend;
addBlend.enableBlending(true);
addBlend.setFunction(Blending::ONE, Blending::ONE);
addBlend.setEquation(Blending::FUNC_ADD);
addBlend.setFunction(RenderStateBlending::ONE, RenderStateBlending::ONE);
addBlend.setEquation(RenderStateBlending::FUNC_ADD);
addBlend.applyOpenGL(oglContext);
}
@@ -327,19 +330,19 @@ void DrawableText::renderText(OpenGLContext* oglContext, ShaderProgram* shaderPr
if (m_checkPosVisible)
{
PolygonOffset resetPO;
RenderStatePolygonOffset resetPO;
resetPO.applyOpenGL(oglContext);
Blending resetBlend;
RenderStateBlending resetBlend;
resetBlend.applyOpenGL(oglContext);
#ifndef CVF_OPENGL_ES
if (!shaderProgram)
{
Material_FF mat;
RenderStateMaterial_FF mat;
mat.applyOpenGL(oglContext);
Lighting_FF light;
RenderStateLighting_FF light;
light.applyOpenGL(oglContext);
}
#endif

View File

@@ -50,51 +50,108 @@ Font::~Font()
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Font::lineSpacing()
{
ref<Glyph> glyph = getGlyph(L'A');
float spacing = cvf::Math::floor(static_cast<float>(glyph->height())*1.75f);
return spacing;
}
//--------------------------------------------------------------------------------------------------
/// Get the extent (width and height) of the given text with this font in pixels
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui Font::textExtent(const String& text)
{
Vec2ui textBB(0,0);
std::vector<cvf::String> lines = text.split("\n");
int minHeight = std::numeric_limits<int>::max();
int maxHeight = std::numeric_limits<int>::min();
size_t numCharacters = text.size();
for (size_t j = 0; j < numCharacters; j++)
float maxLineWidth = 0;
uint textHeight = 0;
uint lineSpacing = static_cast<uint>(this->lineSpacing());
for (size_t lineIdx = 0; lineIdx < lines.size(); ++lineIdx)
{
wchar_t character = text[j];
ref<Glyph> glyph = getGlyph(character);
String line = lines[lineIdx];
size_t numCharacters = line.size();
float lineWidth = 0;
// Find bottom and top with regards to baseline (Y = 0)
int minY = static_cast<int>(glyph->horizontalBearingY()) - static_cast<int>(glyph->height());
int maxY = glyph->horizontalBearingY();
if (minHeight > minY) minHeight = minY;
if (maxHeight < maxY) maxHeight = maxY;
uint charWidth = 0;
if (j < (numCharacters - 1))
for (size_t j = 0; j < numCharacters; ++j)
{
charWidth = advance(character, text[j + 1]);
wchar_t character = line[j];
// Jump to the next character in the string, if any
if (j < (numCharacters - 1))
{
float advance = static_cast<float>(this->advance(character, text[j + 1]));
lineWidth += advance;
}
else
{
ref<Glyph> glyph = getGlyph(character);
lineWidth += static_cast<float>(glyph->width()) + static_cast<float>(glyph->horizontalBearingX());
}
}
maxLineWidth = CVF_MAX(lineWidth, maxLineWidth);
if (lineIdx == 0)
{
ref<Glyph> glyph = getGlyph(L'A');
textHeight += glyph->height();
}
else
{
charWidth = glyph->width() + glyph->horizontalBearingX();
textHeight += lineSpacing;
}
textBB.x() += charWidth;
}
if (maxHeight < minHeight)
{
return Vec2ui(0,0);
}
textBB.y() = static_cast<uint>(maxHeight - minHeight);
return textBB;
return Vec2ui(static_cast<uint>(maxLineWidth), textHeight);
}
// Vec2ui textBB(0,0);
//
// int minHeight = std::numeric_limits<int>::max();
// int maxHeight = std::numeric_limits<int>::min();
//
// size_t numCharacters = text.size();
// for (size_t j = 0; j < numCharacters; j++)
// {
// wchar_t character = text[j];
// ref<Glyph> glyph = getGlyph(character);
//
// // Find bottom and top with regards to baseline (Y = 0)
// int minY = static_cast<int>(glyph->horizontalBearingY()) - static_cast<int>(glyph->height());
// int maxY = glyph->horizontalBearingY();
//
// if (minHeight > minY) minHeight = minY;
// if (maxHeight < maxY) maxHeight = maxY;
//
// uint charWidth = 0;
//
// if (j < (numCharacters - 1))
// {
// charWidth = advance(character, text[j + 1]);
// }
// else
// {
// charWidth = glyph->width() + glyph->horizontalBearingX();
// }
//
// textBB.x() += charWidth;
// }
//
// if (maxHeight < minHeight)
// {
// return Vec2ui(0,0);
// }
//
// textBB.y() = static_cast<uint>(maxHeight - minHeight);
//
// return textBB;
} // namespace cvf

View File

@@ -43,8 +43,11 @@ public:
virtual ref<Glyph> getGlyph(wchar_t character) = 0;
virtual uint advance(wchar_t character, wchar_t nextCharacter) = 0;
virtual bool isEmpty() = 0;
float lineSpacing();
Vec2ui textExtent(const String& text);
};
} // namespace cvf

View File

@@ -32,11 +32,11 @@ namespace cvf {
//==================================================================================================
///
/// \class cvf::FrameBufferObject
/// \class cvf::FramebufferObject
/// \ingroup Render
///
/// Encapsulates FBOs which are used to redirect OpenGL (and thus shader) output from the default
/// Window Framebuffer to a number of custom buffers (either textures or RenderBuffers
/// Window Framebuffer to a number of custom buffers (either textures or renderbuffers)
///
//==================================================================================================
@@ -232,7 +232,7 @@ void FramebufferObject::applyOpenGL(OpenGLContext* oglContext)
createdNewFrameBuffer = true;
}
glBindFramebuffer(GL_FRAMEBUFFER, OglRc::safeOglId(m_oglRcBuffer.p()));
bind(oglContext);
bool attachmentsModified = createdNewFrameBuffer;
@@ -419,7 +419,11 @@ void FramebufferObject::applyOpenGL(OpenGLContext* oglContext)
}
}
#ifndef CVF_OPENGL_ES
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilRenderBuffer->renderbufferOglId());
#else
CVF_FAIL_MSG("Not supported on iOS");
#endif
m_depthAttachmentVersionTick = m_depthStencilRenderBuffer->versionTick();
}
@@ -439,7 +443,11 @@ void FramebufferObject::applyOpenGL(OpenGLContext* oglContext)
if (m_depthStencilTexture2d->textureType() == Texture::TEXTURE_2D)
{
#ifndef CVF_OPENGL_ES
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilTexture2d->textureOglId(), 0);
#else
CVF_FAIL_MSG("Not supported on iOS");
#endif
}
else if (m_depthStencilTexture2d->textureType() == Texture::TEXTURE_RECTANGLE)
{
@@ -462,6 +470,18 @@ void FramebufferObject::applyOpenGL(OpenGLContext* oglContext)
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::bind(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_ASSERT(OglRc::safeOglId(m_oglRcBuffer.p()) != 0);
glBindFramebuffer(GL_FRAMEBUFFER, m_oglRcBuffer->oglId());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -475,6 +495,8 @@ void FramebufferObject::useDefaultWindowFramebuffer(OpenGLContext* oglContext)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
#endif
CVF_CHECK_OGL(oglContext);
}
@@ -564,7 +586,7 @@ bool FramebufferObject::isFramebufferComplete(OpenGLContext* oglContext, String*
{
CVF_CALLSITE_OPENGL(oglContext);
glBindFramebuffer(GL_FRAMEBUFFER, OglRc::safeOglId(m_oglRcBuffer.p()));
bind(oglContext);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)

View File

@@ -57,6 +57,7 @@ public:
void attachDepthStencilTexture2d(Texture* texture);
void applyOpenGL(OpenGLContext* oglContext);
void bind(OpenGLContext* oglContext) const;
static void useDefaultWindowFramebuffer(OpenGLContext* oglContext);
void deleteFramebuffer(OpenGLContext* oglContext);

View File

@@ -23,8 +23,9 @@
#include "cvfMath.h"
#include "cvfTextureImage.h"
#include "cvfTexture.h"
#include "cvfRenderState.h"
#include "cvfSampler.h"
#include "cvfRenderStateTextureBindings.h"
#ifndef CVF_OPENGL_ES
#include "cvfTexture2D_FF.h"
#include "cvfRenderState_FF.h"
@@ -249,7 +250,7 @@ void Glyph::setupAndBindTexture(OpenGLContext* oglContext, bool software)
#ifndef CVF_OPENGL_ES
if (renderStateType == RenderState::TEXTURE_MAPPING_FF)
{
TextureMapping_FF* texMapping = static_cast<TextureMapping_FF*>(m_textureBindings.p());
RenderStateTextureMapping_FF* texMapping = static_cast<RenderStateTextureMapping_FF*>(m_textureBindings.p());
texMapping->setupTexture(oglContext);
texMapping->applyOpenGL(oglContext);
return;
@@ -262,7 +263,7 @@ void Glyph::setupAndBindTexture(OpenGLContext* oglContext, bool software)
{
if (renderStateType == RenderState::TEXTURE_BINDINGS)
{
TextureBindings* texBindings = static_cast<TextureBindings*>(m_textureBindings.p());
RenderStateTextureBindings* texBindings = static_cast<RenderStateTextureBindings*>(m_textureBindings.p());
texBindings->setupTextures(oglContext);
texBindings->applyOpenGL(oglContext);
return;
@@ -331,8 +332,8 @@ void Glyph::setupAndBindTexture(OpenGLContext* oglContext, bool software)
texture->setupTexture(oglContext);
texture->setupTextureParams(oglContext);
ref<TextureMapping_FF> textureMapping = new TextureMapping_FF(texture.p());
textureMapping->setTextureFunction(TextureMapping_FF::MODULATE);
ref<RenderStateTextureMapping_FF> textureMapping = new RenderStateTextureMapping_FF(texture.p());
textureMapping->setTextureFunction(RenderStateTextureMapping_FF::MODULATE);
m_textureBindings = textureMapping;
#endif
@@ -347,7 +348,7 @@ void Glyph::setupAndBindTexture(OpenGLContext* oglContext, bool software)
ref<Texture> texture = new Texture(m_textureImage.p());
texture->setupTexture(oglContext);
TextureBindings* textureBindings = new TextureBindings(texture.p(), sampler.p(), "dummy");
RenderStateTextureBindings* textureBindings = new RenderStateTextureBindings(texture.p(), sampler.p(), "dummy");
textureBindings->setupTextures(oglContext);
m_textureBindings = textureBindings;

View File

@@ -76,7 +76,7 @@ private:
// Texture info
ref<TextureImage> m_textureImage; // Pre-rendered image of m_character
ref<FloatArray> m_textureCoordinates; // Texture coordinates of where in the m_texgtureImage to find the given pre-rendered character
ref<RenderState> m_textureBindings; // For shader based rendering this is a TextureBindings object, while software rendering uses TextureMapping_FF instead
ref<RenderState> m_textureBindings; // For shader based rendering this is a TextureBindings object, while software rendering uses RenderStateTextureMapping_FF instead
};
} // namespace cvf

View File

@@ -46,6 +46,8 @@
#include "cvfOpenGLTypes.h"
#include "cvfOverlayAxisCross.h"
#include "cvfOverlayColorLegend.h"
#include "cvfOverlayImage.h"
#include "cvfOverlayScalarMapperLegend.h"
#include "cvfOverlayItem.h"
#include "cvfOverlayTextBox.h"
#include "cvfPrimitiveSet.h"
@@ -55,10 +57,26 @@
#include "cvfPrimitiveSetIndexedUIntScoped.h"
#include "cvfRenderbufferObject.h"
#include "cvfRenderState.h"
#include "cvfRenderStateBlending.h"
#include "cvfRenderStateColorMask.h"
#include "cvfRenderStateCullFace.h"
#include "cvfRenderStateDepth.h"
#include "cvfRenderStateFrontFace.h"
#include "cvfRenderStateLine.h"
#include "cvfRenderStatePoint.h"
#include "cvfRenderStatePolygonMode.h"
#include "cvfRenderStatePolygonOffset.h"
#include "cvfRenderStateSet.h"
#include "cvfRenderStateStencil.h"
#include "cvfRenderStateTextureBindings.h"
#include "cvfRenderStateTracker.h"
#include "cvfSampler.h"
#include "cvfScalarMapper.h"
#include "cvfScalarMapperRangeBased.h"
#include "cvfScalarMapperDiscreteLinear.h"
#include "cvfScalarMapperDiscreteLog.h"
#include "cvfScalarMapperContinuousLinear.h"
#include "cvfScalarMapperContinuousLog.h"
#include "cvfScalarMapperUniformLevels.h"
#include "cvfShader.h"
#include "cvfShaderSourceProvider.h"
@@ -78,3 +96,4 @@
#include "cvfRenderState_FF.h"
#include "cvfTexture2D_FF.h"
#endif

View File

@@ -74,6 +74,17 @@ MatrixState::MatrixState(const Vec2ui& viewportPosition, const Vec2ui& viewportS
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void MatrixState::setViewMatrix(const Mat4d& viewMatrix)
{
m_viewMatrix = Mat4f(viewMatrix);
m_viewProjectionMatrix = m_projectionMatrix*m_viewMatrix;
m_versionTick++;
}
//--------------------------------------------------------------------------------------------------
/// Computes height of a pixel at unit distance in world system
//--------------------------------------------------------------------------------------------------

View File

@@ -37,6 +37,8 @@ public:
MatrixState(const Camera& camera);
MatrixState(const Vec2ui& viewportPosition, const Vec2ui& viewportSize, const Mat4d& projectionMatrix, const Mat4d& viewMatrix);
void setViewMatrix(const Mat4d& viewMatrix);
void setModelMatrix(const Mat4d& modelMatrix);
void clearModelMatrix();

View File

@@ -74,6 +74,33 @@ OpenGLCapabilities& OpenGLCapabilities::operator=(const OpenGLCapabilities& rhs)
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGLCapabilities::operator==(const OpenGLCapabilities& rhs) const
{
if (m_capabilityFlags == rhs.m_capabilityFlags &&
m_openGLMajorVersion == rhs.m_openGLMajorVersion &&
m_supportsFixedFunction == rhs.m_supportsFixedFunction)
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGLCapabilities::operator!=(const OpenGLCapabilities& rhs) const
{
return !(*this == rhs);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -48,6 +48,8 @@ public:
~OpenGLCapabilities();
OpenGLCapabilities& operator=(const OpenGLCapabilities& rhs);
bool operator==(const OpenGLCapabilities& rhs) const;
bool operator!=(const OpenGLCapabilities& rhs) const;
bool hasCapability(Capability capability) const;
void addCapablity(Capability capability);

View File

@@ -255,12 +255,12 @@ void OverlayAxisCross::renderAxisImmediateMode(OpenGLContext* oglContext, const
m_axis->renderImmediateMode(oglContext, matrixState);
// Draw X axis triangle
Material_FF xMaterial(Material_FF::PURE_RED);
RenderStateMaterial_FF xMaterial(RenderStateMaterial_FF::PURE_RED);
xMaterial.applyOpenGL(oglContext);
m_xAxisTriangle->renderImmediateMode(oglContext, matrixState);
// Draw Y axis triangle
Material_FF yMaterial(Material_FF::PURE_GREEN);
RenderStateMaterial_FF yMaterial(RenderStateMaterial_FF::PURE_GREEN);
yMaterial.applyOpenGL(oglContext);
m_yAxisTriangle->renderImmediateMode(oglContext, matrixState);
#endif // CVF_OPENGL_ES

View File

@@ -35,13 +35,12 @@
#include "cvfMatrixState.h"
#include "cvfBufferObjectManaged.h"
#include "cvfGlyph.h"
#include "cvfRenderStateDepth.h"
#include "cvfRenderStateLine.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#else
#include "cvfRenderState.h"
#endif
#include "cvfLegendScalarMapper.h"
namespace cvf {
@@ -61,11 +60,17 @@ namespace cvf {
OverlayColorLegend::OverlayColorLegend(Font* font)
: m_sizeHint(200, 200),
m_color(Color3::BLACK),
m_lineColor(Color3::BLACK),
m_lineWidth(1),
m_font(font)
{
CVF_ASSERT(font);
CVF_ASSERT(!font->isEmpty());
m_levelColors.reserve(2);
m_levelColors.add(Color3::RED);
m_levelColors.add(Color3::BLUE);
m_tickValues.reserve(3);
m_tickValues.add(0.0);
m_tickValues.add(0.5);
@@ -112,17 +117,13 @@ cvf::Vec2ui OverlayColorLegend::minimumSize()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::setScalarMapper(const LegendScalarMapper* scalarMapper)
void OverlayColorLegend::configureLevels(const Color3ubArray& levelColors, const DoubleArray& tickValues)
{
m_scalarMapper = scalarMapper;
if (m_scalarMapper.notNull())
{
std::vector<double> levelValues;
m_scalarMapper->majorLevels(&levelValues);
CVF_ASSERT(levelColors.size() > 0);
CVF_ASSERT(levelColors.size() + 1 == tickValues.size());
m_tickValues.assign(levelValues);
}
m_levelColors = levelColors;
m_tickValues = tickValues;
}
@@ -153,6 +154,8 @@ const Color3f& OverlayColorLegend::color() const
}
//--------------------------------------------------------------------------------------------------
/// Set the title (text that will be rendered above the legend)
///
@@ -210,6 +213,32 @@ void OverlayColorLegend::renderSoftware(OpenGLContext* oglContext, const Vec2ui&
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OverlayColorLegend::pick(uint oglXCoord, uint oglYCoord, const Vec2ui& position, const Vec2ui& size)
{
Rectui oglRect(position, size.x(), size.y());
OverlayColorLegendLayoutInfo layoutInViewPortCoords(oglRect.min(), Vec2ui(oglRect.width(), oglRect.height()));
layoutInfo(&layoutInViewPortCoords);
Vec2ui legendBarOrigin = oglRect.min();
legendBarOrigin.x() += static_cast<uint>(layoutInViewPortCoords.legendRect.min().x());
legendBarOrigin.y() += static_cast<uint>(layoutInViewPortCoords.legendRect.min().y());
Rectui legendBarRect = Rectui(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;
}
//--------------------------------------------------------------------------------------------------
/// Set up camera/viewport and render
//--------------------------------------------------------------------------------------------------
@@ -277,7 +306,7 @@ void OverlayColorLegend::setupTextDrawer(TextDrawer* textDrawer, OverlayColorLeg
float textY = static_cast<float>(layout->legendRect.min().y() + layout->tickPixelPos->get(it));
// Always draw first and last tick label. For all others, skip drawing if text ends up
// on top of the previous label.
// on top of the previous label
if (it != 0 && it != (numTicks - 1))
{
if (cvf::Math::abs(textY - lastVisibleTextY) < overlapTolerance)
@@ -285,15 +314,6 @@ void OverlayColorLegend::setupTextDrawer(TextDrawer* textDrawer, OverlayColorLeg
m_visibleTickLabels.push_back(false);
continue;
}
// Make sure it does not overlap the last tick as well
float lastTickY = static_cast<float>(layout->legendRect.max().y() );
if (cvf::Math::abs(textY - lastTickY) < overlapTolerance)
{
m_visibleTickLabels.push_back(false);
continue;
}
}
double tickValue = m_tickValues[it];
@@ -328,7 +348,7 @@ void OverlayColorLegend::renderLegend(OpenGLContext* oglContext, OverlayColorLeg
CVF_TIGHT_ASSERT(layout->size.x() > 0);
CVF_TIGHT_ASSERT(layout->size.y() > 0);
Depth depth(false);
RenderStateDepth depth(false);
depth.applyOpenGL(oglContext);
// All vertices. Initialized here to set Z to zero once and for all.
@@ -338,22 +358,25 @@ void OverlayColorLegend::renderLegend(OpenGLContext* oglContext, OverlayColorLeg
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f
};
// Per vector convenience pointers
float* v0 = &vertexArray[0];
float* v1 = &vertexArray[3];
float* v2 = &vertexArray[6];
float* v3 = &vertexArray[9];
float* v4 = &vertexArray[12];
float* v1 = &vertexArray[0]; // x0, y0
float* v2 = &vertexArray[3]; // x1, y0
float* v3 = &vertexArray[6]; // tickX, y0
float* v4 = &vertexArray[9]; // x0, y1
float* v5 = &vertexArray[12]; // x1, y1
float* v6 = &vertexArray[15]; // tickX, y1
// Constant coordinates
v0[0] = v3[0] = layout->x0;
v1[0] = v4[0] = layout->x1;
v1[0] = v4[0] = layout->x0;
v2[0] = v5[0] = layout->x1;
// Connects
static const ushort trianglesConnects[] = { 0, 1, 4, 0, 4, 3 };
static const ushort linesConnects[] = { 0, 3, 1, 4, 0, 2, 3, 5 };
ref<ShaderProgram> shaderProgram = oglContext->resourceManager()->getLinkedUnlitColorShaderProgram(oglContext);
CVF_TIGHT_ASSERT(shaderProgram.notNull());
@@ -368,98 +391,49 @@ void OverlayColorLegend::renderLegend(OpenGLContext* oglContext, OverlayColorLeg
glEnableVertexAttribArray(ShaderProgram::VERTEX);
glVertexAttribPointer(ShaderProgram::VERTEX, 3, GL_FLOAT, GL_FALSE, 0, vertexArray);
// Render color bar as one colored quad per pixel
int legendHeightPixelCount = static_cast<int>(layout->tickPixelPos->get(m_tickValues.size()-1) - layout->tickPixelPos->get(0) + 0.01);
if (m_scalarMapper.notNull())
// Render colored quads and lines
size_t numColors = m_levelColors.size();
CVF_ASSERT(numColors == m_tickValues.size() - 1);
size_t ic;
for (ic = 0; ic < numColors; ic++)
{
int iPx;
for (iPx = 0; iPx < legendHeightPixelCount; iPx++)
const Color3ub& clr = m_levelColors[ic];
float y0 = static_cast<float>(layout->legendRect.min().y() + layout->tickPixelPos->get(ic));
float y1 = static_cast<float>(layout->legendRect.min().y() + layout->tickPixelPos->get(ic + 1));
// Dynamic coordinates for rectangle
v1[1] = v2[1] = y0;
v4[1] = v5[1] = y1;
// Dynamic coordinates for tickmarks-lines
v3[0] = m_visibleTickLabels[ic] ? layout->tickX : layout->x1;
v6[0] = m_visibleTickLabels[ic + 1] ? layout->tickX : layout->x1;
v3[1] = y0;
v6[1] = y1;
// Draw filled rectangle elements
{
const Color3ub& clr = m_scalarMapper->mapToColor(m_scalarMapper->domainValue((iPx+0.5)/legendHeightPixelCount));
float y0 = static_cast<float>(layout->legendRect.min().y() + iPx);
float y1 = static_cast<float>(layout->legendRect.min().y() + iPx + 1);
// Dynamic coordinates for rectangle
v0[1] = v1[1] = y0;
v3[1] = v4[1] = y1;
// Draw filled rectangle elements
{
UniformFloat uniformColor("u_color", Color4f(Color3f(clr)));
shaderProgram->applyUniform(oglContext, uniformColor);
UniformFloat uniformColor("u_color", Color4f(Color3f(clr)));
shaderProgram->applyUniform(oglContext, uniformColor);
#ifdef CVF_OPENGL_ES
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, trianglesConnects);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, trianglesConnects);
#else
glDrawRangeElements(GL_TRIANGLES, 0, 4, 6, GL_UNSIGNED_SHORT, trianglesConnects);
glDrawRangeElements(GL_TRIANGLES, 0, 4, 6, GL_UNSIGNED_SHORT, trianglesConnects);
#endif
}
}
}
// Render frame
// Dynamic coordinates for tickmarks-lines
bool isRenderingFrame = true;
if (isRenderingFrame)
{
v0[0] = v2[0] = layout->legendRect.min().x()-0.5f;
v1[0] = v3[0] = layout->legendRect.max().x()-0.5f;
v0[1] = v1[1] = layout->legendRect.min().y()-0.5f;
v2[1] = v3[1] = layout->legendRect.max().y()-0.5f;
static const ushort frameConnects[] = { 0, 1, 1, 3, 3, 2, 2, 0};
UniformFloat uniformColor("u_color", Color4f(m_color));
shaderProgram->applyUniform(oglContext, uniformColor);
#ifdef CVF_OPENGL_ES
glDrawElements(GL_LINES, 8, GL_UNSIGNED_SHORT, frameConnects);
#else
glDrawRangeElements(GL_LINES, 0, 3, 8, GL_UNSIGNED_SHORT, frameConnects);
#endif
}
// Render tickmarks
bool isRenderingTicks = true;
if (isRenderingTicks)
{
// Constant coordinates
v0[0] = layout->x0;
v1[0] = layout->x1 - 0.5f*(layout->tickX - layout->x1) - 0.5f;
v2[0] = layout->x1;
v3[0] = layout->tickX - 0.5f*(layout->tickX - layout->x1) - 0.5f;
v4[0] = layout->tickX;
static const ushort tickLinesWithLabel[] = { 0, 4 };
static const ushort tickLinesWoLabel[] = { 2, 3 };
size_t ic;
for (ic = 0; ic < m_tickValues.size(); ic++)
// Draw legend lines
{
float y0 = static_cast<float>(layout->legendRect.min().y() + layout->tickPixelPos->get(ic) - 0.5f);
// Dynamic coordinates for tickmarks-lines
v0[1] = v1[1] = v2[1] = v3[1] = v4[1] = y0;
UniformFloat uniformColor("u_color", Color4f(m_color));
shaderProgram->applyUniform(oglContext, uniformColor);
const ushort * linesConnects;
if ( m_visibleTickLabels[ic])
{
linesConnects = tickLinesWithLabel;
}
else
{
linesConnects = tickLinesWoLabel;
}
RenderStateLine line(static_cast<float>(m_lineWidth));
line.applyOpenGL(oglContext);
UniformFloat uniformColor("u_color", Color4f(m_lineColor));
shaderProgram->applyUniform(oglContext, uniformColor);
#ifdef CVF_OPENGL_ES
glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, linesConnects);
glDrawElements(GL_LINES, 8, GL_UNSIGNED_SHORT, linesConnects);
#else
glDrawRangeElements(GL_LINES, 0, 4, 2, GL_UNSIGNED_SHORT, linesConnects);
glDrawRangeElements(GL_LINES, 0, 5, 8, GL_UNSIGNED_SHORT, linesConnects);
#endif
}
}
@@ -470,9 +444,12 @@ void OverlayColorLegend::renderLegend(OpenGLContext* oglContext, OverlayColorLeg
shaderProgram->useNoProgram(oglContext);
// Reset render states
Depth resetDepth;
RenderStateDepth resetDepth;
resetDepth.applyOpenGL(oglContext);
RenderStateLine resetLine;
resetLine.applyOpenGL(oglContext);
CVF_CHECK_OGL(oglContext);
}
@@ -490,10 +467,10 @@ void OverlayColorLegend::renderLegendImmediateMode(OpenGLContext* oglContext, Ov
CVF_TIGHT_ASSERT(layout->size.x() > 0);
CVF_TIGHT_ASSERT(layout->size.y() > 0);
Depth depth(false);
RenderStateDepth depth(false);
depth.applyOpenGL(oglContext);
Lighting_FF lighting(false);
RenderStateLighting_FF lighting(false);
lighting.applyOpenGL(oglContext);
// All vertices. Initialized here to set Z to zero once and for all.
@@ -504,111 +481,68 @@ void OverlayColorLegend::renderLegendImmediateMode(OpenGLContext* oglContext, Ov
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f
};
// Per vector convenience pointers
float* v0 = &vertexArray[0];
float* v1 = &vertexArray[3];
float* v2 = &vertexArray[6];
float* v3 = &vertexArray[9];
float* v4 = &vertexArray[12];
float* v1 = &vertexArray[0]; // x0, y0
float* v2 = &vertexArray[3]; // x1, y0
float* v3 = &vertexArray[6]; // tickX, y0
float* v4 = &vertexArray[9]; // x0, y1
float* v5 = &vertexArray[12]; // x1, y1
float* v6 = &vertexArray[15]; // tickX, y1
// Constant coordinates
v0[0] = v3[0] = layout->x0;
v1[0] = v4[0] = layout->x1;
v1[0] = v4[0] = layout->x0;
v2[0] = v5[0] = layout->x1;
// Render color bar as one colored quad per pixel
int legendHeightPixelCount = static_cast<int>(layout->tickPixelPos->get(m_tickValues.size() - 1) - layout->tickPixelPos->get(0) + 0.01);
if (m_scalarMapper.notNull())
// Render colored quads and lines
size_t numColors = m_levelColors.size();
CVF_ASSERT(numColors == m_tickValues.size() - 1);
size_t ic;
for (ic = 0; ic < numColors; ic++)
{
int iPx;
for (iPx = 0; iPx < legendHeightPixelCount; iPx++)
{
const Color3ub& clr = m_scalarMapper->mapToColor(m_scalarMapper->domainValue((iPx+0.5)/legendHeightPixelCount));
float y0 = static_cast<float>(layout->legendRect.min().y() + iPx);
float y1 = static_cast<float>(layout->legendRect.min().y() + iPx + 1);
const Color3ub& levelColor = m_levelColors[ic];
float y0 = static_cast<float>(layout->margins.y() + layout->tickPixelPos->get(ic));
float y1 = static_cast<float>(layout->margins.y() + layout->tickPixelPos->get(ic + 1));
// Dynamic coordinates for rectangle
v0[1] = v1[1] = y0;
v3[1] = v4[1] = y1;
// Dynamic coordinates for rectangle
v1[1] = v2[1] = y0;
v4[1] = v5[1] = y1;
// Draw filled rectangle elements
glColor3ubv(clr.ptr());
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v4);
glVertex3fv(v3);
glEnd();
}
}
// Dynamic coordinates for tickmarks-lines
v3[0] = m_visibleTickLabels[ic] ? layout->tickX : layout->x1;
v6[0] = m_visibleTickLabels[ic + 1] ? layout->tickX : layout->x1;
v3[1] = y0;
v6[1] = y1;
// Render frame
// Dynamic coordinates for tickmarks-lines
bool isRenderingFrame = true;
if (isRenderingFrame)
{
v0[0] = v2[0] = layout->legendRect.min().x()-0.5f;
v1[0] = v3[0] = layout->legendRect.max().x()-0.5f;
v0[1] = v1[1] = layout->legendRect.min().y()-0.5f;
v2[1] = v3[1] = layout->legendRect.max().y()-0.5f;
glColor3fv(m_color.ptr());
glBegin(GL_LINES);
glVertex3fv(v0);
// Draw filled rectangle elements
glColor3ubv(levelColor.ptr());
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(v1);
glVertex3fv(v1);
glVertex3fv(v3);
glVertex3fv(v3);
glVertex3fv(v2);
glVertex3fv(v2);
glVertex3fv(v0);
glVertex3fv(v5);
glVertex3fv(v4);
glEnd();
}
// Render tickmarks
bool isRenderingTicks = true;
if (isRenderingTicks)
{
// Constant coordinates
v0[0] = layout->x0;
v1[0] = layout->x1 - 0.5f*(layout->tickX - layout->x1) - 0.5f;
v2[0] = layout->x1;
v3[0] = layout->tickX - 0.5f*(layout->tickX - layout->x1) - 0.5f;
v4[0] = layout->tickX;
size_t ic;
for (ic = 0; ic < m_tickValues.size(); ic++)
{
float y0 = static_cast<float>(layout->legendRect.min().y() + layout->tickPixelPos->get(ic) - 0.5f);
// Dynamic coordinates for tickmarks-lines
v0[1] = v1[1] = v2[1] = v3[1] = v4[1] = y0;
glColor3fv(m_color.ptr());
glBegin(GL_LINES);
if ( m_visibleTickLabels[ic])
{
glVertex3fv(v0);
glVertex3fv(v4);
}
else
{
glVertex3fv(v2);
glVertex3fv(v3);
}
glEnd();
}
// Draw legend lines
glColor3fv(m_color.ptr());
glBegin(GL_LINES);
glVertex3fv(v1);
glVertex3fv(v4);
glVertex3fv(v2);
glVertex3fv(v5);
glVertex3fv(v1);
glVertex3fv(v3);
glVertex3fv(v4);
glVertex3fv(v6);
glEnd();
}
// Reset render states
Lighting_FF resetLighting;
RenderStateLighting_FF resetLighting;
resetLighting.applyOpenGL(oglContext);
Depth resetDepth;
RenderStateDepth resetDepth;
resetDepth.applyOpenGL(oglContext);
CVF_CHECK_OGL(oglContext);
@@ -641,22 +575,79 @@ void OverlayColorLegend::layoutInfo(OverlayColorLegendLayoutInfo* layout)
layout->x1 = layout->margins.x() + layout->legendRect.width();
layout->tickX = layout->x1 + 5;
// Build array containing the pixel positions of all the ticks
size_t numTicks = m_tickValues.size();
layout->tickPixelPos = new DoubleArray(numTicks);
size_t i;
for (i = 0; i < numTicks; i++)
if (numTicks < 1)
{
double t;
if (m_scalarMapper.isNull()) t = 0;
else t = m_scalarMapper->normalizedLevelPosition(m_tickValues[i]);
t = Math::clamp(t, 0.0, 1.1);
layout->tickPixelPos->set(i, t*layout->legendRect.height());
return;
}
// Get legend range (the slightly odd test on the range should guard against any NaNs
double minVal = m_tickValues[0];
double maxVal = m_tickValues[numTicks - 1];
double valueRange = (maxVal - minVal);
if (!(valueRange >= 0))
{
layout->tickPixelPos = NULL;
return;
}
// Build array containing the pixel positions of all the ticks
layout->tickPixelPos = new DoubleArray(numTicks);
if (valueRange > 0)
{
size_t i;
for (i = 0; i < numTicks; i++)
{
double t = (m_tickValues[i] - minVal)/valueRange;
t = Math::clamp(t, 0.0, 1.1);
layout->tickPixelPos->set(i, t*layout->legendRect.height());
}
}
else
{
size_t i;
for (i = 0; i < numTicks; i++)
{
layout->tickPixelPos->set(i, static_cast<double>(i)*(layout->legendRect.height()/static_cast<double>(numTicks)));
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::setLineColor(const Color3f& lineColor)
{
m_lineColor = lineColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Color3f& OverlayColorLegend::lineColor() const
{
return m_lineColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::setLineWidth(int lineWidth)
{
m_lineWidth = lineWidth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int OverlayColorLegend::lineWidth() const
{
return m_lineWidth;
}
} // namespace cvf

View File

@@ -31,7 +31,6 @@ class Font;
class ShaderProgram;
class MatrixState;
class TextDrawer;
class LegendScalarMapper;
//==================================================================================================
@@ -76,16 +75,22 @@ public:
virtual Vec2ui sizeHint();
virtual Vec2ui maximumSize();
virtual Vec2ui minimumSize();
void setScalarMapper(const LegendScalarMapper* scalarMapper);
virtual void render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size);
virtual void renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size);
virtual bool pick(uint oglXCoord, uint oglYCoord, const Vec2ui& position, const Vec2ui& size);
void configureLevels(const Color3ubArray& levelColors, const DoubleArray& tickValues);
void setSizeHint(const Vec2ui& size);
void setColor(const Color3f& color);
const Color3f& color() const;
void setLineColor(const Color3f& lineColor);
const Color3f& lineColor() const;
void setLineWidth(int lineWidth);
int lineWidth() const;
void setTitle(const String& title);
String title() const;
@@ -99,16 +104,17 @@ protected:
void layoutInfo(OverlayColorLegendLayoutInfo* layout);
protected:
Color3ubArray m_levelColors; // Colors for n levels
DoubleArray m_tickValues; // Ticks between each level + top and bottom of legend (n+1 entries)
std::vector<bool> m_visibleTickLabels; // Skip tick labels ending up on top of previous visible label
Vec2ui m_sizeHint; // Pixel size of the color legend area
Color3f m_color;
Color3f m_lineColor;
int m_lineWidth;
std::vector<String> m_titleStrings;
ref<Font> m_font;
cref<LegendScalarMapper> m_scalarMapper;
};
}

View File

@@ -0,0 +1,317 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfOverlayImage.h"
#include "cvfMatrixState.h"
#include "cvfCamera.h"
#include "cvfShaderProgram.h"
#include "cvfOpenGL.h"
#include "cvfViewport.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfUniform.h"
#include "cvfTextureImage.h"
#include "cvfSampler.h"
#include "cvfTexture.h"
#include "cvfShaderProgramGenerator.h"
#include "cvfShaderSourceRepository.h"
#include "cvfShaderSourceProvider.h"
#include "cvfShaderProgram.h"
#include "cvfRenderStateDepth.h"
#include "cvfRenderStateTextureBindings.h"
#include "cvfRenderStateBlending.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#endif
namespace cvf {
//==================================================================================================
///
/// \class cvf::OverlayImage
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor. The specified font is used to draw all the text
//--------------------------------------------------------------------------------------------------
OverlayImage::OverlayImage(TextureImage* image)
: m_alpha(1.0f)
{
CVF_ASSERT(image);
m_size.x() = image->width();
m_size.y() = image->height();
m_blendMode = NO_BLENDING;
m_sampler = new cvf::Sampler;
m_sampler->setWrapMode(cvf::Sampler::CLAMP_TO_EDGE);
m_sampler->setMinFilter(cvf::Sampler::NEAREST);
m_sampler->setMagFilter(cvf::Sampler::NEAREST);
setImage(image);
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
OverlayImage::~OverlayImage()
{
}
//--------------------------------------------------------------------------------------------------
/// Returns the wanted size in pixels
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayImage::sizeHint()
{
return m_size;
}
//--------------------------------------------------------------------------------------------------
/// Returns the maximum size of the text box in pixels
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayImage::maximumSize()
{
return sizeHint();
}
//--------------------------------------------------------------------------------------------------
/// Returns the minimum size of the text box in pixels
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayImage::minimumSize()
{
return sizeHint();
}
//--------------------------------------------------------------------------------------------------
/// Render using Shaders
//--------------------------------------------------------------------------------------------------
void OverlayImage::render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
render(oglContext, position, size, false);
}
//--------------------------------------------------------------------------------------------------
/// Render using Fixed Function
//--------------------------------------------------------------------------------------------------
void OverlayImage::renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
render(oglContext, position, size, true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayImage::render(OpenGLContext* oglContext, const Vec2ui& 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)
{
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);
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);
}
}
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_texture->textureOglId() == 0)
{
m_texture->setupTexture(oglContext);
}
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_alpha);
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);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayImage::setImage(TextureImage* image)
{
m_image = image;
m_texture = new Texture(image);
m_textureBindings = new cvf::RenderStateTextureBindings;
m_textureBindings->addBinding(m_texture.p(), m_sampler.p(), "u_texture2D");
}
//--------------------------------------------------------------------------------------------------
/// Set the size (in pixels) of the text box
//--------------------------------------------------------------------------------------------------
void OverlayImage::setPixelSize( const Vec2ui& size )
{
m_size = size;
}
//--------------------------------------------------------------------------------------------------
/// Returns the text shown in the text box
//--------------------------------------------------------------------------------------------------
const TextureImage* OverlayImage::image() const
{
return m_image.p();
}
//--------------------------------------------------------------------------------------------------
/// Set the transparency of the image. 1.0 = opaque, 0.0 = invisible
//--------------------------------------------------------------------------------------------------
void OverlayImage::setGlobalAlpha(float alphaFactor)
{
m_alpha = alphaFactor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayImage::setBlending(Blending mode)
{
m_blendMode = mode;
}
} // namespace cvf

View File

@@ -0,0 +1,80 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfOverlayItem.h"
namespace cvf {
class TextureImage;
class Sampler;
class RenderStateTextureBindings;
class Texture;
class ShaderProgram;
//==================================================================================================
//
// Overlay text box
//
//==================================================================================================
class OverlayImage : public OverlayItem
{
public:
enum Blending
{
NO_BLENDING,
GLOBAL_ALPHA,
TEXTURE_ALPHA
};
public:
OverlayImage(TextureImage* image);
~OverlayImage();
virtual Vec2ui sizeHint();
virtual Vec2ui maximumSize();
virtual Vec2ui minimumSize();
virtual void render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size);
virtual void renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size);
void setImage(TextureImage* image);
void setPixelSize(const Vec2ui& size);
void setGlobalAlpha(float alphaFactor);
void setBlending(Blending mode);
const TextureImage* image() const;
private:
void render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software);
private:
Vec2ui m_size;
ref<TextureImage> m_image;
ref<Sampler> m_sampler;
ref<RenderStateTextureBindings> m_textureBindings;
ref<Texture> m_texture;
ref<ShaderProgram> m_shaderProgram;
Blending m_blendMode;
float m_alpha;
};
}

View File

@@ -0,0 +1,62 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfOverlayTextBox.h"
#include "cvfDrawableText.h"
#include "cvfMatrixState.h"
#include "cvfCamera.h"
#include "cvfShaderProgram.h"
#include "cvfOpenGL.h"
#include "cvfViewport.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfUniform.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#endif
namespace cvf {
//==================================================================================================
///
/// \class cvf::OverlayItem
/// \ingroup Render
///
/// A base class for all overlay items
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Do hit test on the overlay item. Base class only does a check
//--------------------------------------------------------------------------------------------------
bool OverlayItem::pick(uint oglXCoord, uint oglYCoord, const Vec2ui& position, const Vec2ui& size)
{
Rectui oglRect(position, size.x(), size.y());
if ((oglXCoord > oglRect.min().x()) && (oglXCoord < oglRect.max().x()) &&
(oglYCoord > oglRect.min().y()) && (oglYCoord < oglRect.max().y()))
{
return true;
}
return false;
}
} // namespace cvf

View File

@@ -21,6 +21,7 @@
#include "cvfObject.h"
#include "cvfVector2.h"
#include "cvfRect.h"
namespace cvf {
@@ -58,6 +59,7 @@ public:
virtual void render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size) = 0;
virtual void renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size) = 0;
virtual bool pick(uint oglXCoord, uint oglYCoord, const Vec2ui& position, const Vec2ui& size);
};
}

View File

@@ -0,0 +1,725 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfOverlayNavigationCube.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfGeometryBuilderDrawableGeo.h"
#include "cvfGeometryUtils.h"
#include "cvfViewport.h"
#include "cvfCamera.h"
#include "cvfTextDrawer.h"
#include "cvfFont.h"
#include "cvfShaderProgram.h"
#include "cvfUniform.h"
#include "cvfMatrixState.h"
#include "cvfDrawableVectors.h"
#include "cvfGeometryBuilderTriangles.h"
#include "cvfArrowGenerator.h"
#include "cvfBufferObjectManaged.h"
#include "cvfDrawableText.h"
#include "cvfTextureImage.h"
#include "cvfPrimitiveSet.h"
#include "cvfPrimitiveSetIndexedUShort.h"
#include "cvfShaderProgramGenerator.h"
#include "cvfShaderSourceProvider.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#endif
namespace cvf {
//==================================================================================================
///
/// \class cvf::OverlayNavigationCube
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
OverlayNavigationCube::OverlayNavigationCube(Camera* camera, Font* font)
: m_camera(camera),
m_xLabel("ax"),
m_yLabel("by"),
m_zLabel("cz"),
m_textColor(Color3::BLACK),
m_font(font),
m_size(120, 120)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OverlayNavigationCube::~OverlayNavigationCube()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::setAxisLabels( const String& xLabel, const String& yLabel, const String& zLabel )
{
// Clipping of axis label text is depends on m_size and
// z-part of axisMatrix.setTranslation(Vec3d(0, 0, -4.4)) defined in OverlayNavigationCube::render()
CVF_ASSERT (xLabel.size() < 5 && yLabel.size() < 5 && zLabel.size() < 5);
m_xLabel = xLabel;
m_yLabel = yLabel;
m_zLabel = zLabel;
}
//--------------------------------------------------------------------------------------------------
/// Set color of the axis labels
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::setAxisLabelsColor(const Color3f& color)
{
m_textColor = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayNavigationCube::sizeHint()
{
return m_size;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayNavigationCube::maximumSize()
{
return sizeHint();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayNavigationCube::minimumSize()
{
return sizeHint();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::setSize(const Vec2ui& size)
{
m_size = size;
}
//--------------------------------------------------------------------------------------------------
/// Hardware rendering using shader programs
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
Mat4d viewMatrix = m_camera->viewMatrix();
render(oglContext, position, size, false, viewMatrix);
}
//--------------------------------------------------------------------------------------------------
/// Software rendering
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
Mat4d viewMatrix = m_camera->viewMatrix();
render(oglContext, position, size, true, viewMatrix);
}
//--------------------------------------------------------------------------------------------------
/// Set up camera/viewport and render
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::render(OpenGLContext* oglContext, const Vec2ui& 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);
}
//--------------------------------------------------------------------------------------------------
/// Draw the axis
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::renderAxis(OpenGLContext* oglContext, const MatrixState& matrixState)
{
CVF_ASSERT(m_axis.notNull());
OpenGLResourceManager* resourceManager = oglContext->resourceManager();
ref<ShaderProgram> vectorProgram = resourceManager->getLinkedVectorDrawerShaderProgram(oglContext);
if (vectorProgram->useProgram(oglContext))
{
vectorProgram->clearUniformApplyTracking();
vectorProgram->applyFixedUniforms(oglContext, matrixState);
}
// Draw X, Y and Z vectors
m_axis->render(oglContext, vectorProgram.p(), matrixState);
}
//--------------------------------------------------------------------------------------------------
/// Draw the axis using immediate mode OpenGL
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::renderAxisImmediateMode(OpenGLContext* oglContext, const MatrixState& matrixState)
{
#ifdef CVF_OPENGL_ES
CVF_FAIL_MSG("Not supported on OpenGL ES");
#else
m_axis->renderImmediateMode(oglContext, matrixState);
#endif // CVF_OPENGL_ES
}
//--------------------------------------------------------------------------------------------------
/// Create the geometry used to draw the axis (vector arrows) and the two triangles
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::createAxisGeometry(bool software)
{
CVF_ASSERT(m_axis.isNull());
// Axis colors
ref<Color3fArray> colorArray = new Color3fArray;
colorArray->resize(3);
colorArray->set(0, Color3::RED); // X axis
colorArray->set(1, Color3::GREEN); // Y axis
colorArray->set(2, Color3::BLUE); // Z axis
// Positions of the vectors - All in origo
Vec3f cp[8];
navCubeCornerPoints(cp);
ref<cvf::Vec3fArray> vertexArray = new Vec3fArray;
vertexArray->resize(3);
vertexArray->set(0, cp[0]); // X axis
vertexArray->set(1, cp[0]); // Y axis
vertexArray->set(2, cp[0]); // Z axis
// Direction & magnitude of the vectors
ref<cvf::Vec3fArray> vectorArray = new Vec3fArray;
vectorArray->resize(3);
vectorArray->set(0, Vec3f::X_AXIS); // X axis
vectorArray->set(1, Vec3f::Y_AXIS); // Y axis
vectorArray->set(2, Vec3f::Z_AXIS); // Z axis
// Create the arrow glyph for the vector drawer
GeometryBuilderTriangles arrowBuilder;
ArrowGenerator gen;
gen.setShaftRelativeRadius(0.045f);
gen.setHeadRelativeRadius(0.12f);
gen.setHeadRelativeLength(0.2f);
gen.setNumSlices(30);
gen.generate(&arrowBuilder);
if (software)
{
m_axis = new DrawableVectors();
}
else
{
m_axis = new DrawableVectors("u_transformationMatrix", "u_color");
}
m_axis->setVectors(vertexArray.p(), vectorArray.p());
m_axis->setColors(colorArray.p());
m_axis->setGlyph(arrowBuilder.trianglesUShort().p(), arrowBuilder.vertices().p());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::renderCubeGeos(OpenGLContext* oglContext, bool software, const MatrixState& matrixState)
{
CVF_UNUSED(software);
for (size_t i = 0; i < m_cubeGeos.size(); ++i)
{
m_cubeGeos[i]->render(oglContext, m_cubeGeoShader.p(), matrixState);
}
}
//--------------------------------------------------------------------------------------------------
/// Draw the axis labels
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::renderAxisLabels(OpenGLContext* oglContext, bool software, const MatrixState& matrixState)
{
// Multiply with 1.08 will slightly pull the labels away from the corresponding arrow head
Vec3f xPos(1.08f, 0, 0);
Vec3f yPos(0, 1.08f, 0);
Vec3f zPos(0, 0, 1.08f);
DrawableText drawableText;
drawableText.setFont(m_font.p());
drawableText.setCheckPosVisible(false);
drawableText.setDrawBorder(false);
drawableText.setDrawBackground(false);
drawableText.setVerticalAlignment(TextDrawer::CENTER);
drawableText.setTextColor(m_textColor);
if (!m_xLabel.isEmpty()) drawableText.addText(m_xLabel, xPos);
if (!m_yLabel.isEmpty()) drawableText.addText(m_yLabel, yPos);
if (!m_zLabel.isEmpty()) drawableText.addText(m_zLabel, zPos);
// Do the actual rendering
// -----------------------------------------------
if (software)
{
drawableText.renderSoftware(oglContext, matrixState);
}
else
{
ref<ShaderProgram> textShader = oglContext->resourceManager()->getLinkedTextShaderProgram(oglContext);
drawableText.render(oglContext, textShader.p(), matrixState);
}
}
//--------------------------------------------------------------------------------------------------
/// Face (with local indices):
/// 7---------6 4 3
/// /| /| |z |---|----------|---|
/// / | / | | / y |TL | TOP |TR |
/// 4---------5 | | / |---|----------|---|
/// | 3------|--2 *---x | | | |
/// | / | / | L | CENTER | R |
/// |/ |/ | | | |
/// 0---------1 |---|----------|---|
/// |BL | BOTTOM |BR |
/// |---|----------|---|
/// 1 2
///
/// Items:
/// Faces:
/// +X : VT_NCI_X_POS : RIGHT : 0 2 6 5
/// -X : VT_NCI_X_NEG : LEFT : 3 0 4 7
/// +Y : VT_NCI_Y_POS : BACK : 2 3 7 6
/// -Y : VT_NCI_Y_NEG : FRONT : 0 1 5 4
/// +Z : VT_NCI_Z_POS : TOP : 4 5 6 7
/// -Z : VT_NCI_Z_NEG : BOTTOM : 3 2 1 0
///
/// Corners:
/// 0 : VT_NCI_CORNER_XN_YN_ZN
/// 1 : VT_NCI_CORNER_XP_YN_ZN
/// 2 : VT_NCI_CORNER_XP_YP_ZN
/// 3 : VT_NCI_CORNER_XN_YP_ZN
/// 4 : VT_NCI_CORNER_XN_YN_ZP
/// 5 : VT_NCI_CORNER_XP_YN_ZP
/// 6 : VT_NCI_CORNER_XP_YP_ZP
/// 7 : VT_NCI_CORNER_XN_YP_ZP
///
/// Edges:
/// 01: VT_NCI_EDGE_YN_ZN
/// 12: VT_NCI_EDGE_XP_ZN
/// 23: VT_NCI_EDGE_YP_ZN
/// 03: VT_NCI_EDGE_XN_ZN
/// 45: VT_NCI_EDGE_YN_ZP
/// 56: VT_NCI_EDGE_XP_ZP
/// 67: VT_NCI_EDGE_YP_ZP
/// 47: VT_NCI_EDGE_XN_ZP
/// 04: VT_NCI_EDGE_XN_YN
/// 15: VT_NCI_EDGE_XP_YN
/// 26: VT_NCI_EDGE_XP_YP
/// 37: VT_NCI_EDGE_XN_YP
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::createCubeGeos()
{
Vec3f cp[8];
navCubeCornerPoints(cp);
m_cubeGeos.clear();
createCubeFaceGeos(NCF_Y_NEG, cp[0], cp[1], cp[5], cp[4]);//, m_yNegAxisName, m_yFaceColor, m_textureNegYAxis.p()); // Front
createCubeFaceGeos(NCF_Y_POS, cp[2], cp[3], cp[7], cp[6]);//, m_yPosAxisName, m_yFaceColor, m_texturePosYAxis.p()); // Back
createCubeFaceGeos(NCF_Z_POS, cp[4], cp[5], cp[6], cp[7]);//, m_zPosAxisName, m_zFaceColor, m_texturePosZAxis.p()); // Top
createCubeFaceGeos(NCF_Z_NEG, cp[3], cp[2], cp[1], cp[0]);//, m_zNegAxisName, m_zFaceColor, m_textureNegZAxis.p()); // Bottom
createCubeFaceGeos(NCF_X_NEG, cp[3], cp[0], cp[4], cp[7]);//, m_xNegAxisName, m_xFaceColor, m_textureNegXAxis.p()); // left
createCubeFaceGeos(NCF_X_POS, cp[1], cp[2], cp[6], cp[5]);//, m_xPosAxisName, m_xFaceColor, m_texturePosXAxis.p()); // Right
}
//--------------------------------------------------------------------------------------------------
/// Face (with local indices):
/// 4 3
/// |z |---|----------|---|
/// | / y |TL | TOP |TR |
/// | / |---|----------|---|
/// *---x | | | |
/// | L | CENTER | R |
/// | | | |
/// |---|----------|---|
/// |BL | BOTTOM |BR |
/// |---|----------|---|
/// 1 2
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::createCubeFaceGeos(NavCubeFace face, Vec3f p1, Vec3f p2, Vec3f p3, Vec3f p4)//, const String& name, const Color3f& baseColor, TextureImage* texture)
{
// Get the orientation vectors for the face
// Vec3f vNormal, vUp, vRight;
// faceOrientation(face, &vNormal, &vUp, &vRight);
float fCornerFactor = 0.175f;
Vec3f p12 = p1 + (p2 - p1)*fCornerFactor;
Vec3f p14 = p1 + (p4 - p1)*fCornerFactor;
Vec3f pi1 = p1 + (p12 - p1) + (p14 - p1);
Vec3f p21 = p2 + (p1 - p2)*fCornerFactor;
Vec3f p23 = p2 + (p3 - p2)*fCornerFactor;
Vec3f pi2 = p2 + (p21 - p2) + (p23 - p2);
Vec3f p32 = p3 + (p2 - p3)*fCornerFactor;
Vec3f p34 = p3 + (p4 - p3)*fCornerFactor;
Vec3f pi3 = p3 + (p32 - p3) + (p34 - p3);
Vec3f p41 = p4 + (p1 - p4)*fCornerFactor;
Vec3f p43 = p4 + (p3 - p4)*fCornerFactor;
Vec3f pi4 = p4 + (p41 - p4) + (p43 - p4);
// Bottom left
m_cubeItemType.push_back(navCubeItem(face, NCFI_BOTTOM_LEFT));
m_cubeGeos.push_back(createQuadGeo(p1, p12, pi1, p14).p());
// Bottom right
m_cubeItemType.push_back(navCubeItem(face, NCFI_BOTTOM_RIGHT));
m_cubeGeos.push_back(createQuadGeo(p2, p23, pi2, p21).p());
// Top right
m_cubeItemType.push_back(navCubeItem(face, NCFI_TOP_RIGHT));
m_cubeGeos.push_back(createQuadGeo(p3, p34, pi3, p32).p());
// Top left
m_cubeItemType.push_back(navCubeItem(face, NCFI_TOP_LEFT));
m_cubeGeos.push_back(createQuadGeo(p4, p41, pi4, p43).p());
// Bottom
m_cubeItemType.push_back(navCubeItem(face, NCFI_BOTTOM));
m_cubeGeos.push_back(createQuadGeo(p12, p21, pi2, pi1).p());
// Top
m_cubeItemType.push_back(navCubeItem(face, NCFI_TOP));
m_cubeGeos.push_back(createQuadGeo(p34, p43, pi4, pi3).p());
// Right
m_cubeItemType.push_back(navCubeItem(face, NCFI_RIGHT));
m_cubeGeos.push_back(createQuadGeo(p23, p32, pi3, pi2).p());
// Left
m_cubeItemType.push_back(navCubeItem(face, NCFI_LEFT));
m_cubeGeos.push_back(createQuadGeo(p41, p14, pi1, pi4).p());
// Inner part
m_cubeItemType.push_back(navCubeItem(face, NCFI_CENTER));
m_cubeGeos.push_back(createQuadGeo(pi1, pi2, pi3, pi4).p());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<DrawableGeo> OverlayNavigationCube::createQuadGeo(const Vec3f& v1, const Vec3f& v2, const Vec3f& v3, const Vec3f& v4)
{
ref<DrawableGeo> geo = new DrawableGeo;
ref<Vec3fArray> vertexArray = new Vec3fArray(4);
vertexArray->set(0, v1);
vertexArray->set(1, v2);
vertexArray->set(2, v3);
vertexArray->set(3, v4);
geo->setVertexArray(vertexArray.p());
ref<cvf::UShortArray> indices = new cvf::UShortArray(6);
indices->set(0, 0);
indices->set(1, 1);
indices->set(2, 2);
indices->set(3, 0);
indices->set(4, 2);
indices->set(5, 3);
ref<cvf::PrimitiveSetIndexedUShort> primSet = new cvf::PrimitiveSetIndexedUShort(cvf::PT_TRIANGLES);
primSet->setIndices(indices.p());
geo->addPrimitiveSet(primSet.p());
return geo;
}
//--------------------------------------------------------------------------------------------------
/// 7---------6
/// /| /| |z
/// / | / | | / y
/// 4---------5 | | /
/// | 3------|--2 *---x
/// | / | /
/// |/ |/
/// 0---------1
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::navCubeCornerPoints(Vec3f points[8])
{
float fBoxLength = 0.65f;
Vec3f min(-fBoxLength/2.0f, -fBoxLength/2.0f, -fBoxLength/2.0f);
Vec3f max(fBoxLength/2.0f, fBoxLength/2.0f, fBoxLength/2.0f);
points[0].set(min.x(), min.y(), min.z());
points[1].set(max.x(), min.y(), min.z());
points[2].set(max.x(), max.y(), min.z());
points[3].set(min.x(), max.y(), min.z());
points[4].set(min.x(), min.y(), max.z());
points[5].set(max.x(), min.y(), max.z());
points[6].set(max.x(), max.y(), max.z());
points[7].set(min.x(), max.y(), max.z());
}
/*************************************************************************************************
*//**
* Convert face + faceItem to VTNavCubeItem
*
*************************************************************************************************/
OverlayNavigationCube::NavCubeItem OverlayNavigationCube::navCubeItem(NavCubeFace face, NavCubeFaceItem faceItem) const
{
NavCubeItem item = NCI_NONE;
switch(face)
{
case NCF_X_POS:
{
switch(faceItem)
{
case NCFI_CENTER: item = NCI_FACE_X_POS; break;
case NCFI_TOP: item = NCI_EDGE_XP_ZP; break;
case NCFI_BOTTOM: item = NCI_EDGE_XP_ZN; break;
case NCFI_LEFT: item = NCI_EDGE_XP_YN; break;
case NCFI_RIGHT: item = NCI_EDGE_XP_YP; break;
case NCFI_TOP_LEFT: item = NCI_CORNER_XP_YN_ZP; break;
case NCFI_TOP_RIGHT: item = NCI_CORNER_XP_YP_ZP; break;
case NCFI_BOTTOM_LEFT: item = NCI_CORNER_XP_YN_ZN; break;
case NCFI_BOTTOM_RIGHT: item = NCI_CORNER_XP_YP_ZN; break;
case NCFI_NONE: item = NCI_NONE; break;
}
break;
}
case NCF_X_NEG:
{
switch(faceItem)
{
case NCFI_CENTER: item = NCI_FACE_X_NEG; break;
case NCFI_TOP: item = NCI_EDGE_XN_ZP; break;
case NCFI_BOTTOM: item = NCI_EDGE_XN_ZN; break;
case NCFI_LEFT: item = NCI_EDGE_XN_YP; break;
case NCFI_RIGHT: item = NCI_EDGE_XN_YN; break;
case NCFI_TOP_LEFT: item = NCI_CORNER_XN_YP_ZP; break;
case NCFI_TOP_RIGHT: item = NCI_CORNER_XN_YN_ZP; break;
case NCFI_BOTTOM_LEFT: item = NCI_CORNER_XN_YP_ZN; break;
case NCFI_BOTTOM_RIGHT: item = NCI_CORNER_XN_YN_ZN; break;
case NCFI_NONE: item = NCI_NONE; break;
}
break;
}
case NCF_Y_POS:
{
switch(faceItem)
{
case NCFI_CENTER: item = NCI_FACE_Y_POS; break;
case NCFI_TOP: item = NCI_EDGE_YP_ZP; break;
case NCFI_BOTTOM: item = NCI_EDGE_YP_ZN; break;
case NCFI_LEFT: item = NCI_EDGE_XP_YP; break;
case NCFI_RIGHT: item = NCI_EDGE_XN_YP; break;
case NCFI_TOP_LEFT: item = NCI_CORNER_XP_YP_ZP; break;
case NCFI_TOP_RIGHT: item = NCI_CORNER_XN_YP_ZP; break;
case NCFI_BOTTOM_LEFT: item = NCI_CORNER_XP_YP_ZN; break;
case NCFI_BOTTOM_RIGHT: item = NCI_CORNER_XN_YP_ZN; break;
case NCFI_NONE: item = NCI_NONE; break;
}
break;
}
case NCF_Y_NEG:
{
switch(faceItem)
{
case NCFI_CENTER: item = NCI_FACE_Y_NEG; break;
case NCFI_TOP: item = NCI_EDGE_YN_ZP; break;
case NCFI_BOTTOM: item = NCI_EDGE_YN_ZN; break;
case NCFI_LEFT: item = NCI_EDGE_XN_YN; break;
case NCFI_RIGHT: item = NCI_EDGE_XP_YN; break;
case NCFI_TOP_LEFT: item = NCI_CORNER_XN_YN_ZP; break;
case NCFI_TOP_RIGHT: item = NCI_CORNER_XP_YN_ZP; break;
case NCFI_BOTTOM_LEFT: item = NCI_CORNER_XN_YN_ZN; break;
case NCFI_BOTTOM_RIGHT: item = NCI_CORNER_XP_YN_ZN; break;
case NCFI_NONE: item = NCI_NONE; break;
}
break;
}
case NCF_Z_POS:
{
switch(faceItem)
{
case NCFI_CENTER: item = NCI_FACE_Z_POS; break;
case NCFI_TOP: item = NCI_EDGE_YP_ZP; break;
case NCFI_BOTTOM: item = NCI_EDGE_YN_ZP; break;
case NCFI_LEFT: item = NCI_EDGE_XN_ZP; break;
case NCFI_RIGHT: item = NCI_EDGE_XP_ZP; break;
case NCFI_TOP_LEFT: item = NCI_CORNER_XN_YP_ZP; break;
case NCFI_TOP_RIGHT: item = NCI_CORNER_XP_YP_ZP; break;
case NCFI_BOTTOM_LEFT: item = NCI_CORNER_XN_YN_ZP; break;
case NCFI_BOTTOM_RIGHT: item = NCI_CORNER_XP_YN_ZP; break;
case NCFI_NONE: item = NCI_NONE; break;
}
break;
}
case NCF_Z_NEG:
{
switch(faceItem)
{
case NCFI_CENTER: item = NCI_FACE_Z_NEG; break;
case NCFI_TOP: item = NCI_EDGE_YN_ZN; break;
case NCFI_BOTTOM: item = NCI_EDGE_YP_ZN; break;
case NCFI_LEFT: item = NCI_EDGE_XN_ZN; break;
case NCFI_RIGHT: item = NCI_EDGE_XP_ZN; break;
case NCFI_TOP_LEFT: item = NCI_CORNER_XN_YN_ZN; break;
case NCFI_TOP_RIGHT: item = NCI_CORNER_XP_YN_ZN; break;
case NCFI_BOTTOM_LEFT: item = NCI_CORNER_XN_YP_ZN; break;
case NCFI_BOTTOM_RIGHT: item = NCI_CORNER_XP_YP_ZN; break;
case NCFI_NONE: item = NCI_NONE; break;
}
break;
}
case NCF_NONE:
{
CVF_FAIL_MSG("Illegal nav cube face specified");
break;
}
}
return item;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::faceOrientation(NavCubeFace face, Vec3f* normal, Vec3f* upVector, Vec3f* rightVector) const
{
CVF_ASSERT(normal && upVector && rightVector);
switch (face)
{
case NCF_X_POS: *normal = Vec3f::X_AXIS; break;
case NCF_X_NEG: *normal = -Vec3f::X_AXIS; break;
case NCF_Y_POS: *normal = Vec3f::Y_AXIS; break;
case NCF_Y_NEG: *normal = -Vec3f::Y_AXIS; break;
case NCF_Z_POS: *normal = Vec3f::Z_AXIS; break;
case NCF_Z_NEG: *normal = -Vec3f::Z_AXIS; break;
case NCF_NONE: CVF_FAIL_MSG("Illegal nav cube face"); break;
}
if ((*normal)*m_upVector == 0.0)
{
if (*normal == m_upVector) *upVector = -m_frontVector;
else *upVector = m_frontVector;
}
else
{
*upVector = m_upVector;
}
*rightVector = *upVector^*normal;
normal->normalize();
upVector->normalize();
rightVector->normalize();
}
} // namespace cvf

View File

@@ -0,0 +1,187 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfOverlayItem.h"
#include "cvfMatrix4.h"
#include "cvfColor3.h"
#include "cvfString.h"
#include "cvfBoundingBox.h"
#include "cvfCollection.h"
namespace cvf {
class Camera;
class DrawableGeo;
class DrawableVectors;
class Font;
class ShaderProgram;
class MatrixState;
class TextureImage;
//==================================================================================================
//
// Overlay axis cross
//
//==================================================================================================
class OverlayNavigationCube: public OverlayItem
{
public:
enum NavCubeFace {
NCF_NONE,
NCF_X_POS,
NCF_X_NEG,
NCF_Y_POS,
NCF_Y_NEG,
NCF_Z_POS,
NCF_Z_NEG
};
// Note that the order of the items starting at the VT_NCFI_BOTTOM_LEFT is important (in a CCW order)
enum NavCubeFaceItem {
NCFI_NONE,
NCFI_CENTER,
NCFI_BOTTOM_LEFT,
NCFI_BOTTOM,
NCFI_BOTTOM_RIGHT,
NCFI_RIGHT,
NCFI_TOP_RIGHT,
NCFI_TOP,
NCFI_TOP_LEFT,
NCFI_LEFT
};
enum NavCubeItem
{
NCI_NONE,
NCI_CORNER_XN_YN_ZN,
NCI_CORNER_XP_YN_ZN,
NCI_CORNER_XP_YP_ZN,
NCI_CORNER_XN_YP_ZN,
NCI_CORNER_XN_YN_ZP,
NCI_CORNER_XP_YN_ZP,
NCI_CORNER_XP_YP_ZP,
NCI_CORNER_XN_YP_ZP,
NCI_EDGE_YN_ZN,
NCI_EDGE_XP_ZN,
NCI_EDGE_YP_ZN,
NCI_EDGE_XN_ZN,
NCI_EDGE_YN_ZP,
NCI_EDGE_XP_ZP,
NCI_EDGE_YP_ZP,
NCI_EDGE_XN_ZP,
NCI_EDGE_XN_YN,
NCI_EDGE_XP_YN,
NCI_EDGE_XP_YP,
NCI_EDGE_XN_YP,
NCI_FACE_X_POS,
NCI_FACE_X_NEG,
NCI_FACE_Y_POS,
NCI_FACE_Y_NEG,
NCI_FACE_Z_POS,
NCI_FACE_Z_NEG,
NCI_ARROW_LEFT,
NCI_ARROW_RIGHT,
NCI_ARROW_TOP,
NCI_ARROW_BOTTOM,
NCI_HOME,
NCI_ROTATE_CW,
NCI_ROTATE_CCW
};
public:
OverlayNavigationCube(Camera* camera, Font* font);
~OverlayNavigationCube();
virtual Vec2ui sizeHint();
virtual Vec2ui maximumSize();
virtual Vec2ui minimumSize();
virtual void render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size);
virtual void renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size);
void setSize(const Vec2ui& size);
void updateHighlight(int winCoordX, int winCoordY);
void processSelection(int winCoordX, int winCoordY, const BoundingBox& boundingBox, Vec3d* eye, Vec3d* viewDirection);
void setAxisLabels(const String& xLabel, const String& yLabel, const String& zlabel);
void setAxisLabelsColor(const Color3f& color);
private:
void render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software, const Mat4d& viewMatrix);
void createAxisGeometry(bool software);
void renderAxis(OpenGLContext* oglContext, const MatrixState& matrixState);
void renderAxisImmediateMode(OpenGLContext* oglContext, const MatrixState& matrixState);
void renderAxisLabels(OpenGLContext* oglContext, bool software, const MatrixState& matrixState);
void renderCubeGeos(OpenGLContext* oglContext, bool software, const MatrixState& matrixState);
void createCubeGeos();
void createCubeFaceGeos(NavCubeFace face, Vec3f p1, Vec3f p2, Vec3f p3, Vec3f p4);//, const String& name, const Color3f& baseColor, TextureImage* texture);
void navCubeCornerPoints(Vec3f points[8]);
ref<DrawableGeo> createQuadGeo(const Vec3f& v1, const Vec3f& v2, const Vec3f& v3, const Vec3f& v4);
NavCubeItem navCubeItem(NavCubeFace face, NavCubeFaceItem item) const;
void faceOrientation(NavCubeFace face, Vec3f* normal, Vec3f* upVector, Vec3f* rightVector) const;
private:
ref<Camera> m_camera; // This camera's view matrix will be used to orient the axis cross
String m_xLabel; // Label to display on x axis, default 'x'
String m_yLabel;
String m_zLabel;
Color3f m_textColor; // Text color
ref<Font> m_font;
Vec2ui m_size; // Pixel size of the axis area
Collection<DrawableGeo> m_cubeGeos;
std::vector<NavCubeItem> m_cubeItemType;
ref<ShaderProgram> m_cubeGeoShader;
ref<DrawableVectors> m_axis;
NavCubeItem m_hightlightItem; ///< The currently highlighted cube item (face, corner, edge, buttons)
Vec3f m_upVector; ///< Specify the up vector, which is used for the orientation of the text and textures on the faces
Vec3f m_frontVector; ///< Specify the front vector, which is used for the orientation of the top and bottom faces
String m_xPosAxisName; ///< The name of the X_POS face
String m_xNegAxisName; ///< The name of the X_NEG face
String m_yPosAxisName; ///< The name of the Y_POS face
String m_yNegAxisName; ///< The name of the Y_NEG face
String m_zPosAxisName; ///< The name of the Z_POS face
String m_zNegAxisName; ///< The name of the Z_NEG face
ref<TextureImage> m_texturePosXAxis; ///< The texture to draw on the X_POS face. If NULL, the specified text will be drawn.
ref<TextureImage> m_textureNegXAxis; ///< The texture to draw on the X_NEG face. If NULL, the specified text will be drawn.
ref<TextureImage> m_texturePosYAxis; ///< The texture to draw on the Y_POS face. If NULL, the specified text will be drawn.
ref<TextureImage> m_textureNegYAxis; ///< The texture to draw on the Y_NEG face. If NULL, the specified text will be drawn.
ref<TextureImage> m_texturePosZAxis; ///< The texture to draw on the Z_POS face. If NULL, the specified text will be drawn.
ref<TextureImage> m_textureNegZAxis; ///< The texture to draw on the Z_NEG face. If NULL, the specified text will be drawn.
Color3f m_xFaceColor; ///< The color of the X_POS and X_NEG faces
Color3f m_yFaceColor; ///< The color of the Y_POS and Y_NEG faces
Color3f m_zFaceColor; ///< The color of the Z_POS and Z_NEG faces
};
}

View File

@@ -0,0 +1,730 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfOverlayScalarMapperLegend.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfGeometryBuilderDrawableGeo.h"
#include "cvfGeometryUtils.h"
#include "cvfViewport.h"
#include "cvfCamera.h"
#include "cvfTextDrawer.h"
#include "cvfFont.h"
#include "cvfShaderProgram.h"
#include "cvfShaderProgramGenerator.h"
#include "cvfShaderSourceProvider.h"
#include "cvfShaderSourceRepository.h"
#include "cvfUniform.h"
#include "cvfMatrixState.h"
#include "cvfBufferObjectManaged.h"
#include "cvfGlyph.h"
#include "cvfRenderStateDepth.h"
#include "cvfRenderStateLine.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#endif
#include "cvfScalarMapper.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::OverlayColorLegend
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
OverlayScalarMapperLegend::OverlayScalarMapperLegend(Font* font)
: m_sizeHint(200, 200),
m_color(Color3::BLACK),
m_lineColor(Color3::BLACK),
m_lineWidth(1),
m_font(font)
{
CVF_ASSERT(font);
CVF_ASSERT(!font->isEmpty());
m_tickValues.reserve(3);
m_tickValues.add(0.0);
m_tickValues.add(0.5);
m_tickValues.add(1.0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OverlayScalarMapperLegend::~OverlayScalarMapperLegend()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayScalarMapperLegend::sizeHint()
{
return m_sizeHint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayScalarMapperLegend::maximumSize()
{
return m_sizeHint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayScalarMapperLegend::minimumSize()
{
return Vec2ui(100,100);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::setScalarMapper(const ScalarMapper* scalarMapper)
{
m_scalarMapper = scalarMapper;
if (m_scalarMapper.notNull())
{
std::vector<double> levelValues;
m_scalarMapper->majorTickValues(&levelValues);
m_tickValues.assign(levelValues);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::setSizeHint(const Vec2ui& size)
{
m_sizeHint = size;
}
//--------------------------------------------------------------------------------------------------
/// Set color of the text and lines to be rendered
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::setColor(const Color3f& color)
{
m_color = color;
}
//--------------------------------------------------------------------------------------------------
/// Returns the color of the text and lines
//--------------------------------------------------------------------------------------------------
const Color3f& OverlayScalarMapperLegend::color() const
{
return m_color;
}
//--------------------------------------------------------------------------------------------------
/// Set the title (text that will be rendered above the legend)
///
/// The legend supports multi-line titles. Separate each line with a '\n' character
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::setTitle(const String& title)
{
// Title
if (title.isEmpty())
{
m_titleStrings.clear();
}
else
{
m_titleStrings = title.split("\n");
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String OverlayScalarMapperLegend::title() const
{
String title;
for (size_t i = 0; i < m_titleStrings.size(); ++i)
{
title += m_titleStrings[i];
if (i != m_titleStrings.size() - 1)
{
title += "\n";
}
}
return title;
}
//--------------------------------------------------------------------------------------------------
/// Hardware rendering using shader programs
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
render(oglContext, position, size, false);
}
//--------------------------------------------------------------------------------------------------
/// Software rendering using software
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
render(oglContext, position, size, true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OverlayScalarMapperLegend::pick(uint oglXCoord, uint oglYCoord, const Vec2ui& position, const Vec2ui& size)
{
Rectui oglRect(position, size.x(), size.y());
OverlayColorLegendLayoutInfo layoutInViewPortCoords(oglRect.min(), Vec2ui(oglRect.width(), oglRect.height()));
layoutInfo(&layoutInViewPortCoords);
Vec2ui legendBarOrigin = oglRect.min();
legendBarOrigin.x() += static_cast<uint>(layoutInViewPortCoords.legendRect.min().x());
legendBarOrigin.y() += static_cast<uint>(layoutInViewPortCoords.legendRect.min().y());
Rectui legendBarRect = Rectui(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;
}
//--------------------------------------------------------------------------------------------------
/// Set up camera/viewport and render
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::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);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::setupTextDrawer(TextDrawer* textDrawer, OverlayColorLegendLayoutInfo* layout)
{
CVF_ASSERT(layout);
textDrawer->setVerticalAlignment(TextDrawer::CENTER);
textDrawer->setTextColor(m_color);
m_visibleTickLabels.clear();
const float textX = layout->tickX + 5;
const float overlapTolerance = 1.2f * layout->charHeight;
float lastVisibleTextY = 0.0;
size_t numTicks = m_tickValues.size();
size_t it;
for (it = 0; it < numTicks; it++)
{
float textY = static_cast<float>(layout->legendRect.min().y() + layout->tickPixelPos->get(it));
// Always draw first and last tick label. For all others, skip drawing if text ends up
// on top of the previous label.
if (it != 0 && it != (numTicks - 1))
{
if (cvf::Math::abs(textY - lastVisibleTextY) < overlapTolerance)
{
m_visibleTickLabels.push_back(false);
continue;
}
// Make sure it does not overlap the last tick as well
float lastTickY = static_cast<float>(layout->legendRect.max().y() );
if (cvf::Math::abs(textY - lastTickY) < overlapTolerance)
{
m_visibleTickLabels.push_back(false);
continue;
}
}
double tickValue = m_tickValues[it];
String valueString = String::number(tickValue);
Vec2f pos(textX, textY);
textDrawer->addText(valueString, pos);
lastVisibleTextY = textY;
m_visibleTickLabels.push_back(true);
}
float titleY = static_cast<float>(layout->size.y()) - layout->margins.y() - layout->charHeight/2.0f;
for (it = 0; it < m_titleStrings.size(); it++)
{
Vec2f pos(layout->margins.x(), titleY);
textDrawer->addText(m_titleStrings[it], pos);
titleY -= layout->lineSpacing;
}
}
//--------------------------------------------------------------------------------------------------
/// Draw the legend using shader programs
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::renderLegend(OpenGLContext* oglContext, OverlayColorLegendLayoutInfo* layout, const MatrixState& matrixState)
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_TIGHT_ASSERT(layout);
CVF_TIGHT_ASSERT(layout->size.x() > 0);
CVF_TIGHT_ASSERT(layout->size.y() > 0);
RenderStateDepth depth(false);
depth.applyOpenGL(oglContext);
RenderStateLine line(static_cast<float>(m_lineWidth));
line.applyOpenGL(oglContext);
// All vertices. Initialized here to set Z to zero once and for all.
static float vertexArray[] =
{
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f
};
// Per vector convenience pointers
float* v0 = &vertexArray[0];
float* v1 = &vertexArray[3];
float* v2 = &vertexArray[6];
float* v3 = &vertexArray[9];
float* v4 = &vertexArray[12];
// Constant coordinates
v0[0] = v3[0] = layout->x0;
v1[0] = v4[0] = layout->x1;
// Connects
static const ushort trianglesConnects[] = { 0, 1, 4, 0, 4, 3 };
ref<ShaderProgram> shaderProgram = oglContext->resourceManager()->getLinkedUnlitColorShaderProgram(oglContext);
CVF_TIGHT_ASSERT(shaderProgram.notNull());
if (shaderProgram->useProgram(oglContext))
{
shaderProgram->clearUniformApplyTracking();
shaderProgram->applyFixedUniforms(oglContext, matrixState);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(ShaderProgram::VERTEX);
glVertexAttribPointer(ShaderProgram::VERTEX, 3, GL_FLOAT, GL_FALSE, 0, vertexArray);
// Render color bar as one colored quad per pixel
int legendHeightPixelCount = static_cast<int>(layout->tickPixelPos->get(m_tickValues.size()-1) - layout->tickPixelPos->get(0) + 0.01);
if (m_scalarMapper.notNull())
{
int iPx;
for (iPx = 0; iPx < legendHeightPixelCount; iPx++)
{
const Color3ub& clr = m_scalarMapper->mapToColor(m_scalarMapper->domainValue((iPx+0.5)/legendHeightPixelCount));
float y0 = static_cast<float>(layout->legendRect.min().y() + iPx);
float y1 = static_cast<float>(layout->legendRect.min().y() + iPx + 1);
// Dynamic coordinates for rectangle
v0[1] = v1[1] = y0;
v3[1] = v4[1] = y1;
// Draw filled rectangle elements
{
UniformFloat uniformColor("u_color", Color4f(Color3f(clr)));
shaderProgram->applyUniform(oglContext, uniformColor);
#ifdef CVF_OPENGL_ES
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, trianglesConnects);
#else
glDrawRangeElements(GL_TRIANGLES, 0, 4, 6, GL_UNSIGNED_SHORT, trianglesConnects);
#endif
}
}
}
// Render frame
// Dynamic coordinates for tickmarks-lines
bool isRenderingFrame = true;
if (isRenderingFrame)
{
v0[0] = v2[0] = layout->legendRect.min().x()-0.5f;
v1[0] = v3[0] = layout->legendRect.max().x()-0.5f;
v0[1] = v1[1] = layout->legendRect.min().y()-0.5f;
v2[1] = v3[1] = layout->legendRect.max().y()-0.5f;
static const ushort frameConnects[] = { 0, 1, 1, 3, 3, 2, 2, 0};
UniformFloat uniformColor("u_color", Color4f(m_lineColor));
shaderProgram->applyUniform(oglContext, uniformColor);
#ifdef CVF_OPENGL_ES
glDrawElements(GL_LINES, 8, GL_UNSIGNED_SHORT, frameConnects);
#else
glDrawRangeElements(GL_LINES, 0, 3, 8, GL_UNSIGNED_SHORT, frameConnects);
#endif
}
// Render tickmarks
bool isRenderingTicks = true;
if (isRenderingTicks)
{
// Constant coordinates
v0[0] = layout->x0;
v1[0] = layout->x1 - 0.5f*(layout->tickX - layout->x1) - 0.5f;
v2[0] = layout->x1;
v3[0] = layout->tickX - 0.5f*(layout->tickX - layout->x1) - 0.5f;
v4[0] = layout->tickX;
static const ushort tickLinesWithLabel[] = { 0, 4 };
static const ushort tickLinesWoLabel[] = { 2, 3 };
size_t ic;
for (ic = 0; ic < m_tickValues.size(); ic++)
{
float y0 = static_cast<float>(layout->legendRect.min().y() + layout->tickPixelPos->get(ic) - 0.5f);
// Dynamic coordinates for tickmarks-lines
v0[1] = v1[1] = v2[1] = v3[1] = v4[1] = y0;
UniformFloat uniformColor("u_color", Color4f(m_lineColor));
shaderProgram->applyUniform(oglContext, uniformColor);
const ushort * linesConnects;
if ( m_visibleTickLabels[ic])
{
linesConnects = tickLinesWithLabel;
}
else
{
linesConnects = tickLinesWoLabel;
}
#ifdef CVF_OPENGL_ES
glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, linesConnects);
#else
glDrawRangeElements(GL_LINES, 0, 4, 2, GL_UNSIGNED_SHORT, linesConnects);
#endif
}
}
glDisableVertexAttribArray(ShaderProgram::VERTEX);
CVF_TIGHT_ASSERT(shaderProgram.notNull());
shaderProgram->useNoProgram(oglContext);
// Reset render states
RenderStateDepth resetDepth;
resetDepth.applyOpenGL(oglContext);
RenderStateLine resetLine;
resetLine.applyOpenGL(oglContext);
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
/// Draw the legend using immediate mode OpenGL
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::renderLegendImmediateMode(OpenGLContext* oglContext, OverlayColorLegendLayoutInfo* layout)
{
#ifdef CVF_OPENGL_ES
CVF_UNUSED(layout);
CVF_FAIL_MSG("Not supported on OpenGL ES");
#else
CVF_TIGHT_ASSERT(layout);
CVF_TIGHT_ASSERT(layout->size.x() > 0);
CVF_TIGHT_ASSERT(layout->size.y() > 0);
RenderStateDepth depth(false);
depth.applyOpenGL(oglContext);
RenderStateLighting_FF lighting(false);
lighting.applyOpenGL(oglContext);
// All vertices. Initialized here to set Z to zero once and for all.
static float vertexArray[] =
{
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
};
// Per vector convenience pointers
float* v0 = &vertexArray[0];
float* v1 = &vertexArray[3];
float* v2 = &vertexArray[6];
float* v3 = &vertexArray[9];
float* v4 = &vertexArray[12];
// Constant coordinates
v0[0] = v3[0] = layout->x0;
v1[0] = v4[0] = layout->x1;
// Render color bar as one colored quad per pixel
int legendHeightPixelCount = static_cast<int>(layout->tickPixelPos->get(m_tickValues.size() - 1) - layout->tickPixelPos->get(0) + 0.01);
if (m_scalarMapper.notNull())
{
int iPx;
for (iPx = 0; iPx < legendHeightPixelCount; iPx++)
{
const Color3ub& clr = m_scalarMapper->mapToColor(m_scalarMapper->domainValue((iPx+0.5)/legendHeightPixelCount));
float y0 = static_cast<float>(layout->legendRect.min().y() + iPx);
float y1 = static_cast<float>(layout->legendRect.min().y() + iPx + 1);
// Dynamic coordinates for rectangle
v0[1] = v1[1] = y0;
v3[1] = v4[1] = y1;
// Draw filled rectangle elements
glColor3ubv(clr.ptr());
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v4);
glVertex3fv(v3);
glEnd();
}
}
// Render frame
// Dynamic coordinates for tickmarks-lines
bool isRenderingFrame = true;
if (isRenderingFrame)
{
v0[0] = v2[0] = layout->legendRect.min().x()-0.5f;
v1[0] = v3[0] = layout->legendRect.max().x()-0.5f;
v0[1] = v1[1] = layout->legendRect.min().y()-0.5f;
v2[1] = v3[1] = layout->legendRect.max().y()-0.5f;
glColor3fv(m_color.ptr());
glBegin(GL_LINES);
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v1);
glVertex3fv(v3);
glVertex3fv(v3);
glVertex3fv(v2);
glVertex3fv(v2);
glVertex3fv(v0);
glEnd();
}
// Render tickmarks
bool isRenderingTicks = true;
if (isRenderingTicks)
{
// Constant coordinates
v0[0] = layout->x0;
v1[0] = layout->x1 - 0.5f*(layout->tickX - layout->x1) - 0.5f;
v2[0] = layout->x1;
v3[0] = layout->tickX - 0.5f*(layout->tickX - layout->x1) - 0.5f;
v4[0] = layout->tickX;
size_t ic;
for (ic = 0; ic < m_tickValues.size(); ic++)
{
float y0 = static_cast<float>(layout->legendRect.min().y() + layout->tickPixelPos->get(ic) - 0.5f);
// Dynamic coordinates for tickmarks-lines
v0[1] = v1[1] = v2[1] = v3[1] = v4[1] = y0;
glColor3fv(m_color.ptr());
glBegin(GL_LINES);
if ( m_visibleTickLabels[ic])
{
glVertex3fv(v0);
glVertex3fv(v4);
}
else
{
glVertex3fv(v2);
glVertex3fv(v3);
}
glEnd();
}
}
// Reset render states
RenderStateLighting_FF resetLighting;
resetLighting.applyOpenGL(oglContext);
RenderStateDepth resetDepth;
resetDepth.applyOpenGL(oglContext);
CVF_CHECK_OGL(oglContext);
#endif // CVF_OPENGL_ES
}
//--------------------------------------------------------------------------------------------------
/// Get layout information
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::layoutInfo(OverlayColorLegendLayoutInfo* layout)
{
CVF_TIGHT_ASSERT(layout);
ref<Glyph> glyph = m_font->getGlyph(L'A');
layout->charHeight = static_cast<float>(glyph->height());
layout->lineSpacing = layout->charHeight*1.5f;
layout->margins = Vec2f(4.0f, 4.0f);
float legendWidth = 25.0f;
float legendHeight = static_cast<float>(layout->size.y()) - 2*layout->margins.y() - static_cast<float>(m_titleStrings.size())*layout->lineSpacing - layout->lineSpacing;
layout->legendRect = Rectf(layout->margins.x(), layout->margins.y() + layout->charHeight/2.0f, legendWidth, legendHeight);
if (layout->legendRect.width() < 1 || layout->legendRect.height() < 1)
{
return;
}
layout->x0 = layout->margins.x();
layout->x1 = layout->margins.x() + layout->legendRect.width();
layout->tickX = layout->x1 + 5;
// Build array containing the pixel positions of all the ticks
size_t numTicks = m_tickValues.size();
layout->tickPixelPos = new DoubleArray(numTicks);
size_t i;
for (i = 0; i < numTicks; i++)
{
double t;
if (m_scalarMapper.isNull()) t = 0;
else t = m_scalarMapper->normalizedValue(m_tickValues[i]);
t = Math::clamp(t, 0.0, 1.1);
layout->tickPixelPos->set(i, t*layout->legendRect.height());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::setLineColor(const Color3f& lineColor)
{
m_lineColor = lineColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Color3f& OverlayScalarMapperLegend::lineColor() const
{
return m_lineColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayScalarMapperLegend::setLineWidth(int lineWidth)
{
m_lineWidth = lineWidth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int OverlayScalarMapperLegend::lineWidth() const
{
return m_lineWidth;
}
} // namespace cvf

View File

@@ -0,0 +1,123 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfOverlayItem.h"
#include "cvfArray.h"
#include "cvfCamera.h"
#include "cvfString.h"
#include "cvfRect.h"
namespace cvf {
class Font;
class ShaderProgram;
class MatrixState;
class TextDrawer;
class ScalarMapper;
//==================================================================================================
//
// Overlay color legend
//
//==================================================================================================
class OverlayScalarMapperLegend : public OverlayItem
{
public:
OverlayScalarMapperLegend(Font* font);
virtual ~OverlayScalarMapperLegend();
virtual Vec2ui sizeHint();
virtual Vec2ui maximumSize();
virtual Vec2ui minimumSize();
void setScalarMapper(const ScalarMapper* scalarMapper);
virtual void render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size);
virtual void renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size);
virtual bool pick(uint oglXCoord, uint oglYCoord, const Vec2ui& position, const Vec2ui& size);
void setSizeHint(const Vec2ui& size);
void setColor(const Color3f& color);
const Color3f& color() const;
void setLineColor(const Color3f& lineColor);
const Color3f& lineColor() const;
void setLineWidth(int lineWidth);
int lineWidth() const;
void setTitle(const String& title);
String title() const;
protected:
//==================================================================================================
//
// Helper for storing layout info
//
//==================================================================================================
struct OverlayColorLegendLayoutInfo
{
OverlayColorLegendLayoutInfo(const Vec2ui& pos, const Vec2ui& setSize)
{
position = pos;
size = setSize;
}
float charHeight;
float lineSpacing;
Vec2f margins;
float tickX;
float x0, x1;
Rectf legendRect;
ref<DoubleArray> tickPixelPos;
Vec2ui position;
Vec2ui size;
};
void render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software);
virtual void renderLegend(OpenGLContext* oglContext, OverlayColorLegendLayoutInfo* layout, const MatrixState& matrixState);
virtual void renderLegendImmediateMode(OpenGLContext* oglContext, OverlayColorLegendLayoutInfo* layout);
virtual void setupTextDrawer(TextDrawer* textDrawer, OverlayColorLegendLayoutInfo* layout);
void layoutInfo(OverlayColorLegendLayoutInfo* layout);
protected:
DoubleArray m_tickValues; // Ticks between each level + top and bottom of legend (n+1 entries)
std::vector<bool> m_visibleTickLabels; // Skip tick labels ending up on top of previous visible label
Vec2ui m_sizeHint; // Pixel size of the color legend area
Color3f m_color;
Color3f m_lineColor;
int m_lineWidth;
std::vector<String> m_titleStrings;
ref<Font> m_font;
cref<ScalarMapper> m_scalarMapper;
};
}

View File

@@ -22,12 +22,15 @@
#include "cvfDrawableText.h"
#include "cvfMatrixState.h"
#include "cvfCamera.h"
#include "cvfRenderState.h"
#include "cvfShaderProgram.h"
#include "cvfOpenGL.h"
#include "cvfViewport.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfUniform.h"
#include "cvfRenderStateDepth.h"
#include "cvfFont.h"
#include "cvfGlyph.h"
#include "cvfRenderStateLine.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
@@ -49,6 +52,7 @@ namespace cvf {
//--------------------------------------------------------------------------------------------------
OverlayTextBox::OverlayTextBox(Font* font)
: m_size(200, 50),
m_font(font),
m_drawBackground(true),
m_drawBorder(true),
m_textColor(Color3::WHITE),
@@ -56,7 +60,7 @@ OverlayTextBox::OverlayTextBox(Font* font)
m_borderColor(0.6f, 0.6f, 1.0f)
{
m_textDrawer = new TextDrawer(font);
m_textDrawer->setVerticalAlignment(TextDrawer::CENTER);
m_textDrawer->setVerticalAlignment(TextDrawer::BASELINE);
m_textDrawer->setDrawBackground(false);
m_textDrawer->setDrawBorder(false);
}
@@ -130,6 +134,9 @@ void OverlayTextBox::render(OpenGLContext* oglContext, const Vec2ui& position, c
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);
@@ -161,7 +168,7 @@ void OverlayTextBox::renderBackgroundAndBorder(OpenGLContext* oglContext, const
projCam.setViewMatrix(Mat4d::IDENTITY);
// Turn off depth test
Depth depth(false, Depth::LESS, false);
RenderStateDepth depth(false, RenderStateDepth::LESS, false);
depth.applyOpenGL(oglContext);
ref<ShaderProgram> backgroundShader;
@@ -177,11 +184,11 @@ void OverlayTextBox::renderBackgroundAndBorder(OpenGLContext* oglContext, const
}
#ifndef CVF_OPENGL_ES
Material_FF mat;
RenderStateMaterial_FF mat;
mat.enableColorMaterial(true);
mat.applyOpenGL(oglContext);
Lighting_FF light(false);
RenderStateLighting_FF light(false);
light.applyOpenGL(oglContext);
#endif
projCam.applyOpenGL();
@@ -256,8 +263,14 @@ void OverlayTextBox::renderBackgroundAndBorder(OpenGLContext* oglContext, const
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);
}
}
}
@@ -275,12 +288,35 @@ void OverlayTextBox::setText(const String& text)
//--------------------------------------------------------------------------------------------------
/// Set the size (in pixels) of the text box
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::setSize( const Vec2ui& size )
void OverlayTextBox::setPixelSize( const Vec2ui& size )
{
m_size = size;
}
//--------------------------------------------------------------------------------------------------
/// 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);
}
//--------------------------------------------------------------------------------------------------
/// Set the text color
//--------------------------------------------------------------------------------------------------

View File

@@ -48,7 +48,9 @@ public:
virtual void renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size);
void setText(const String& text);
void setSize(const Vec2ui& size);
void setPixelSize(const Vec2ui& size);
void setSizeToFitText();
void setTextColor(const Color3f& color);
void setBackgroundColor(const Color3f& color);
void setBorderColor(const Color3f& color);
@@ -71,6 +73,7 @@ private:
Vec2ui m_size;
String m_text;
ref<TextDrawer> m_textDrawer;
ref<Font> m_font;
bool m_drawBackground;
bool m_drawBorder;

View File

@@ -49,6 +49,18 @@ PrimitiveSetIndexedUInt::PrimitiveSetIndexedUInt(PrimitiveType primitiveType)
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PrimitiveSetIndexedUInt::PrimitiveSetIndexedUInt(PrimitiveType primitiveType, UIntArray* indices)
: PrimitiveSet(primitiveType),
m_minIndex(0),
m_maxIndex(0)
{
setIndices(indices);
}
//--------------------------------------------------------------------------------------------------
/// Deletes OpenGL resources created by this primitive set
//--------------------------------------------------------------------------------------------------

View File

@@ -35,6 +35,7 @@ class PrimitiveSetIndexedUInt : public PrimitiveSet
{
public:
PrimitiveSetIndexedUInt(PrimitiveType primitiveType);
PrimitiveSetIndexedUInt(PrimitiveType primitiveType, UIntArray* indices);
virtual ~PrimitiveSetIndexedUInt();
virtual void render(OpenGLContext* oglContext) const;

View File

@@ -50,6 +50,18 @@ PrimitiveSetIndexedUShort::PrimitiveSetIndexedUShort(PrimitiveType primitiveType
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PrimitiveSetIndexedUShort::PrimitiveSetIndexedUShort(PrimitiveType primitiveType, UShortArray* indices)
: PrimitiveSet(primitiveType),
m_minIndex(0),
m_maxIndex(0)
{
setIndices(indices);
}
//--------------------------------------------------------------------------------------------------
/// Deletes OpenGL resources created by this primitive set
//--------------------------------------------------------------------------------------------------

View File

@@ -35,6 +35,7 @@ class PrimitiveSetIndexedUShort : public PrimitiveSet
{
public:
PrimitiveSetIndexedUShort(PrimitiveType primitiveType);
PrimitiveSetIndexedUShort(PrimitiveType primitiveType, UShortArray* indices);
virtual ~PrimitiveSetIndexedUShort();
virtual void render(OpenGLContext* oglContext) const;

File diff suppressed because it is too large Load Diff

View File

@@ -20,16 +20,10 @@
#pragma once
#include "cvfObject.h"
#include "cvfOpenGLTypes.h"
#include "cvfColor4.h"
#include "cvfString.h"
namespace cvf {
class OpenGLContext;
class ShaderProgram;
class Sampler;
class Texture;
//==================================================================================================
@@ -45,11 +39,13 @@ public:
BLENDING, // Must start at 0, used for indexing in RenderStateTracker
COLOR_MASK,
CULL_FACE,
FRONT_FACE,
DEPTH,
FRONT_FACE,
LINE,
POINT,
POLYGON_MODE,
POLYGON_OFFSET,
STENCIL,
TEXTURE_BINDINGS,
#ifndef CVF_OPENGL_ES
@@ -78,348 +74,5 @@ private:
//==================================================================================================
//
// Controls OpenGL blending
//
//==================================================================================================
class Blending : public RenderState
{
public:
enum Function
{
ZERO,
ONE,
SRC_COLOR,
ONE_MINUS_SRC_COLOR,
DST_COLOR,
ONE_MINUS_DST_COLOR,
SRC_ALPHA,
ONE_MINUS_SRC_ALPHA,
DST_ALPHA,
ONE_MINUS_DST_ALPHA,
CONSTANT_COLOR,
ONE_MINUS_CONSTANT_COLOR,
CONSTANT_ALPHA,
ONE_MINUS_CONSTANT_ALPHA,
SRC_ALPHA_SATURATE
};
enum Equation
{
FUNC_ADD,
FUNC_SUBTRACT,
FUNC_REVERSE_SUBTRACT,
MIN, // Unsupported on OpenGL ES
MAX // Unsupported on OpenGL ES
};
public:
Blending();
void enableBlending(bool blend);
void setFunction(Function source, Function destination);
void setEquation(Equation equation);
void setFunctionSeparate(Function sourceRGB, Function destinationRGB, Function sourceAlpha, Function destinationAlpha);
void setEquationSeparate(Equation equationRGB, Equation equationAlpha);
void setBlendColor(Color4f blendColor);
void configureTransparencyBlending();
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
cvfGLenum blendFuncOpenGL(Function func) const;
cvfGLenum blendEquationOpenGL(Equation eq) const;
private:
bool m_enableBlending;
Function m_funcSourceRGB;
Function m_funcDestinationRGB;
Function m_funcSourceAlpha;
Function m_funcDestinationAlpha;
Equation m_equationRGB;
Equation m_equationAlpha;
Color4f m_blendColor;
};
//==================================================================================================
//
// Encapsulate OpenGL glColorMask() function.
//
//==================================================================================================
class ColorMask : public RenderState
{
public:
ColorMask(bool writeAllComponents = true);
void enable(bool writeRed, bool writeGreen, bool writeBlue, bool writeAlpha);
void enableWriteAllComponents(bool writeAllComponents);
bool isRedEnabled() const;
bool isGreenEnabled() const;
bool isBlueEnabled() const;
bool isAlphaEnabled() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
bool m_writeRed;
bool m_writeGreen;
bool m_writeBlue;
bool m_writeAlpha;
};
//==================================================================================================
//
// Encapsulate OpenGL glCullFace() and glEnable(GL_CULL_FACE) functions.
//
//==================================================================================================
class CullFace : public RenderState
{
public:
enum Mode
{
BACK, ///< Cull back facing polygons
FRONT, ///< Cull front facing polygons
FRONT_AND_BACK ///< No polygons are drawn, but other primitives such as points and lines are drawn
};
public:
CullFace(bool enableCulling = true, Mode faceMode = BACK);
void enable(bool enableCulling);
bool isEnabled() const;
void setMode(Mode faceMode);
Mode mode() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
bool m_enableCulling;
Mode m_faceMode;
};
//==================================================================================================
//
// Encapsulate OpenGL glFrontFace().
//
//==================================================================================================
class FrontFace : public RenderState
{
public:
enum Mode
{
CCW, ///< Counterclockwise order (default)
CW ///< Clockwise order
};
public:
FrontFace(Mode faceMode = CCW);
void setMode(Mode faceMode);
Mode mode() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
Mode m_faceMode;
};
//==================================================================================================
//
// Encapsulate OpenGL glEnable(GL_DEPTH_TEST), glDepthFunc() and glDepthMask() functions.
//
//==================================================================================================
class Depth : public RenderState
{
public:
enum Function
{
NEVER, ///< Never passes
LESS, ///< Passes if the incoming depth value is less than the stored depth value. This is the OpenGL default.
EQUAL, ///< Passes if the incoming depth value is equal to the stored depth value.
LEQUAL, ///< Passes if the incoming depth value is less than or equal to the stored depth value.
GREATER, ///< Passes if the incoming depth value is greater than the stored depth value.
NOTEQUAL, ///< Passes if the incoming depth value is not equal to the stored depth value.
GEQUAL, ///< Passes if the incoming depth value is greater than or equal to the stored depth value.
ALWAYS ///< Always passes.
};
public:
Depth(bool depthTest = true, Function func = LESS, bool depthWrite = true);
void setFunction(Function func);
void enableDepthTest(bool enableTest);
void enableDepthWrite(bool enableWrite);
Function function() const;
bool isDepthTestEnabled() const;
bool isDepthWriteEnabled() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
cvfGLenum depthFuncOpenGL() const;
private:
Function m_depthFunc;
bool m_enableDepthTest;
bool m_enableDepthWrite;
};
//==================================================================================================
//
// Controls OpenGL point size, glPointSize() and glEnable()/glDisable() with GL_PROGRAM_POINT_SIZE
//
//==================================================================================================
class Point : public RenderState
{
public:
enum Mode
{
FIXED_SIZE, ///< Fixed diameter of raserized points (as specified by point size/glPointSize())
PROGRAM_SIZE ///< Point size will be specified using GLSL and the gl_PointSize built-in variable
};
public:
Point(Mode sizeMode = FIXED_SIZE);
void setMode(Mode sizeMode);
Mode mode() const;
void enablePointSprite(bool enable);
bool isPointSpriteEnabled() const;
void setSize(float pointSize);
float size() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
Mode m_sizeMode;
bool m_pointSprite;
float m_pointSize;
};
//==================================================================================================
//
// Controls OpenGL polygon rasterization mode, glPolygonMode()
//
//==================================================================================================
class PolygonMode : public RenderState
{
public:
enum Mode
{
FILL, ///< The interior of the polygons is filled
LINE, ///< Boundary edges of the polygons are drawn as line segments
POINT ///< Polygon vertices that are marked as the start of a boundary edge are drawn as points
};
public:
PolygonMode(Mode frontAndBackFaceMode = FILL);
void set(Mode frontAndBackMode);
void setFrontFace(Mode mode);
void setBackFace(Mode mode);
Mode frontFace() const;
Mode backFace() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
static cvfGLenum polygonModeOpenGL(Mode mode);
private:
Mode m_frontFaceMode;
Mode m_backFaceMode;
};
//==================================================================================================
//
// Encapsulate OpenGL glPolygonOffset() and glEnable()/glDisable() with GL_POLYGON_OFFSET_FILL/LINE/POINT
//
//==================================================================================================
class PolygonOffset : public RenderState
{
public:
PolygonOffset();
void enableFillMode(bool enableFill);
void enableLineMode(bool enableLine);
void enablePointMode(bool enablePoint);
bool isFillModeEnabled() const;
bool isLineModeEnabled() const;
bool isPointModeEnabled() const;
void setFactor(float factor);
void setUnits(float units);
float factor() const;
float units() const;
void configurePolygonPositiveOffset();
void configureLineNegativeOffset();
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
float m_factor; // Default value is 0.0
float m_units; // Default value is 0.0
bool m_enableFillMode;
bool m_enableLineMode;
bool m_enablePointMode;
};
//==================================================================================================
//
// Binds a texture and a sampler to a texture unit
//
//==================================================================================================
class TextureBindings : public RenderState
{
public:
TextureBindings();
TextureBindings(Texture* texture, Sampler* sampler, const char* samplerUniformName);
~TextureBindings();
void addBinding(Texture* texture, Sampler* sampler, const char* samplerUniformName);
int bindingCount() const;
Texture* texture(int bindingIdx);
const Texture* texture(int bindingIdx) const;
Sampler* sampler(int bindingIdx);
const Sampler* sampler(int bindingIdx) const;
String samplerUniformName(int bindingIdx) const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
void setupTextures(OpenGLContext* oglContext);
void applySamplerTextureUnitUniforms(OpenGLContext* oglContext, ShaderProgram* shaderProgram) const;
public:
static const int MAX_TEXTURE_UNITS = 16;
private:
struct BindingEntry
{
ref<Texture> texture;
ref<Sampler> sampler;
String samplerUniformName;
};
BindingEntry m_bindings[MAX_TEXTURE_UNITS];
int m_bindingCount;
};
} // namespace cvf

View File

@@ -0,0 +1,256 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRenderStateBlending.h"
#include "cvfAssert.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLCapabilities.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStateBlending
/// \ingroup Render
///
/// Encapsulate OpenGL blending functions: glEnable(GL_BLEND), glBlendEquation(), glBlendEquationSeparate()
/// glBlendFunc(), glBlendFuncSeparate(), glBlendColor()
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glBlendEquation.xml
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glBlendEquationSeparate.xml
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glBlendFunc.xml
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glBlendFuncSeparate.xml
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glBlendColor.xml
///
/// \todo
/// Add support for enable/disable blending per drawbuffer: glEnablei(GL_BLEND, drawBufferIndex)
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateBlending::RenderStateBlending()
: RenderState(BLENDING),
m_enableBlending(false),
m_funcSourceRGB(ONE),
m_funcDestinationRGB(ZERO),
m_funcSourceAlpha(ONE),
m_funcDestinationAlpha(ZERO),
m_equationRGB(FUNC_ADD),
m_equationAlpha(FUNC_ADD),
m_blendColor(0, 0, 0, 0)
{
}
//--------------------------------------------------------------------------------------------------
/// glEnable(GL_BLEND) / glDisable(GL_BLEND)
//--------------------------------------------------------------------------------------------------
void RenderStateBlending::enableBlending(bool blend/*, uint drawBufferIndex*/)
{
m_enableBlending = blend;
}
//--------------------------------------------------------------------------------------------------
/// glBlendFunc()
//--------------------------------------------------------------------------------------------------
void RenderStateBlending::setFunction(Function source, Function destination)
{
m_funcSourceRGB = source;
m_funcSourceAlpha = source;
m_funcDestinationRGB = destination;
m_funcDestinationAlpha = destination;
}
//--------------------------------------------------------------------------------------------------
/// glBlendEquation(). Requires OpenGL 2.0
//--------------------------------------------------------------------------------------------------
void RenderStateBlending::setEquation(Equation eq)
{
m_equationRGB = eq;
m_equationAlpha = eq;
}
//--------------------------------------------------------------------------------------------------
/// glBlendFuncSeparate(). Requires OpenGL 2.0
//--------------------------------------------------------------------------------------------------
void RenderStateBlending::setFunctionSeparate(Function sourceRGB, Function destinationRGB, Function sourceAlpha, Function destinationAlpha)
{
m_funcSourceRGB = sourceRGB;
m_funcDestinationRGB = destinationRGB;
m_funcSourceAlpha = sourceAlpha;
m_funcDestinationAlpha = destinationAlpha;
}
//--------------------------------------------------------------------------------------------------
/// glBlendEquationSeparate(). Requires OpenGL 2.0
//--------------------------------------------------------------------------------------------------
void RenderStateBlending::setEquationSeparate(Equation equationRGB, Equation equationAlpha)
{
m_equationRGB = equationRGB;
m_equationAlpha = equationAlpha;
}
//--------------------------------------------------------------------------------------------------
/// glBlendColor(). Requires OpenGL 2.0
//--------------------------------------------------------------------------------------------------
void RenderStateBlending::setBlendColor(Color4f blendColor)
{
m_blendColor = blendColor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateBlending::configureTransparencyBlending()
{
m_enableBlending = true;
setFunction(SRC_ALPHA, ONE_MINUS_SRC_ALPHA);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateBlending::applyOpenGL(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
/// As we do not care about specific support for OpenGL 1.4, 1.3 etc., everything that is not in 1.1
/// will require at least support for our baseline (currently OpenGL 2.0)
bool openGL2Support = oglContext->capabilities()->supportsOpenGL2();
if (m_enableBlending)
{
glEnable(GL_BLEND);
}
else
{
glDisable(GL_BLEND);
}
if ((m_funcSourceRGB == m_funcSourceAlpha) && (m_funcDestinationRGB == m_funcDestinationAlpha))
{
glBlendFunc(blendFuncOpenGL(m_funcSourceRGB), blendFuncOpenGL(m_funcDestinationRGB));
}
else
{
if (openGL2Support)
{
glBlendFuncSeparate(blendFuncOpenGL(m_funcSourceRGB), blendFuncOpenGL(m_funcDestinationRGB), blendFuncOpenGL(m_funcSourceAlpha), blendFuncOpenGL(m_funcDestinationAlpha));
}
else
{
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support separate blend functions.");
}
}
if (openGL2Support)
{
if (m_equationRGB == m_equationAlpha)
{
glBlendEquation(blendEquationOpenGL(m_equationRGB));
}
else
{
glBlendEquationSeparate(blendEquationOpenGL(m_equationRGB), blendEquationOpenGL(m_equationAlpha));
}
glBlendColor(m_blendColor.r(), m_blendColor.g(), m_blendColor.b(), m_blendColor.a());
}
else
{
// Only error reporting here
if (m_equationRGB != FUNC_ADD ||
m_equationRGB != m_equationAlpha)
{
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support blend equations.");
}
if (m_blendColor != Color4f(0, 0, 0, 0))
{
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support blend color.");
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvfGLenum RenderStateBlending::blendEquationOpenGL(Equation eq) const
{
switch (eq)
{
case FUNC_ADD: return GL_FUNC_ADD;
case FUNC_SUBTRACT: return GL_FUNC_SUBTRACT;
case FUNC_REVERSE_SUBTRACT: return GL_FUNC_REVERSE_SUBTRACT;
#ifndef CVF_OPENGL_ES
case MIN: return GL_MIN;
case MAX: return GL_MAX;
#endif
}
CVF_FAIL_MSG("Unhandled blend equation");
return 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvfGLenum RenderStateBlending::blendFuncOpenGL(Function func) const
{
switch (func)
{
case ZERO: return GL_ZERO;
case ONE: return GL_ONE;
case SRC_COLOR: return GL_SRC_COLOR;
case ONE_MINUS_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR;
case DST_COLOR: return GL_DST_COLOR;
case ONE_MINUS_DST_COLOR: return GL_ONE_MINUS_DST_COLOR;
case SRC_ALPHA: return GL_SRC_ALPHA;
case ONE_MINUS_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA;
case DST_ALPHA: return GL_DST_ALPHA;
case ONE_MINUS_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA;
case CONSTANT_COLOR: return GL_CONSTANT_COLOR;
case ONE_MINUS_CONSTANT_COLOR: return GL_ONE_MINUS_CONSTANT_COLOR;
case CONSTANT_ALPHA: return GL_CONSTANT_ALPHA;
case ONE_MINUS_CONSTANT_ALPHA: return GL_ONE_MINUS_CONSTANT_ALPHA;
case SRC_ALPHA_SATURATE: return GL_SRC_ALPHA_SATURATE;
}
CVF_FAIL_MSG("Unhandled blend func");
return 0;
}
} // namespace cvf

View File

@@ -0,0 +1,99 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfRenderState.h"
#include "cvfOpenGLTypes.h"
#include "cvfColor4.h"
namespace cvf {
//==================================================================================================
//
// Controls OpenGL blending
//
//==================================================================================================
class RenderStateBlending : public RenderState
{
public:
enum Function
{
ZERO,
ONE,
SRC_COLOR,
ONE_MINUS_SRC_COLOR,
DST_COLOR,
ONE_MINUS_DST_COLOR,
SRC_ALPHA,
ONE_MINUS_SRC_ALPHA,
DST_ALPHA,
ONE_MINUS_DST_ALPHA,
CONSTANT_COLOR,
ONE_MINUS_CONSTANT_COLOR,
CONSTANT_ALPHA,
ONE_MINUS_CONSTANT_ALPHA,
SRC_ALPHA_SATURATE
};
enum Equation
{
FUNC_ADD,
FUNC_SUBTRACT,
FUNC_REVERSE_SUBTRACT,
MIN, // Unsupported on OpenGL ES
MAX // Unsupported on OpenGL ES
};
public:
RenderStateBlending();
void enableBlending(bool blend);
void setFunction(Function source, Function destination);
void setEquation(Equation equation);
void setFunctionSeparate(Function sourceRGB, Function destinationRGB, Function sourceAlpha, Function destinationAlpha);
void setEquationSeparate(Equation equationRGB, Equation equationAlpha);
void setBlendColor(Color4f blendColor);
void configureTransparencyBlending();
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
cvfGLenum blendFuncOpenGL(Function func) const;
cvfGLenum blendEquationOpenGL(Equation eq) const;
private:
bool m_enableBlending;
Function m_funcSourceRGB;
Function m_funcDestinationRGB;
Function m_funcSourceAlpha;
Function m_funcDestinationAlpha;
Equation m_equationRGB;
Equation m_equationAlpha;
Color4f m_blendColor;
};
} // namespace cvf

View File

@@ -0,0 +1,130 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRenderStateColorMask.h"
#include "cvfAssert.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStateColorMask
/// \ingroup Render
///
/// Encapsulate OpenGL glColorMask() function.
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glColorMask.xml
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateColorMask::RenderStateColorMask(bool writeAllComponents)
: RenderState(COLOR_MASK),
m_writeRed(writeAllComponents),
m_writeGreen(writeAllComponents),
m_writeBlue(writeAllComponents),
m_writeAlpha(writeAllComponents)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateColorMask::enable(bool writeRed, bool writeGreen, bool writeBlue, bool writeAlpha)
{
m_writeRed = writeRed;
m_writeGreen = writeGreen;
m_writeBlue = writeBlue;
m_writeAlpha = writeAlpha;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateColorMask::enableWriteAllComponents(bool writeAllComponents)
{
m_writeRed = writeAllComponents;
m_writeGreen = writeAllComponents;
m_writeBlue = writeAllComponents;
m_writeAlpha = writeAllComponents;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStateColorMask::isRedEnabled() const
{
return m_writeRed;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStateColorMask::isGreenEnabled() const
{
return m_writeGreen;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStateColorMask::isBlueEnabled() const
{
return m_writeBlue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStateColorMask::isAlphaEnabled() const
{
return m_writeAlpha;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateColorMask::applyOpenGL(OpenGLContext* oglContext) const
{
GLboolean writeRed = m_writeRed ? static_cast<GLboolean>(GL_TRUE) : static_cast<GLboolean>(GL_FALSE);
GLboolean writeGreen = m_writeGreen ? static_cast<GLboolean>(GL_TRUE) : static_cast<GLboolean>(GL_FALSE);
GLboolean writeBlue = m_writeBlue ? static_cast<GLboolean>(GL_TRUE) : static_cast<GLboolean>(GL_FALSE);
GLboolean writeAlpha = m_writeAlpha ? static_cast<GLboolean>(GL_TRUE) : static_cast<GLboolean>(GL_FALSE);
glColorMask(writeRed, writeGreen, writeBlue, writeAlpha);
CVF_CHECK_OGL(oglContext);
}
} // namespace cvf

View File

@@ -0,0 +1,55 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfRenderState.h"
namespace cvf {
//==================================================================================================
//
// Encapsulate OpenGL glColorMask() function.
//
//==================================================================================================
class RenderStateColorMask : public RenderState
{
public:
RenderStateColorMask(bool writeAllComponents = true);
void enable(bool writeRed, bool writeGreen, bool writeBlue, bool writeAlpha);
void enableWriteAllComponents(bool writeAllComponents);
bool isRedEnabled() const;
bool isGreenEnabled() const;
bool isBlueEnabled() const;
bool isAlphaEnabled() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
bool m_writeRed;
bool m_writeGreen;
bool m_writeBlue;
bool m_writeAlpha;
};
} // namespace cvf

View File

@@ -0,0 +1,120 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRenderStateCullFace.h"
#include "cvfAssert.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStateCullFace
/// \ingroup Render
///
/// Encapsulate OpenGL glCullFace() and glEnable(GL_CULL_FACE) functions.
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glCullFace.xml
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateCullFace::RenderStateCullFace(bool enableCulling, Mode faceMode)
: RenderState(CULL_FACE),
m_enableCulling(enableCulling),
m_faceMode(faceMode)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateCullFace::enable(bool enableCulling)
{
m_enableCulling = enableCulling;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStateCullFace::isEnabled() const
{
return m_enableCulling;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateCullFace::setMode(Mode faceMode)
{
m_faceMode = faceMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateCullFace::Mode RenderStateCullFace::mode() const
{
return m_faceMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateCullFace::applyOpenGL(OpenGLContext* oglContext) const
{
if (m_enableCulling)
{
if (m_faceMode == BACK)
{
glCullFace(GL_BACK);
}
else if (m_faceMode == FRONT)
{
glCullFace(GL_FRONT);
}
else
{
glCullFace(GL_FRONT_AND_BACK);
}
glEnable(GL_CULL_FACE);
}
else
{
glDisable(GL_CULL_FACE);
}
CVF_CHECK_OGL(oglContext);
}
} // namespace cvf

View File

@@ -0,0 +1,60 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfRenderState.h"
namespace cvf {
//==================================================================================================
//
// Encapsulate OpenGL glCullFace() and glEnable(GL_CULL_FACE) functions.
//
//==================================================================================================
class RenderStateCullFace : public RenderState
{
public:
enum Mode
{
BACK, ///< Cull back facing polygons
FRONT, ///< Cull front facing polygons
FRONT_AND_BACK ///< No polygons are drawn, but other primitives such as points and lines are drawn
};
public:
RenderStateCullFace(bool enableCulling = true, Mode faceMode = BACK);
void enable(bool enableCulling);
bool isEnabled() const;
void setMode(Mode faceMode);
Mode mode() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
bool m_enableCulling;
Mode m_faceMode;
};
} // namespace cvf

View File

@@ -0,0 +1,173 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRenderStateDepth.h"
#include "cvfAssert.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStateDepth
/// \ingroup Render
///
/// Encapsulate OpenGL glEnable(GL_DEPTH_TEST), glDepthFunc() and glDepthMask() functions.
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glDepthFunc.xml
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glDepthMask.xml
///
/// \todo
/// Add support for glDepthRange() if needed.
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateDepth::RenderStateDepth(bool depthTest, Function func, bool depthWrite)
: RenderState(DEPTH)
{
m_enableDepthTest = depthTest;
m_depthFunc = func;
m_enableDepthWrite = depthWrite;
}
//--------------------------------------------------------------------------------------------------
/// Specifies the depth comparison function.
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glDepthFunc.xml
//--------------------------------------------------------------------------------------------------
void RenderStateDepth::setFunction(Function func)
{
m_depthFunc = func;
}
//--------------------------------------------------------------------------------------------------
/// Enable or disable depth testing and updating of the depth buffer.
///
/// \param enableTest Specify true to enable testing against and updating of depth buffer.
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml with GL_DEPTH_TEST
///
/// From OpenGL docs:
/// If enabled, do depth comparisons and update the depth buffer. Note that even if the depth buffer
/// exists and the depth mask is non-zero, the depth buffer is not updated if the depth test is disabled
//--------------------------------------------------------------------------------------------------
void RenderStateDepth::enableDepthTest(bool enableTest)
{
m_enableDepthTest = enableTest;
}
//--------------------------------------------------------------------------------------------------
/// Enable or disable writing into the depth buffer
///
/// \param enableWrite Specify true to enable writing to depth buffer, false to disable. The default is true.
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glDepthMask.xml
//--------------------------------------------------------------------------------------------------
void RenderStateDepth::enableDepthWrite(bool enableWrite)
{
m_enableDepthWrite = enableWrite;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateDepth::Function RenderStateDepth::function() const
{
return m_depthFunc;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStateDepth::isDepthTestEnabled() const
{
return m_enableDepthTest;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStateDepth::isDepthWriteEnabled() const
{
return m_enableDepthWrite;
}
//--------------------------------------------------------------------------------------------------
/// Specify the depth setting to OpenGL.
//--------------------------------------------------------------------------------------------------
void RenderStateDepth::applyOpenGL(OpenGLContext* oglContext) const
{
if (m_enableDepthTest)
{
GLenum depthFuncOGL = depthFuncOpenGL();
glDepthFunc(depthFuncOGL);
GLboolean enableDepthWrite = m_enableDepthWrite ? static_cast<GLboolean>(GL_TRUE) : static_cast<GLboolean>(GL_FALSE);
glDepthMask(enableDepthWrite);
glEnable(GL_DEPTH_TEST);
}
else
{
glDisable(GL_DEPTH_TEST);
}
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvfGLenum RenderStateDepth::depthFuncOpenGL() const
{
switch (m_depthFunc)
{
case NEVER: return GL_NEVER;
case LESS: return GL_LESS;
case EQUAL: return GL_EQUAL;
case LEQUAL: return GL_LEQUAL;
case GREATER: return GL_GREATER;
case NOTEQUAL: return GL_NOTEQUAL;
case GEQUAL: return GL_GEQUAL;
case ALWAYS: return GL_ALWAYS;
}
CVF_FAIL_MSG("Unhandled depth func");
return 0;
}
} // namespace cvf

View File

@@ -0,0 +1,70 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfRenderState.h"
#include "cvfOpenGLTypes.h"
namespace cvf {
//==================================================================================================
//
// Encapsulate OpenGL glEnable(GL_DEPTH_TEST), glDepthFunc() and glDepthMask() functions.
//
//==================================================================================================
class RenderStateDepth : public RenderState
{
public:
enum Function
{
NEVER, ///< Never passes
LESS, ///< Passes if the incoming depth value is less than the stored depth value. This is the OpenGL default.
EQUAL, ///< Passes if the incoming depth value is equal to the stored depth value.
LEQUAL, ///< Passes if the incoming depth value is less than or equal to the stored depth value.
GREATER, ///< Passes if the incoming depth value is greater than the stored depth value.
NOTEQUAL, ///< Passes if the incoming depth value is not equal to the stored depth value.
GEQUAL, ///< Passes if the incoming depth value is greater than or equal to the stored depth value.
ALWAYS ///< Always passes.
};
public:
RenderStateDepth(bool depthTest = true, Function func = LESS, bool depthWrite = true);
void setFunction(Function func);
void enableDepthTest(bool enableTest);
void enableDepthWrite(bool enableWrite);
Function function() const;
bool isDepthTestEnabled() const;
bool isDepthWriteEnabled() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
cvfGLenum depthFuncOpenGL() const;
private:
Function m_depthFunc;
bool m_enableDepthTest;
bool m_enableDepthWrite;
};
} // namespace cvf

View File

@@ -0,0 +1,89 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRenderStateFrontFace.h"
#include "cvfAssert.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStateFrontFace
/// \ingroup Render
///
/// Encapsulate OpenGL glFrontFace() used to specify polygon winding. Used together with RenderStateCullFace
/// render state and the gl_FrontFacing bultin shader input variable.
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glFrontFace.xml
/// \sa http://www.opengl.org/sdk/docs/manglsl/xhtml/gl_FrontFacing.xml
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateFrontFace::RenderStateFrontFace(Mode faceMode)
: RenderState(FRONT_FACE),
m_faceMode(faceMode)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateFrontFace::setMode(Mode faceMode)
{
m_faceMode = faceMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateFrontFace::Mode RenderStateFrontFace::mode() const
{
return m_faceMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateFrontFace::applyOpenGL(OpenGLContext* oglContext) const
{
if (m_faceMode == CW)
{
glFrontFace(GL_CW);
}
else
{
glFrontFace(GL_CCW);
}
CVF_CHECK_OGL(oglContext);
}
} // namespace cvf

View File

@@ -17,23 +17,39 @@
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfLegendScalarMapper.h"
#pragma once
#include "cvfRenderState.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::LegendScalarMapper
/// \ingroup Render
///
/// Abstract base class for ScalarMapper's that communicate with a legend
///
//
// Encapsulate OpenGL glFrontFace().
//
//==================================================================================================
class RenderStateFrontFace : public RenderState
{
public:
enum Mode
{
CCW, ///< Counterclockwise order (default)
CW ///< Clockwise order
};
public:
RenderStateFrontFace(Mode faceMode = CCW);
void setMode(Mode faceMode);
Mode mode() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
Mode m_faceMode;
};
} // namespace cvf
} // namespace cvf

View File

@@ -0,0 +1,110 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRenderStateLine.h"
#include "cvfAssert.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStateLine
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateLine::RenderStateLine(float lineWidth)
: RenderState(LINE),
m_lineWidth(lineWidth),
m_smooth(false)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateLine::setWidth(float lineWidth)
{
m_lineWidth = lineWidth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RenderStateLine::width() const
{
return m_lineWidth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateLine::enableSmooth(bool enableSmooth)
{
m_smooth = enableSmooth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStateLine::isSmoothEnabled() const
{
return m_smooth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateLine::applyOpenGL(OpenGLContext* oglContext) const
{
CVF_UNUSED(oglContext);
glLineWidth(m_lineWidth);
#ifndef CVF_OPENGL_ES
if (m_smooth)
{
glEnable(GL_LINE_SMOOTH);
}
else
{
glDisable(GL_LINE_SMOOTH);
}
#endif
}
} // namespace cvf

View File

@@ -19,30 +19,33 @@
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfArray.h"
#include "cvfScalarMapper.h"
#include <vector>
#include "cvfRenderState.h"
namespace cvf {
//==================================================================================================
//
// Abstract base class for scalar mappers that communicate with a legend
// Controls OpenGL linewidth and aliasing, glLineWidth() and glEnable()/glDisable() with GL_LINE SMOOTH
//
//==================================================================================================
class LegendScalarMapper : public ScalarMapper
class RenderStateLine : public RenderState
{
public:
// Return a the set of domain values representing sensible major tickmarks
virtual void majorLevels(std::vector<double>* domainValues) const = 0;
// Return the normalized (0.0, 1.0) representation of the domainValue
virtual double normalizedLevelPosition(double domainValue) const = 0;
// Return the domain value from a normalized val
virtual double domainValue(double normalizedPosition) const = 0;
RenderStateLine(float lineWidth = 1.0f);
void setWidth(float lineWidth);
float width() const;
void enableSmooth(bool enableSmooth);
bool isSmoothEnabled() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
float m_lineWidth;
bool m_smooth;
};
}
} // namespace cvf

View File

@@ -0,0 +1,165 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRenderStatePoint.h"
#include "cvfAssert.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLCapabilities.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStatePoint
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStatePoint::RenderStatePoint(Mode sizeMode)
: RenderState(POINT),
m_sizeMode(sizeMode),
m_pointSprite(false),
m_pointSize(1.0f)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePoint::setMode(Mode sizeMode)
{
m_sizeMode = sizeMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStatePoint::Mode RenderStatePoint::mode() const
{
return m_sizeMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePoint::enablePointSprite(bool enable)
{
m_pointSprite = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStatePoint::isPointSpriteEnabled() const
{
return m_pointSprite;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePoint::setSize(float pointSize)
{
m_pointSize = pointSize;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RenderStatePoint::size() const
{
return m_pointSize;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePoint::applyOpenGL(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
// OpenGL ES does not support fixed point size
// Point size is always specified using GLSL's gl_PointSize
#ifndef CVF_OPENGL_ES
bool openGL2Support = oglContext->capabilities()->supportsOpenGL2();
if (m_sizeMode == FIXED_SIZE)
{
if (openGL2Support)
{
glDisable(GL_PROGRAM_POINT_SIZE);
}
glPointSize(m_pointSize);
}
else
{
if (openGL2Support)
{
glEnable(GL_PROGRAM_POINT_SIZE);
}
else
{
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support program point size.");
}
}
if (openGL2Support)
{
if (m_pointSprite)
{
glEnable(GL_POINT_SPRITE);
glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
}
else
{
glDisable(GL_POINT_SPRITE);
}
}
else
{
if (m_pointSprite)
{
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support point sprites.");
}
}
#endif
CVF_CHECK_OGL(oglContext);
}
} // namespace cvf

View File

@@ -0,0 +1,61 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfRenderState.h"
namespace cvf {
//==================================================================================================
//
// Controls OpenGL point size, glPointSize() and glEnable()/glDisable() with GL_PROGRAM_POINT_SIZE
//
//==================================================================================================
class RenderStatePoint : public RenderState
{
public:
enum Mode
{
FIXED_SIZE, ///< Fixed diameter of raserized points (as specified by point size/glPointSize())
PROGRAM_SIZE ///< Point size will be specified using GLSL and the gl_PointSize built-in variable
};
public:
RenderStatePoint(Mode sizeMode = FIXED_SIZE);
void setMode(Mode sizeMode);
Mode mode() const;
void enablePointSprite(bool enable);
bool isPointSpriteEnabled() const;
void setSize(float pointSize);
float size() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
Mode m_sizeMode;
bool m_pointSprite;
float m_pointSize;
};
} // namespace cvf

View File

@@ -0,0 +1,135 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRenderStatePolygonMode.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStatePolygonMode
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStatePolygonMode::RenderStatePolygonMode(Mode frontAndBackFaceMode)
: RenderState(POLYGON_MODE),
m_frontFaceMode(frontAndBackFaceMode),
m_backFaceMode(frontAndBackFaceMode)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonMode::set(Mode frontAndBackMode)
{
m_frontFaceMode = frontAndBackMode;
m_backFaceMode = frontAndBackMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonMode::setFrontFace(Mode mode)
{
m_frontFaceMode = mode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonMode::setBackFace(Mode mode)
{
m_backFaceMode = mode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStatePolygonMode::Mode RenderStatePolygonMode::frontFace() const
{
return m_frontFaceMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStatePolygonMode::Mode RenderStatePolygonMode::backFace() const
{
return m_backFaceMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonMode::applyOpenGL(OpenGLContext* oglContext) const
{
#ifndef CVF_OPENGL_ES
if (m_frontFaceMode == m_backFaceMode)
{
glPolygonMode(GL_FRONT_AND_BACK, polygonModeOpenGL(m_frontFaceMode));
}
else
{
glPolygonMode(GL_FRONT, polygonModeOpenGL(m_frontFaceMode));
glPolygonMode(GL_BACK, polygonModeOpenGL(m_backFaceMode));
}
#endif
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvfGLenum RenderStatePolygonMode::polygonModeOpenGL(Mode mode)
{
switch (mode)
{
#ifndef CVF_OPENGL_ES
case FILL: return GL_FILL;
case LINE: return GL_LINE;
case POINT: return GL_POINT;
default: CVF_FAIL_MSG("Unhandled polygon mode");
#endif
}
return 0;
}
} // namespace cvf

View File

@@ -0,0 +1,65 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfRenderState.h"
#include "cvfOpenGLTypes.h"
#include "cvfColor4.h"
namespace cvf {
//==================================================================================================
//
// Controls OpenGL polygon rasterization mode, glPolygonMode()
//
//==================================================================================================
class RenderStatePolygonMode : public RenderState
{
public:
enum Mode
{
FILL, ///< The interior of the polygons is filled
LINE, ///< Boundary edges of the polygons are drawn as line segments
POINT ///< Polygon vertices that are marked as the start of a boundary edge are drawn as points
};
public:
RenderStatePolygonMode(Mode frontAndBackFaceMode = FILL);
void set(Mode frontAndBackMode);
void setFrontFace(Mode mode);
void setBackFace(Mode mode);
Mode frontFace() const;
Mode backFace() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
static cvfGLenum polygonModeOpenGL(Mode mode);
private:
Mode m_frontFaceMode;
Mode m_backFaceMode;
};
} // namespace cvf

View File

@@ -0,0 +1,196 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfAssert.h"
#include "cvfRenderStatePolygonOffset.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStatePolygonOffset
/// \ingroup Render
///
/// Encapsulate OpenGL glPolygonOffset() and glEnable()/glDisable() with GL_POLYGON_OFFSET_FILL/LINE/POINT
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glPolygonOffset.xml
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
///
//==================================================================================================
RenderStatePolygonOffset::RenderStatePolygonOffset()
: RenderState(POLYGON_OFFSET),
m_factor(0.0f),
m_units(0.0f),
m_enableFillMode(false),
m_enableLineMode(false),
m_enablePointMode(false)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonOffset::enableFillMode(bool enableFill)
{
m_enableFillMode = enableFill;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonOffset::enableLineMode(bool enableLine)
{
m_enableLineMode = enableLine;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonOffset::enablePointMode(bool enablePoint)
{
m_enablePointMode = enablePoint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStatePolygonOffset::isFillModeEnabled() const
{
return m_enableFillMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStatePolygonOffset::isLineModeEnabled() const
{
return m_enableLineMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderStatePolygonOffset::isPointModeEnabled() const
{
return m_enablePointMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonOffset::setFactor(float factor)
{
m_factor = factor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonOffset::setUnits(float units)
{
m_units = units;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RenderStatePolygonOffset::factor() const
{
return m_factor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RenderStatePolygonOffset::units() const
{
return m_units;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonOffset::configurePolygonPositiveOffset()
{
m_enableFillMode = true;
m_enableLineMode = false;
m_enablePointMode = false;
m_factor = 1.0;
m_units = 1.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonOffset::configureLineNegativeOffset()
{
m_enableFillMode = false;
m_enableLineMode = true;
m_enablePointMode = false;
m_factor = -1.0;
m_units = -1.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStatePolygonOffset::applyOpenGL(OpenGLContext* oglContext) const
{
if (m_enableFillMode ||
m_enableLineMode ||
m_enablePointMode)
{
glPolygonOffset(m_factor, m_units);
}
if (m_enableFillMode) glEnable(GL_POLYGON_OFFSET_FILL);
else glDisable(GL_POLYGON_OFFSET_FILL);
#ifndef CVF_OPENGL_ES
if (m_enableLineMode) glEnable(GL_POLYGON_OFFSET_LINE);
else glDisable(GL_POLYGON_OFFSET_LINE);
if (m_enablePointMode) glEnable(GL_POLYGON_OFFSET_POINT);
else glDisable(GL_POLYGON_OFFSET_POINT);
#endif
CVF_CHECK_OGL(oglContext);
}
} // namespace cvf

View File

@@ -0,0 +1,66 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfRenderState.h"
#include "cvfOpenGLTypes.h"
#include "cvfColor4.h"
namespace cvf {
//==================================================================================================
//
// Encapsulate OpenGL glPolygonOffset() and glEnable()/glDisable() with GL_POLYGON_OFFSET_FILL/LINE/POINT
//
//==================================================================================================
class RenderStatePolygonOffset : public RenderState
{
public:
RenderStatePolygonOffset();
void enableFillMode(bool enableFill);
void enableLineMode(bool enableLine);
void enablePointMode(bool enablePoint);
bool isFillModeEnabled() const;
bool isLineModeEnabled() const;
bool isPointModeEnabled() const;
void setFactor(float factor);
void setUnits(float units);
float factor() const;
float units() const;
void configurePolygonPositiveOffset();
void configureLineNegativeOffset();
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
float m_factor; // Default value is 0.0
float m_units; // Default value is 0.0
bool m_enableFillMode;
bool m_enableLineMode;
bool m_enablePointMode;
};
} // namespace cvf

View File

@@ -0,0 +1,159 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRenderStateStencil.h"
#include "cvfAssert.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStateStencil
/// \ingroup Render
///
/// glStencilFunc(), glStencilOp() and glEnable(GL_STENCIL_TEST) functions.
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glStencilFunc.xml
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glStencilOp.xml
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateStencil::RenderStateStencil()
: RenderState(STENCIL),
m_function(ALWAYS),
m_functionRefValue(0),
m_functionMask(0xffffffff),
m_opStencilFails(KEEP),
m_opStencilPassesDepthFails(KEEP),
m_opStencilPassesDepthPasses(KEEP),
m_enable(false)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateStencil::enableStencilTest(bool enableTest)
{
m_enable = enableTest;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateStencil::setFunction(Function func, int refValue, uint mask)
{
m_function = func;
m_functionRefValue = refValue;
m_functionMask = mask;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateStencil::setOperation(Operation stencilFails, Operation stencilPassesDepthFails, Operation stencilPassesDepthPasses)
{
m_opStencilFails = stencilFails;
m_opStencilPassesDepthFails = stencilPassesDepthFails;
m_opStencilPassesDepthPasses = stencilPassesDepthPasses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateStencil::applyOpenGL(OpenGLContext* oglContext) const
{
if (m_enable)
{
GLenum funcOGL = functionOpenGL(m_function);
glStencilFunc(funcOGL, m_functionRefValue, m_functionMask);
const GLenum stencilFailsOGL = operationOpenGL(m_opStencilFails);
const GLenum stencilPassesDepthFails = operationOpenGL(m_opStencilPassesDepthFails);
const GLenum stencilPassesDepthPasses = operationOpenGL(m_opStencilPassesDepthPasses);
glStencilOp(stencilFailsOGL, stencilPassesDepthFails, stencilPassesDepthPasses);
glEnable(GL_STENCIL_TEST);
}
else
{
glDisable(GL_STENCIL_TEST);
}
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::cvfGLenum RenderStateStencil::functionOpenGL(Function func)
{
switch (func)
{
case NEVER: return GL_NEVER;
case LESS: return GL_LESS;
case LEQUAL: return GL_LEQUAL;
case GREATER: return GL_GREATER;
case GEQUAL: return GL_GEQUAL;
case EQUAL: return GL_EQUAL;
case NOTEQUAL: return GL_NOTEQUAL;
case ALWAYS: return GL_ALWAYS;
}
CVF_FAIL_MSG("Unhandled stencil func");
return 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::cvfGLenum RenderStateStencil::operationOpenGL(Operation op)
{
switch (op)
{
case KEEP: return GL_KEEP;
case ZERO: return GL_ZERO;
case REPLACE: return GL_REPLACE;
case INCR: return GL_INCR;
case INCR_WRAP: return GL_INCR_WRAP;
case DECR: return GL_DECR;
case DECR_WRAP: return GL_DECR_WRAP;
case INVERT: return GL_INVERT;
}
CVF_FAIL_MSG("Unhandled stencil operation");
return 0;
}
} // namespace cvf

View File

@@ -0,0 +1,84 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfRenderState.h"
#include "cvfOpenGLTypes.h"
namespace cvf {
//==================================================================================================
//
// Encapsulate OpenGL glStencilFunc(), glStencilOp() and glEnable(GL_STENCIL_TEST) functions.
//
//==================================================================================================
class RenderStateStencil : public RenderState
{
public:
enum Function
{
NEVER, ///< Always fails.
LESS, ///< Passes if ( ref & mask ) < ( stencil & mask ).
LEQUAL, ///< Passes if ( ref & mask ) <= ( stencil & mask ).
GREATER, ///< Passes if ( ref & mask ) > ( stencil & mask ).
GEQUAL, ///< Passes if ( ref & mask ) >= ( stencil & mask ).
EQUAL, ///< Passes if ( ref & mask ) = ( stencil & mask ).
NOTEQUAL, ///< Passes if ( ref & mask ) != ( stencil & mask ).
ALWAYS ///< Always passes.
};
enum Operation
{
KEEP, ///< Keeps the current value.
ZERO, ///< Sets the stencil buffer value to 0.
REPLACE, ///< Sets the stencil buffer value to ref, as specified by glStencilFunc.
INCR, ///< Increments the current stencil buffer value. Clamps to the maximum representable unsigned value.
INCR_WRAP, ///< Increments the current stencil buffer value. Wraps stencil buffer value to zero when incrementing the maximum representable unsigned value.
DECR, ///< Decrements the current stencil buffer value. Clamps to 0.
DECR_WRAP, ///< Decrements the current stencil buffer value. Wraps stencil buffer value to the maximum representable unsigned value when decrementing a stencil buffer value of zero.
INVERT ///< Bitwise inverts the current stencil buffer value.
};
public:
RenderStateStencil();
void enableStencilTest(bool enableTest);
void setFunction(Function func, int refValue, uint mask);
void setOperation(Operation stencilFails, Operation stencilPassesDepthFails, Operation stencilPassesDepthPasses);
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
private:
static cvfGLenum functionOpenGL(Function func);
static cvfGLenum operationOpenGL(Operation op);
private:
Function m_function; // Stencil test function. Initial value ALWAYS
int m_functionRefValue; // Reference value for the stencil test. Initial value is 0
uint m_functionMask; // Mask that is ANDed with both the reference value and the stored stencil value when the test is done. Initial value is all 1's
Operation m_opStencilFails; // Action to take when the stencil test fails. Initial value is KEEP.
Operation m_opStencilPassesDepthFails; // Stencil action when the stencil test passes, but the depth test fails. Initial value is KEEP
Operation m_opStencilPassesDepthPasses; // Stencil action when both the stencil test and the depth test passes. Initial value is KEEP
bool m_enable; // Enable/disable the stencil test
};
} // namespace cvf

View File

@@ -0,0 +1,251 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRenderStateTextureBindings.h"
#include "cvfAssert.h"
#include "cvfOpenGL.h"
#include "cvfUniform.h"
#include "cvfShaderProgram.h"
#include "cvfTexture.h"
#include "cvfSampler.h"
#include "cvfOpenGLCapabilities.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStateTextureBindings
/// \ingroup Render
///
/// \warning Requires OpenGL2 support
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateTextureBindings::RenderStateTextureBindings()
: RenderState(TEXTURE_BINDINGS),
m_bindingCount(0)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateTextureBindings::RenderStateTextureBindings(Texture* texture, Sampler* sampler, const char* samplerUniformName)
: RenderState(TEXTURE_BINDINGS),
m_bindingCount(0)
{
addBinding(texture, sampler, samplerUniformName);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateTextureBindings::~RenderStateTextureBindings()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateTextureBindings::addBinding(Texture* texture, Sampler* sampler, const char* samplerUniformName)
{
CVF_ASSERT(m_bindingCount < MAX_TEXTURE_UNITS - 1);
CVF_ASSERT(texture && sampler && samplerUniformName);
m_bindings[m_bindingCount].sampler = sampler;
m_bindings[m_bindingCount].texture = texture;
m_bindings[m_bindingCount].samplerUniformName = samplerUniformName;
m_bindingCount++;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RenderStateTextureBindings::bindingCount() const
{
return m_bindingCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Texture* RenderStateTextureBindings::texture(int bindingIdx)
{
CVF_ASSERT(bindingIdx >= 0 && bindingIdx < m_bindingCount);
return m_bindings[bindingIdx].texture.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Texture* RenderStateTextureBindings::texture(int bindingIdx) const
{
CVF_ASSERT(bindingIdx >= 0 && bindingIdx < m_bindingCount);
return m_bindings[bindingIdx].texture.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Sampler* RenderStateTextureBindings::sampler(int bindingIdx) const
{
CVF_ASSERT(bindingIdx >= 0 && bindingIdx < m_bindingCount);
return m_bindings[bindingIdx].sampler.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Sampler* RenderStateTextureBindings::sampler(int bindingIdx)
{
CVF_ASSERT(bindingIdx >= 0 && bindingIdx < m_bindingCount);
return m_bindings[bindingIdx].sampler.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String RenderStateTextureBindings::samplerUniformName(int bindingIdx) const
{
CVF_ASSERT(bindingIdx >= 0 && bindingIdx < m_bindingCount);
return m_bindings[bindingIdx].samplerUniformName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateTextureBindings::setupTextures(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
const OpenGLCapabilities* oglCaps = oglContext->capabilities();
if (!oglCaps->supportsOpenGL2())
{
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support texture setup using RenderStateTextureBindings.");
return;
}
glActiveTexture(GL_TEXTURE0);
int i;
for (i = 0; i < m_bindingCount; i++)
{
Texture* texture = m_bindings[i].texture.p();
if (texture->textureOglId() == 0)
{
glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + i));
texture->setupTexture(oglContext);
CVF_CHECK_OGL(oglContext);
}
else
{
// Handle case where mipmap generation is enabled, but the mipmaps are not present
// This will typically happen if the texture has been rendered to using an FBO
// In that case the texture exists, but no mipmaps have yet been generated
if (texture->isMipmapGenerationEnabled() && !texture->hasMipmap())
{
if (oglCaps->hasCapability(OpenGLCapabilities::GENERATE_MIPMAP_FUNC))
{
glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + i));
texture->generateMipmap(oglContext);
CVF_CHECK_OGL(oglContext);
}
else
{
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support explicit mipmap generation.");
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateTextureBindings::applyOpenGL(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
// The apply function needs to work for all contexts in its default state
// so just return if no bindings have been set
if (m_bindingCount == 0)
{
return;
}
if (!oglContext->capabilities()->supportsOpenGL2())
{
CVF_LOG_RENDER_ERROR(oglContext, "Context does not support TextureBinding application.");
return;
}
int i;
for (i = 0; i < m_bindingCount; i++)
{
const Texture* texture = m_bindings[i].texture.p();
const Sampler* sampler = m_bindings[i].sampler.p();
CVF_ASSERT(texture && sampler);
glActiveTexture(static_cast<GLenum>(GL_TEXTURE0 + i));
texture->bind(oglContext);
texture->setupTextureParamsFromSampler(oglContext, *sampler);
CVF_CHECK_OGL(oglContext);
}
}
//--------------------------------------------------------------------------------------------------
/// Specify the mapping between the sampler name in the shader program and the texture unit
/// This is done by providing an Int Uniform with the name of the sampler and the index of the
/// texture unit.
//--------------------------------------------------------------------------------------------------
void RenderStateTextureBindings::applySamplerTextureUnitUniforms(OpenGLContext* oglContext, ShaderProgram* shaderProgram) const
{
CVF_ASSERT(shaderProgram);
int i;
for (i = 0; i < m_bindingCount; i++)
{
UniformInt uniform(m_bindings[i].samplerUniformName.toAscii().ptr(), i);
shaderProgram->applyUniform(oglContext, uniform);
}
}
} // namespace cvf

View File

@@ -0,0 +1,73 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfRenderState.h"
#include "cvfString.h"
namespace cvf {
class Sampler;
class Texture;
class ShaderProgram;
//==================================================================================================
//
// Binds a texture and a sampler to a texture unit
//
//==================================================================================================
class RenderStateTextureBindings : public RenderState
{
public:
RenderStateTextureBindings();
RenderStateTextureBindings(Texture* texture, Sampler* sampler, const char* samplerUniformName);
~RenderStateTextureBindings();
void addBinding(Texture* texture, Sampler* sampler, const char* samplerUniformName);
int bindingCount() const;
Texture* texture(int bindingIdx);
const Texture* texture(int bindingIdx) const;
Sampler* sampler(int bindingIdx);
const Sampler* sampler(int bindingIdx) const;
String samplerUniformName(int bindingIdx) const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
void setupTextures(OpenGLContext* oglContext);
void applySamplerTextureUnitUniforms(OpenGLContext* oglContext, ShaderProgram* shaderProgram) const;
public:
static const int MAX_TEXTURE_UNITS = 16;
private:
struct BindingEntry
{
ref<Texture> texture;
ref<Sampler> sampler;
String samplerUniformName;
};
BindingEntry m_bindings[MAX_TEXTURE_UNITS];
int m_bindingCount;
};
} // namespace cvf

View File

@@ -20,6 +20,17 @@
#include "cvfBase.h"
#include "cvfRenderStateTracker.h"
#include "cvfRenderStateSet.h"
#include "cvfRenderStateBlending.h"
#include "cvfRenderStateColorMask.h"
#include "cvfRenderStateCullFace.h"
#include "cvfRenderStateDepth.h"
#include "cvfRenderStateFrontFace.h"
#include "cvfRenderStateLine.h"
#include "cvfRenderStatePoint.h"
#include "cvfRenderStatePolygonMode.h"
#include "cvfRenderStatePolygonOffset.h"
#include "cvfRenderStateStencil.h"
#include "cvfRenderStateTextureBindings.h"
#include "cvfOpenGLContext.h"
#include "cvfOpenGLCapabilities.h"
@@ -59,21 +70,23 @@ RenderStateTracker::RenderStateTracker()
//--------------------------------------------------------------------------------------------------
void RenderStateTracker::setupDefaultRenderStates()
{
m_defaultRenderStates[RenderState::BLENDING] = new Blending;
m_defaultRenderStates[RenderState::COLOR_MASK] = new ColorMask;
m_defaultRenderStates[RenderState::CULL_FACE] = new CullFace(false);
m_defaultRenderStates[RenderState::FRONT_FACE] = new FrontFace;
m_defaultRenderStates[RenderState::DEPTH] = new Depth;
m_defaultRenderStates[RenderState::POINT] = new Point;
m_defaultRenderStates[RenderState::POLYGON_MODE] = new PolygonMode;
m_defaultRenderStates[RenderState::POLYGON_OFFSET] = new PolygonOffset;
m_defaultRenderStates[RenderState::TEXTURE_BINDINGS] = new TextureBindings;
m_defaultRenderStates[RenderState::BLENDING] = new RenderStateBlending;
m_defaultRenderStates[RenderState::COLOR_MASK] = new RenderStateColorMask;
m_defaultRenderStates[RenderState::CULL_FACE] = new RenderStateCullFace(false);
m_defaultRenderStates[RenderState::DEPTH] = new RenderStateDepth;
m_defaultRenderStates[RenderState::FRONT_FACE] = new RenderStateFrontFace;
m_defaultRenderStates[RenderState::LINE] = new RenderStateLine;
m_defaultRenderStates[RenderState::POINT] = new RenderStatePoint;
m_defaultRenderStates[RenderState::POLYGON_MODE] = new RenderStatePolygonMode;
m_defaultRenderStates[RenderState::POLYGON_OFFSET] = new RenderStatePolygonOffset;
m_defaultRenderStates[RenderState::STENCIL] = new RenderStateStencil;
m_defaultRenderStates[RenderState::TEXTURE_BINDINGS] = new RenderStateTextureBindings;
#ifndef CVF_OPENGL_ES
m_defaultRenderStates[RenderState::LIGHTING_FF] = new Lighting_FF;
m_defaultRenderStates[RenderState::MATERIAL_FF] = new Material_FF;
m_defaultRenderStates[RenderState::NORMALIZE_FF] = new Normalize_FF(false);
m_defaultRenderStates[RenderState::TEXTURE_MAPPING_FF] = new TextureMapping_FF;
m_defaultRenderStates[RenderState::LIGHTING_FF] = new RenderStateLighting_FF;
m_defaultRenderStates[RenderState::MATERIAL_FF] = new RenderStateMaterial_FF;
m_defaultRenderStates[RenderState::NORMALIZE_FF] = new RenderStateNormalize_FF(false);
m_defaultRenderStates[RenderState::TEXTURE_MAPPING_FF] = new RenderStateTextureMapping_FF;
#endif
}

View File

@@ -31,7 +31,7 @@ namespace cvf {
//==================================================================================================
///
/// \class cvf::Lighting_FF
/// \class cvf::RenderStateLighting_FF
/// \ingroup Render
///
/// Encapsulate OpenGL glLightModel() and glEnable()/glDisable() with GL_LIGHTING
@@ -43,7 +43,7 @@ namespace cvf {
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Lighting_FF::Lighting_FF(bool enableLighting)
RenderStateLighting_FF::RenderStateLighting_FF(bool enableLighting)
: RenderState(LIGHTING_FF),
m_enableLighting(enableLighting),
m_twoSided(false),
@@ -58,7 +58,7 @@ Lighting_FF::Lighting_FF(bool enableLighting)
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml with GL_LIGHTING
//--------------------------------------------------------------------------------------------------
void Lighting_FF::enable(bool enableLighting)
void RenderStateLighting_FF::enable(bool enableLighting)
{
m_enableLighting = enableLighting;
}
@@ -67,7 +67,7 @@ void Lighting_FF::enable(bool enableLighting)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Lighting_FF::enableTwoSided(bool enableTwoSided)
void RenderStateLighting_FF::enableTwoSided(bool enableTwoSided)
{
m_twoSided = enableTwoSided;
}
@@ -76,7 +76,7 @@ void Lighting_FF::enableTwoSided(bool enableTwoSided)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Lighting_FF::enableLocalViewer(bool enableLocalViewer)
void RenderStateLighting_FF::enableLocalViewer(bool enableLocalViewer)
{
m_localViewer = enableLocalViewer;
}
@@ -85,7 +85,7 @@ void Lighting_FF::enableLocalViewer(bool enableLocalViewer)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Lighting_FF::setAmbientIntensity(const Color3f& ambientIntensity)
void RenderStateLighting_FF::setAmbientIntensity(const Color3f& ambientIntensity)
{
m_ambientIntensity.set(ambientIntensity, 1.0f);
}
@@ -94,7 +94,7 @@ void Lighting_FF::setAmbientIntensity(const Color3f& ambientIntensity)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Lighting_FF::isEnabled() const
bool RenderStateLighting_FF::isEnabled() const
{
return m_enableLighting;
}
@@ -103,7 +103,7 @@ bool Lighting_FF::isEnabled() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Lighting_FF::isTwoSidedEnabled() const
bool RenderStateLighting_FF::isTwoSidedEnabled() const
{
return m_twoSided;
}
@@ -112,7 +112,7 @@ bool Lighting_FF::isTwoSidedEnabled() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Lighting_FF::isLocalViewerEnabled() const
bool RenderStateLighting_FF::isLocalViewerEnabled() const
{
return m_localViewer;
}
@@ -121,7 +121,7 @@ bool Lighting_FF::isLocalViewerEnabled() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f Lighting_FF::ambientIntensity() const
Color3f RenderStateLighting_FF::ambientIntensity() const
{
return m_ambientIntensity.toColor3f();
}
@@ -130,7 +130,7 @@ Color3f Lighting_FF::ambientIntensity() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Lighting_FF::applyOpenGL(OpenGLContext* oglContext) const
void RenderStateLighting_FF::applyOpenGL(OpenGLContext* oglContext) const
{
if (m_enableLighting)
{
@@ -154,7 +154,7 @@ void Lighting_FF::applyOpenGL(OpenGLContext* oglContext) const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Lighting_FF::isFixedFunction() const
bool RenderStateLighting_FF::isFixedFunction() const
{
return true;
}
@@ -163,7 +163,7 @@ bool Lighting_FF::isFixedFunction() const
//==================================================================================================
///
/// \class cvf::Material_FF
/// \class cvf::RenderStateMaterial_FF
/// \ingroup Render
///
///
@@ -173,7 +173,7 @@ bool Lighting_FF::isFixedFunction() const
//--------------------------------------------------------------------------------------------------
/// Default constructor, initializes all values to OpenGL defaults
//--------------------------------------------------------------------------------------------------
Material_FF::Material_FF()
RenderStateMaterial_FF::RenderStateMaterial_FF()
: RenderState(MATERIAL_FF),
m_ambient(0.2f, 0.2f, 0.2f),
m_diffuse(0.8f, 0.8f, 0.8f),
@@ -189,7 +189,7 @@ Material_FF::Material_FF()
//--------------------------------------------------------------------------------------------------
/// Constructor taking ambient and diffuse color
//--------------------------------------------------------------------------------------------------
Material_FF::Material_FF(const Color3f& ambientAndDiffuseColor)
RenderStateMaterial_FF::RenderStateMaterial_FF(const Color3f& ambientAndDiffuseColor)
: RenderState(MATERIAL_FF),
m_ambient(ambientAndDiffuseColor),
m_diffuse(ambientAndDiffuseColor),
@@ -205,7 +205,7 @@ Material_FF::Material_FF(const Color3f& ambientAndDiffuseColor)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Material_FF::Material_FF(MaterialIdent materialIdent)
RenderStateMaterial_FF::RenderStateMaterial_FF(MaterialIdent materialIdent)
: RenderState(MATERIAL_FF),
m_specular(0, 0, 0),
m_emission(0, 0, 0),
@@ -263,7 +263,7 @@ Material_FF::Material_FF(MaterialIdent materialIdent)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::setAmbientAndDiffuse(const Color3f& color)
void RenderStateMaterial_FF::setAmbientAndDiffuse(const Color3f& color)
{
CVF_ASSERT(color.isValid());
@@ -274,7 +274,7 @@ void Material_FF::setAmbientAndDiffuse(const Color3f& color)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::setDiffuse(const Color3f& color)
void RenderStateMaterial_FF::setDiffuse(const Color3f& color)
{
CVF_ASSERT(color.isValid());
@@ -285,7 +285,7 @@ void Material_FF::setDiffuse(const Color3f& color)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::setSpecular(const Color3f& color)
void RenderStateMaterial_FF::setSpecular(const Color3f& color)
{
CVF_ASSERT(color.isValid());
@@ -296,7 +296,18 @@ void Material_FF::setSpecular(const Color3f& color)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::setAlpha(float alpha)
void RenderStateMaterial_FF::setEmission(const Color3f& color)
{
CVF_ASSERT(color.isValid());
m_emission = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateMaterial_FF::setAlpha(float alpha)
{
m_alpha = alpha;
}
@@ -307,7 +318,7 @@ void Material_FF::setAlpha(float alpha)
/// Only values in the range 0 128 are accepted. The initial specular exponent for
/// both front- and back-facing materials is 0
//--------------------------------------------------------------------------------------------------
void Material_FF::setShininess(float shininess)
void RenderStateMaterial_FF::setShininess(float shininess)
{
m_shininess = shininess;
}
@@ -316,7 +327,7 @@ void Material_FF::setShininess(float shininess)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f Material_FF::frontAmbient() const
Color3f RenderStateMaterial_FF::frontAmbient() const
{
return m_ambient;
}
@@ -325,7 +336,7 @@ Color3f Material_FF::frontAmbient() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f Material_FF::frontDiffuse() const
Color3f RenderStateMaterial_FF::frontDiffuse() const
{
return m_diffuse;
}
@@ -334,7 +345,7 @@ Color3f Material_FF::frontDiffuse() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f Material_FF::frontSpecular() const
Color3f RenderStateMaterial_FF::frontSpecular() const
{
return m_specular;
}
@@ -343,7 +354,7 @@ Color3f Material_FF::frontSpecular() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f Material_FF::frontEmission() const
Color3f RenderStateMaterial_FF::frontEmission() const
{
return m_emission;
}
@@ -352,7 +363,7 @@ Color3f Material_FF::frontEmission() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Material_FF::frontAlpha() const
float RenderStateMaterial_FF::frontAlpha() const
{
return m_alpha;
}
@@ -361,7 +372,7 @@ float Material_FF::frontAlpha() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Material_FF::frontShininess() const
float RenderStateMaterial_FF::frontShininess() const
{
return m_shininess;
}
@@ -370,7 +381,7 @@ float Material_FF::frontShininess() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::enableColorMaterial(bool enableColorMaterial)
void RenderStateMaterial_FF::enableColorMaterial(bool enableColorMaterial)
{
m_enableColorMaterial = enableColorMaterial;
}
@@ -379,7 +390,7 @@ void Material_FF::enableColorMaterial(bool enableColorMaterial)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Material_FF::isColorMaterialEnabled() const
bool RenderStateMaterial_FF::isColorMaterialEnabled() const
{
return m_enableColorMaterial;
}
@@ -388,7 +399,7 @@ bool Material_FF::isColorMaterialEnabled() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::applyOpenGL(OpenGLContext* oglContext) const
void RenderStateMaterial_FF::applyOpenGL(OpenGLContext* oglContext) const
{
Color4f ambient(m_ambient, m_alpha);
Color4f diffuse(m_diffuse, m_alpha);
@@ -427,7 +438,7 @@ void Material_FF::applyOpenGL(OpenGLContext* oglContext) const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Material_FF::isFixedFunction() const
bool RenderStateMaterial_FF::isFixedFunction() const
{
return true;
}
@@ -437,7 +448,7 @@ bool Material_FF::isFixedFunction() const
//==================================================================================================
///
/// \class cvf::Normalize_FF
/// \class cvf::RenderStateNormalize_FF
/// \ingroup Render
///
/// Controls normalization of normals in fixed function
@@ -447,7 +458,7 @@ bool Material_FF::isFixedFunction() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Normalize_FF::Normalize_FF(bool enableNormalization)
RenderStateNormalize_FF::RenderStateNormalize_FF(bool enableNormalization)
: RenderState(NORMALIZE_FF),
m_enable(enableNormalization)
{
@@ -457,7 +468,7 @@ Normalize_FF::Normalize_FF(bool enableNormalization)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Normalize_FF::enable(bool enableNormalization)
void RenderStateNormalize_FF::enable(bool enableNormalization)
{
m_enable = enableNormalization;
}
@@ -466,7 +477,7 @@ void Normalize_FF::enable(bool enableNormalization)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Normalize_FF::isEnabled() const
bool RenderStateNormalize_FF::isEnabled() const
{
return m_enable;
}
@@ -475,7 +486,7 @@ bool Normalize_FF::isEnabled() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Normalize_FF::applyOpenGL(OpenGLContext* oglContext) const
void RenderStateNormalize_FF::applyOpenGL(OpenGLContext* oglContext) const
{
if (m_enable)
{
@@ -493,7 +504,7 @@ void Normalize_FF::applyOpenGL(OpenGLContext* oglContext) const
//==================================================================================================
///
/// \class cvf::TextureMapping_FF
/// \class cvf::RenderStateTextureMapping_FF
/// \ingroup Render
///
/// Enable 2D texturing for texture unit 0 and fixed function
@@ -503,7 +514,7 @@ void Normalize_FF::applyOpenGL(OpenGLContext* oglContext) const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TextureMapping_FF::TextureMapping_FF(Texture2D_FF* texture)
RenderStateTextureMapping_FF::RenderStateTextureMapping_FF(Texture2D_FF* texture)
: RenderState(TEXTURE_MAPPING_FF),
m_texture(texture),
m_textureFunction(MODULATE),
@@ -515,7 +526,7 @@ TextureMapping_FF::TextureMapping_FF(Texture2D_FF* texture)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TextureMapping_FF::~TextureMapping_FF()
RenderStateTextureMapping_FF::~RenderStateTextureMapping_FF()
{
}
@@ -523,7 +534,7 @@ TextureMapping_FF::~TextureMapping_FF()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureMapping_FF::setTexture(Texture2D_FF* texture)
void RenderStateTextureMapping_FF::setTexture(Texture2D_FF* texture)
{
m_texture = texture;
}
@@ -532,7 +543,7 @@ void TextureMapping_FF::setTexture(Texture2D_FF* texture)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Texture2D_FF* TextureMapping_FF::texture()
Texture2D_FF* RenderStateTextureMapping_FF::texture()
{
return m_texture.p();
}
@@ -541,7 +552,7 @@ Texture2D_FF* TextureMapping_FF::texture()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureMapping_FF::setTextureFunction(TextureFunction texFunc)
void RenderStateTextureMapping_FF::setTextureFunction(TextureFunction texFunc)
{
m_textureFunction = texFunc;
}
@@ -550,7 +561,7 @@ void TextureMapping_FF::setTextureFunction(TextureFunction texFunc)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TextureMapping_FF::TextureFunction TextureMapping_FF::textureFunction() const
RenderStateTextureMapping_FF::TextureFunction RenderStateTextureMapping_FF::textureFunction() const
{
return m_textureFunction;
}
@@ -559,7 +570,7 @@ TextureMapping_FF::TextureFunction TextureMapping_FF::textureFunction() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureMapping_FF::setEnvironmentMapping(bool environmentMapping)
void RenderStateTextureMapping_FF::setEnvironmentMapping(bool environmentMapping)
{
m_environmentMapping = environmentMapping;
}
@@ -568,7 +579,7 @@ void TextureMapping_FF::setEnvironmentMapping(bool environmentMapping)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool TextureMapping_FF::environmentMapping() const
bool RenderStateTextureMapping_FF::environmentMapping() const
{
return m_environmentMapping;
}
@@ -577,7 +588,7 @@ bool TextureMapping_FF::environmentMapping() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureMapping_FF::setupTexture(OpenGLContext* oglContext)
void RenderStateTextureMapping_FF::setupTexture(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
@@ -601,7 +612,7 @@ void TextureMapping_FF::setupTexture(OpenGLContext* oglContext)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureMapping_FF::applyOpenGL(OpenGLContext* oglContext) const
void RenderStateTextureMapping_FF::applyOpenGL(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
@@ -656,7 +667,7 @@ void TextureMapping_FF::applyOpenGL(OpenGLContext* oglContext) const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool TextureMapping_FF::isFixedFunction() const
bool RenderStateTextureMapping_FF::isFixedFunction() const
{
return true;
}

View File

@@ -32,10 +32,10 @@ class Texture2D_FF;
// Encapsulates OpenGL's glLightModel() and glEnable()/glDisable() with GL_LIGHTING
//
//==================================================================================================
class Lighting_FF : public RenderState
class RenderStateLighting_FF : public RenderState
{
public:
Lighting_FF(bool enableLighting = true);
RenderStateLighting_FF(bool enableLighting = true);
void enable(bool enableLighting);
bool isEnabled() const;
@@ -65,7 +65,7 @@ private:
// Encapsulates OpenGL glMaterial() state
//
//==================================================================================================
class Material_FF : public RenderState
class RenderStateMaterial_FF : public RenderState
{
public:
enum MaterialIdent
@@ -114,13 +114,14 @@ public:
};
public:
Material_FF();
explicit Material_FF(const Color3f& ambientAndDiffuseColor);
explicit Material_FF(MaterialIdent materialIdent);
RenderStateMaterial_FF();
explicit RenderStateMaterial_FF(const Color3f& ambientAndDiffuseColor);
explicit RenderStateMaterial_FF(MaterialIdent materialIdent);
void setAmbientAndDiffuse(const Color3f& color);
void setDiffuse(const Color3f& color);
void setSpecular(const Color3f& color);
void setEmission(const Color3f& color);
void setAlpha(float alpha);
void setShininess(float shininess);
@@ -153,10 +154,10 @@ private:
// Controls normalization of normals in fixed function
//
//==================================================================================================
class Normalize_FF : public RenderState
class RenderStateNormalize_FF : public RenderState
{
public:
Normalize_FF(bool enableNormalization = true);
RenderStateNormalize_FF(bool enableNormalization = true);
void enable(bool enableNormalization);
bool isEnabled() const;
@@ -173,7 +174,7 @@ private:
//
//
//==================================================================================================
class TextureMapping_FF : public RenderState
class RenderStateTextureMapping_FF : public RenderState
{
public:
enum TextureFunction
@@ -183,8 +184,8 @@ public:
};
public:
TextureMapping_FF(Texture2D_FF* texture = NULL);
~TextureMapping_FF();
RenderStateTextureMapping_FF(Texture2D_FF* texture = NULL);
~RenderStateTextureMapping_FF();
void setTexture(Texture2D_FF* texture);
Texture2D_FF* texture();

View File

@@ -78,7 +78,7 @@ void Sampler::setWrapModeT(WrapMode wrapMode)
//--------------------------------------------------------------------------------------------------
///
/// Set the texture minifying filter function
//--------------------------------------------------------------------------------------------------
void Sampler::setMinFilter(Filter minFilter)
{
@@ -87,7 +87,9 @@ void Sampler::setMinFilter(Filter minFilter)
//--------------------------------------------------------------------------------------------------
/// Set the magnification filter function
///
/// \param magFilter Filter function to use. Legal values are NEAREST and LINEAR.
//--------------------------------------------------------------------------------------------------
void Sampler::setMagFilter(Filter magFilter)
{

View File

@@ -44,7 +44,7 @@ class Sampler : public Object
public:
enum WrapMode
{
REPEAT, // OpenGL default
REPEAT, // OpenGL default
CLAMP_TO_EDGE,
CLAMP_TO_BORDER,
MIRRORED_REPEAT
@@ -52,12 +52,12 @@ public:
enum Filter
{
NEAREST,
LINEAR, // Default mag filter in OpenGL
NEAREST_MIPMAP_NEAREST,
LINEAR_MIPMAP_NEAREST,
NEAREST_MIPMAP_LINEAR, // Default min filter in OpenGL
LINEAR_MIPMAP_LINEAR
NEAREST, ///< Nearest neighbor filtering on the base mip level
LINEAR, ///< Linear filtering on the base mip level. (Default magnification filter in OpenGL)
NEAREST_MIPMAP_NEAREST, ///< Selects nearest mip level and performs nearest neighbor filtering
LINEAR_MIPMAP_NEAREST, ///< Selects nearest mip level and performs linear filtering
NEAREST_MIPMAP_LINEAR, ///< Perform linear interpolation between mip levels and perform nearest neighbor filtering. (Default minifying filter in OpenGL)
LINEAR_MIPMAP_LINEAR ///< Perform linear interpolation between mip levels and perform linear filtering (trilinear mipmapping)
};
public:
@@ -75,10 +75,10 @@ public:
Filter magFilter() const;
private:
WrapMode m_wrapModeS;
WrapMode m_wrapModeT;
Filter m_minFilter;
Filter m_magFilter;
WrapMode m_wrapModeS; ///< Wrap mode for texture coordinate S. Default is REPEAT
WrapMode m_wrapModeT; ///< Wrap mode for texture coordinate T. Default is REPEAT
Filter m_minFilter; ///< Minifying function. Default is NEAREST_MIPMAP_LINEAR
Filter m_magFilter; ///< Magnification function. Default is LINEAR
};
} // namespace cvf

View File

@@ -33,6 +33,9 @@ namespace cvf {
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -139,8 +142,8 @@ ref<Color3ubArray> ScalarMapper::colorTableArray(ColorTable colorTable)
case NORMAL:
{
// Choses the primary colors only variant
colors = normalColorTableArray(5);
// Which number of levels should we choose here?
colors = normalColorTableArray(10);
break;
}
}

View File

@@ -19,8 +19,10 @@
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfArray.h"
#include <vector>
namespace cvf {
@@ -30,6 +32,8 @@ class TextureImage;
//==================================================================================================
//
// Abstract base class for mapping scalar values to texture coordinates/colors
// It also provides an interface that OverlayScalarMapperLegend's use to draw consistent colors
// and labels/ticks
//
//==================================================================================================
class ScalarMapper : public Object
@@ -51,15 +55,34 @@ public:
};
public:
virtual Vec2f mapToTextureCoord(double scalarValue) const = 0;
virtual Color3ub mapToColor(double scalarValue) const = 0;
//////
// Interface for mapping of scalar values to color and texture
virtual bool updateTexture(TextureImage* image) const = 0;
/// Calculate texture coords into an image produced by updateTexture, from the scalarValue
virtual Vec2f mapToTextureCoord(double scalarValue) const = 0;
/// Update the supplied TextureImage to be addressable by the texture coords delivered by mapToTextureCoord
virtual bool updateTexture(TextureImage* image) const = 0;
/// Calculate a color from the scalar value
virtual Color3ub mapToColor(double scalarValue) const = 0;
//////
// Interface used by OverlayScalarMapperLegend:
/// Return a the set of domain values representing sensible major tickmarks
virtual void majorTickValues(std::vector<double>* domainValues) const = 0;
/// Return the normalized (0.0, 1.0) representation of the domainValue
virtual double normalizedValue(double domainValue) const = 0;
/// Return the domain value from a normalized val
virtual double domainValue(double normalizedValue) const = 0;
protected:
static ref<Color3ubArray> colorTableArray(ColorTable colorTable);
static ref<Color3ubArray> normalColorTableArray(uint colorCount);
static ref<Color3ubArray> interpolateColorArray(const Color3ubArray& colorArray, uint targetColorCount);
// Static utility methods that can be used when creating real ScalarMapper's
static ref<Color3ubArray> colorTableArray(ColorTable colorTable);
static ref<Color3ubArray> normalColorTableArray(uint colorCount);
static ref<Color3ubArray> interpolateColorArray(const Color3ubArray& colorArray, uint targetColorCount);
};

View File

@@ -35,7 +35,7 @@ namespace cvf {
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperContinuousLinear::normalizedLevelPosition(double domainValue) const
double ScalarMapperContinuousLinear::normalizedValue(double domainValue) const
{
double range = m_rangeMax - m_rangeMin;
if (range != 0) return cvf::Math::clamp((domainValue - m_rangeMin)/range, 0.0, 1.0);

View File

@@ -19,11 +19,9 @@
#pragma once
#include "cvfScalarMapperContinuousLog.h"
#include "cvfScalarMapperRangeBased.h"
namespace cvf
{
namespace cvf {
//==================================================================================================
//
@@ -31,12 +29,14 @@ namespace cvf
//
//==================================================================================================
class ScalarMapperContinuousLinear : public ScalarMapperContinuousLog
class ScalarMapperContinuousLinear : public ScalarMapperRangeBased
{
public:
ScalarMapperContinuousLinear() {m_decadeLevelCount = 2; }
protected:
virtual double normalizedLevelPosition( double domainValue ) const;
// Implementing the Scalarmapper interface
virtual double normalizedValue( double domainValue ) const;
virtual double domainValue( double normalizedPosition ) const;
};

View File

@@ -34,173 +34,14 @@ namespace cvf {
/// Configured by specifying a number of level colors and a min/max range.
//==================================================================================================
ScalarMapperContinuousLog::ScalarMapperContinuousLog()
: m_rangeMin(1),
m_rangeMax(1),
m_decadeLevelCount(1),
m_majorLevelCount(8),
m_textureSize(2048) // Large enough, I guess and a power of two
{
m_colors.resize(m_textureSize);
m_colors.setAll(Color3ub::WHITE);
setColors(ScalarMapper::NORMAL);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperContinuousLog::setRange(double min, double max)
{
m_rangeMin = min;
m_rangeMax = max;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperContinuousLog::setColors(const Color3ubArray& colorArray)
{
m_colors = *interpolateColorArray(colorArray, m_textureSize);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperContinuousLog::setColors(ColorTable colorTable)
{
ref<Color3ubArray> baseColors = colorTableArray(colorTable);
setColors(*baseColors);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Vec2f ScalarMapperContinuousLog::mapToTextureCoord(double scalarValue) const
{
return Vec2f(static_cast<float>(normalizedLevelPosition(scalarValue)), 0.5f);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3ub ScalarMapperContinuousLog::mapToColor(double scalarValue) const
{
size_t colorIdx = static_cast<size_t>(normalizedLevelPosition(scalarValue) * (m_textureSize - 1));
CVF_TIGHT_ASSERT(colorIdx < m_colors.size());
return m_colors[colorIdx];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ScalarMapperContinuousLog::updateTexture(TextureImage* image) const
{
CVF_ASSERT(image);
image->allocate(m_textureSize, 1);
// For now fill with white so we can see any errors more easily
image->fill(Color4ub(Color3::WHITE));
uint ic;
for (ic = 0; ic < m_textureSize; ic++)
{
const Color4ub clr(m_colors[ic], 255);
image->setPixel(ic, 0, clr);
}
return true;
}
// Then calculate a stepsize that is humanly understandable
// basically rounded to whole or half of the decade in question
static double adjust(double domainValue, double decadeValue, unsigned int decadeParts = 2)
{
if (decadeValue == 0) return domainValue; // Conceptually correct
//double sign = domainValue >= 0 ? 1.0 : -1.0;
// Calculate the decade
decadeValue = cvf::Math::abs(decadeValue);
double logDecValue = log10(decadeValue );
logDecValue = cvf::Math::floor(logDecValue);
double decade = pow(10.0, logDecValue);
double firstDecadeDomVal = decadeParts*domainValue/decade;
double roundedFirstDecadeDomVal;
if ( cvf::Math::abs(firstDecadeDomVal - cvf::Math::floor(firstDecadeDomVal)) < cvf::Math::abs(ceil(firstDecadeDomVal) - firstDecadeDomVal))
{
roundedFirstDecadeDomVal = cvf::Math::floor(firstDecadeDomVal);
}
else
{
roundedFirstDecadeDomVal = ceil(firstDecadeDomVal);
}
double newStep = decade*(roundedFirstDecadeDomVal)/decadeParts;
return newStep;
}
//--------------------------------------------------------------------------------------------------
/// Calculates a set of humanly readable levels. Works very well for linear, and ok for logarithmic.
/// The logarithmic needs a bit more tweaking, so should override this method for linear but not yet done.
//--------------------------------------------------------------------------------------------------
void ScalarMapperContinuousLog::majorLevels( std::vector<double>* domainValues) const
{
CVF_ASSERT(domainValues != NULL);
domainValues->push_back(m_rangeMin);
if (m_majorLevelCount > 1)
{
double stepSizeNorm = 1.0/m_majorLevelCount;
size_t i;
if (m_adjustLevels) // adjust levels
{
double prevDomValue = domainValue(0);
for (i = 1; i < m_majorLevelCount + 5; ++i)
{
double prevNormPos = normalizedLevelPosition(prevDomValue);
double newNormPos = prevNormPos + stepSizeNorm;
double domValue = domainValue(newNormPos);
double domStep = domValue - prevDomValue;
double newLevel;
newLevel = prevDomValue + adjust(domStep, domStep, m_decadeLevelCount);
// Must handle first level specially to get a good absolute staring point
// For log domain this must be done all the time, and it does not hamper linear, so.. do it always
newLevel = adjust(newLevel, domStep, m_decadeLevelCount);
if (newLevel > m_rangeMax - domStep*0.4) break;
domainValues->push_back(newLevel);
prevDomValue = newLevel;
}
}
else
{
for (i = 1; i < m_majorLevelCount; ++i)
{
domainValues->push_back(domainValue(stepSizeNorm*i));
}
}
}
domainValues->push_back(m_rangeMax);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperContinuousLog::normalizedLevelPosition(double scalarValue) const
double ScalarMapperContinuousLog::normalizedValue(double scalarValue) const
{
double logRangeMax = log10(m_rangeMax);
double logRangeMin = log10(m_rangeMin);
@@ -234,13 +75,4 @@ double ScalarMapperContinuousLog::domainValue(double normalizedPosition) const
return pow(10, logValue);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperContinuousLog::setMajorLevelCount(size_t levelCount, bool adjustLevels)
{
m_majorLevelCount = levelCount;
m_adjustLevels = adjustLevels;
}
} // namespace cvf

View File

@@ -18,9 +18,8 @@
//##################################################################################################
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfLegendScalarMapper.h"
#include "cvfScalarMapperRangeBased.h"
namespace cvf {
@@ -29,40 +28,16 @@ namespace cvf {
// Maps scalar values to texture coordinates/colors
//
//==================================================================================================
class ScalarMapperContinuousLog : public LegendScalarMapper
class ScalarMapperContinuousLog : public ScalarMapperRangeBased
{
public:
ScalarMapperContinuousLog();
void setRange(double min, double max);
void setMajorLevelCount(size_t levelCount, bool adjustLevels = true);
// Implementing the Scalarmapper interface
void setColors(const Color3ubArray& colorArray);
void setColors(ColorTable colorTable);
// Scalarmapper interface
virtual Vec2f mapToTextureCoord(double scalarValue) const;
virtual Color3ub mapToColor(double scalarValue) const;
virtual bool updateTexture(TextureImage* image) const;
// LegendScalarmapper interface
virtual void majorLevels(std::vector<double>* domainValues ) const;
virtual double normalizedLevelPosition( double domainValue ) const;
virtual double normalizedValue( double domainValue ) const;
virtual double domainValue( double normalizedPosition ) const;
protected:
double m_rangeMin;
double m_rangeMax;
unsigned int m_decadeLevelCount;
private:
size_t m_majorLevelCount;
bool m_adjustLevels;
Color3ubArray m_colors;
uint m_textureSize; // The size of texture that updateTexture() will produce.
};
}

View File

@@ -32,57 +32,26 @@ namespace cvf {
//==================================================================================================
ScalarMapperDiscreteLinear::ScalarMapperDiscreteLinear()
: m_rangeMin(cvf::UNDEFINED_DOUBLE),
m_rangeMax(cvf::UNDEFINED_DOUBLE),
m_decadeLevelCount(1),
m_colorCount(8),
m_textureSize(2048) // Large enough, I guess and a power of two
{
m_colors.resize(m_textureSize);
m_colors.setAll(Color3ub::WHITE);
setColors(ScalarMapper::NORMAL);
}
//--------------------------------------------------------------------------------------------------
/// Sets the max and min level of the legend. If the levels previously has been set with setLevelsFromValues()
/// only the values between the new max min range becomes visible.
//--------------------------------------------------------------------------------------------------
void ScalarMapperDiscreteLinear::setRange(double min, double max)
{
m_rangeMin = min;
m_rangeMax = max;
updateSortedLevels();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperDiscreteLinear::setColors(const Color3ubArray& colorArray)
{
m_colors = *interpolateColorArray(colorArray, m_textureSize);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperDiscreteLinear::setColors(ColorTable colorTable)
{
ref<Color3ubArray> baseColors = colorTableArray(colorTable);
setColors(*baseColors);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Vec2f ScalarMapperDiscreteLinear::mapToTextureCoord(double scalarValue) const
{
double discVal = discretize(scalarValue);
return Vec2f(static_cast<float>(normalizedLevelPosition(discVal)), 0.5f);
return ScalarMapperRangeBased::mapToTextureCoord(discVal);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3ub ScalarMapperDiscreteLinear::mapToColor(double scalarValue) const
{
double discVal = discretize(scalarValue);
return ScalarMapperRangeBased::mapToColor(discVal);
}
//--------------------------------------------------------------------------------------------------
@@ -104,153 +73,7 @@ double ScalarMapperDiscreteLinear::discretize(double scalarValue) const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperDiscreteLinear::updateSortedLevels()
{
std::vector<double> levels;
majorLevels(&levels);
std::set<double>::iterator it;
m_sortedLevels.clear();
m_sortedLevels.insert(levels.begin(), levels.end());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3ub ScalarMapperDiscreteLinear::mapToColor(double scalarValue) const
{
double discVal = discretize(scalarValue);
size_t colorIdx = static_cast<size_t>(normalizedLevelPosition(discVal) * (m_textureSize - 1));
CVF_TIGHT_ASSERT(colorIdx < m_colors.size());
return m_colors[colorIdx];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ScalarMapperDiscreteLinear::updateTexture(TextureImage* image) const
{
CVF_ASSERT(image);
image->allocate(m_textureSize, 1);
// For now fill with white so we can see any errors more easily
image->fill(Color4ub(Color3::WHITE));
uint ic;
for (ic = 0; ic < m_textureSize; ic++)
{
const Color4ub clr(m_colors[ic], 255);
image->setPixel(ic, 0, clr);
}
return true;
}
// Then calculate a stepsize that is humanly understandable
// basically rounded to whole or half of the decade in question
static double adjust(double domainValue, double decadeValue, unsigned int decadeParts = 2)
{
if (decadeValue == 0) return domainValue; // Conceptually correct
//double sign = domainValue >= 0 ? 1.0 : -1.0;
// Calculate the decade
decadeValue = cvf::Math::abs(decadeValue);
double logDecValue = log10(decadeValue );
logDecValue = cvf::Math::floor(logDecValue);
double decade = pow(10.0, logDecValue);
double firstDecadeDomVal = decadeParts*domainValue/decade;
double roundedFirstDecadeDomVal;
if ( cvf::Math::abs(firstDecadeDomVal - cvf::Math::floor(firstDecadeDomVal)) < cvf::Math::abs(ceil(firstDecadeDomVal) - firstDecadeDomVal))
{
roundedFirstDecadeDomVal = cvf::Math::floor(firstDecadeDomVal);
}
else
{
roundedFirstDecadeDomVal = ceil(firstDecadeDomVal);
}
double newStep = decade*(roundedFirstDecadeDomVal)/decadeParts;
return newStep;
}
//--------------------------------------------------------------------------------------------------
/// Calculates a set of humanly readable levels. Works very well for linear, and ok for logarithmic.
/// The logarithmic needs a bit more tweaking, so should override this method for linear but not yet done.
//--------------------------------------------------------------------------------------------------
void ScalarMapperDiscreteLinear::majorLevels( std::vector<double>* domainValues) const
{
CVF_ASSERT(domainValues != NULL);
CVF_ASSERT(m_rangeMin != cvf::UNDEFINED_DOUBLE && m_rangeMax != cvf::UNDEFINED_DOUBLE);
if (m_userDefinedLevelValues.empty())
{
domainValues->push_back(m_rangeMin);
if (m_colorCount > 1)
{
double stepSizeNorm = 1.0/m_colorCount;
size_t i;
if (m_adjustLevels) // adjust levels
{
double prevDomValue = domainValue(0);
for (i = 1; i < m_colorCount + 5; ++i)
{
double prevNormPos = normalizedLevelPosition(prevDomValue);
double newNormPos = prevNormPos + stepSizeNorm;
double domValue = domainValue(newNormPos);
double domStep = domValue - prevDomValue;
double newLevel;
newLevel = prevDomValue + adjust(domStep, domStep, m_decadeLevelCount);
// Must handle first level specially to get a good absolute staring point
// For log domain this must be done all the time, and it does not hamper linear, so.. do it always
newLevel = adjust(newLevel, domStep, m_decadeLevelCount);
if (newLevel > m_rangeMax - domStep*0.4) break;
domainValues->push_back(newLevel);
prevDomValue = newLevel;
}
}
else
{
for (i = 1; i < m_colorCount; ++i)
{
domainValues->push_back(domainValue(stepSizeNorm*i));
}
}
}
domainValues->push_back(m_rangeMax);
}
else
{
// Use the user defined levels between max and min.
// (max and min values are set from the user defined levels if not set explicitly)
domainValues->push_back(m_rangeMin);
std::set<double>::iterator it;
for (it = m_userDefinedLevelValues.begin(); it != m_userDefinedLevelValues.end(); ++it)
{
if (*it <= m_rangeMin ) continue;
if (*it >= m_rangeMax ) continue;
domainValues->push_back(*it);
}
domainValues->push_back(m_rangeMax);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperDiscreteLinear::normalizedLevelPosition(double domainScalarValue) const
double ScalarMapperDiscreteLinear::normalizedValue(double domainScalarValue) const
{
double range = m_rangeMax - m_rangeMin;
if (range != 0) return cvf::Math::clamp((domainScalarValue - m_rangeMin)/range, 0.0, 1.0);
@@ -268,33 +91,4 @@ double ScalarMapperDiscreteLinear::domainValue(double normalizedPosition) const
}
//--------------------------------------------------------------------------------------------------
/// Sets the number of levels to 1 + colorCount making the scalar mapper have colorCount
/// distinct visible colors
//--------------------------------------------------------------------------------------------------
void ScalarMapperDiscreteLinear::setLevelsFromColorCount(size_t colorCount, bool adjustLevels)
{
m_userDefinedLevelValues.clear();
m_colorCount = colorCount;
m_adjustLevels = adjustLevels;
updateSortedLevels();
}
//--------------------------------------------------------------------------------------------------
/// This method sets all the levels to the user defined domain values,
/// overriding any previous max and min range settings.
//--------------------------------------------------------------------------------------------------
void ScalarMapperDiscreteLinear::setLevelsFromValues(const std::set<double>& levelValues)
{
CVF_ASSERT(!m_userDefinedLevelValues.empty());
m_userDefinedLevelValues = levelValues;
m_rangeMax = (*levelValues.rbegin());
m_rangeMin = (*levelValues.begin());
updateSortedLevels();
}
} // namespace cvf

View File

@@ -19,7 +19,7 @@
#pragma once
#include "cvfLegendScalarMapper.h"
#include "cvfScalarMapperRangeBased.h"
namespace cvf {
@@ -28,48 +28,22 @@ namespace cvf {
// Maps scalar values to texture coordinates/colors
//
//==================================================================================================
class ScalarMapperDiscreteLinear : public LegendScalarMapper
class ScalarMapperDiscreteLinear : public ScalarMapperRangeBased
{
public:
ScalarMapperDiscreteLinear();
void setRange(double min, double max);
void setLevelsFromColorCount(size_t colorCount, bool adjustLevels = true);
void setLevelsFromValues(const std::set<double>& levelValues);
// Scalarmapper interface implementation
void setColors(const Color3ubArray& colorArray);
void setColors(ColorTable colorTable);
// Scalarmapper interface
virtual Vec2f mapToTextureCoord(double scalarValue) const;
virtual Color3ub mapToColor(double scalarValue) const;
virtual bool updateTexture(TextureImage* image) const;
// LegendScalarmapper interface
virtual void majorLevels(std::vector<double>* domainValues ) const;
virtual double normalizedLevelPosition( double domainValue ) const;
virtual double normalizedValue( double domainValue ) const;
virtual double domainValue( double normalizedPosition ) const;
protected:
double m_rangeMin;
double m_rangeMax;
unsigned int m_decadeLevelCount;
private:
void updateSortedLevels();
double discretize(double scalarValue) const;
private:
size_t m_colorCount; //< Number of discrete colors between min and max
bool m_adjustLevels;
std::set<double> m_userDefinedLevelValues;
std::set<double> m_sortedLevels;
Color3ubArray m_colors;
uint m_textureSize; // The size of texture that updateTexture() is will produce.
};
}

View File

@@ -35,7 +35,7 @@ namespace cvf {
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperDiscreteLog::normalizedLevelPosition(double domainScalarValue) const
double ScalarMapperDiscreteLog::normalizedValue(double domainScalarValue) const
{
double logRangeMax = log10(m_rangeMax);
double logRangeMin = log10(m_rangeMin);

View File

@@ -33,8 +33,10 @@ class ScalarMapperDiscreteLog : public ScalarMapperDiscreteLinear
{
public:
ScalarMapperDiscreteLog() {m_decadeLevelCount = 2; }
protected:
virtual double normalizedLevelPosition( double domainValue ) const;
// Implementing the Scalarmapper interface
virtual double normalizedValue( double domainValue ) const;
virtual double domainValue( double normalizedPosition ) const;
};
}

View File

@@ -0,0 +1,260 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfScalarMapperRangeBased.h"
#include "cvfMath.h"
#include "cvfTextureImage.h"
#include <cmath>
namespace cvf {
//==================================================================================================
///
/// \class cvf::ScalarMapperRangeBased
/// \ingroup Render
///
/// This is a base class for ScalarMapper's using range and levels, and does most of the job
/// apart from the mapping itself
//==================================================================================================
ScalarMapperRangeBased::ScalarMapperRangeBased()
: m_rangeMin(cvf::UNDEFINED_DOUBLE),
m_rangeMax(cvf::UNDEFINED_DOUBLE),
m_decadeLevelCount(1),
m_levelCount(8),
m_textureSize(2048) // Large enough, I guess and a power of two
{
m_colors.resize(m_textureSize);
m_colors.setAll(Color3ub::WHITE);
setColors(ScalarMapper::NORMAL);
}
//--------------------------------------------------------------------------------------------------
/// Sets the max and min level of the legend. If the levels previously has been set with setLevelsFromValues()
/// only the values between the new max min range becomes visible.
//--------------------------------------------------------------------------------------------------
void ScalarMapperRangeBased::setRange(double min, double max)
{
m_rangeMin = min;
m_rangeMax = max;
updateSortedLevels();
}
//--------------------------------------------------------------------------------------------------
/// Sets the colors that will be used in the legend. Will be interpolated when needed.
//--------------------------------------------------------------------------------------------------
void ScalarMapperRangeBased::setColors(const Color3ubArray& colorArray)
{
m_colors = *interpolateColorArray(colorArray, m_textureSize);
}
//--------------------------------------------------------------------------------------------------
/// Sets the colors from a predefined color set that will be used in the legend.
/// Will be interpolated when needed.
//--------------------------------------------------------------------------------------------------
void ScalarMapperRangeBased::setColors(ColorTable colorTable)
{
ref<Color3ubArray> baseColors = colorTableArray(colorTable);
setColors(*baseColors);
}
//--------------------------------------------------------------------------------------------------
/// Sets the number of ranges, creating (levelCount + 1) tickmarks (including max and min)
//--------------------------------------------------------------------------------------------------
void ScalarMapperRangeBased::setLevelCount(size_t levelCount, bool adjustLevels)
{
m_userDefinedLevelValues.clear();
m_levelCount = levelCount;
m_adjustLevels = adjustLevels;
updateSortedLevels();
}
//--------------------------------------------------------------------------------------------------
/// This method sets all the levels to the user defined domain values,
/// overriding any previous max and min range settings.
//--------------------------------------------------------------------------------------------------
void ScalarMapperRangeBased::setLevelsFromValues(const std::set<double>& levelValues)
{
CVF_ASSERT(!m_userDefinedLevelValues.empty());
m_userDefinedLevelValues = levelValues;
m_rangeMax = (*levelValues.rbegin());
m_rangeMin = (*levelValues.begin());
updateSortedLevels();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Vec2f ScalarMapperRangeBased::mapToTextureCoord(double scalarValue) const
{
return Vec2f(static_cast<float>(normalizedValue(scalarValue)), 0.5f);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3ub ScalarMapperRangeBased::mapToColor(double scalarValue) const
{
size_t colorIdx = static_cast<size_t>(normalizedValue(scalarValue) * (m_textureSize - 1));
CVF_TIGHT_ASSERT(colorIdx < m_colors.size());
return m_colors[colorIdx];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperRangeBased::updateSortedLevels()
{
std::vector<double> levels;
majorTickValues(&levels);
std::set<double>::iterator it;
m_sortedLevels.clear();
m_sortedLevels.insert(levels.begin(), levels.end());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ScalarMapperRangeBased::updateTexture(TextureImage* image) const
{
CVF_ASSERT(image);
image->allocate(m_textureSize, 1);
// For now fill with white so we can see any errors more easily
image->fill(Color4ub(Color3::WHITE));
uint ic;
for (ic = 0; ic < m_textureSize; ic++)
{
const Color4ub clr(m_colors[ic], 255);
image->setPixel(ic, 0, clr);
}
return true;
}
// Then calculate a stepsize that is humanly understandable
// basically rounded to whole or half of the decade in question
static double adjust(double domainValue, double decadeValue, unsigned int decadeParts = 2)
{
if (decadeValue == 0) return domainValue; // Conceptually correct
//double sign = domainValue >= 0 ? 1.0 : -1.0;
// Calculate the decade
decadeValue = cvf::Math::abs(decadeValue);
double logDecValue = log10(decadeValue );
logDecValue = cvf::Math::floor(logDecValue);
double decade = pow(10.0, logDecValue);
double firstDecadeDomVal = decadeParts*domainValue/decade;
double roundedFirstDecadeDomVal;
if ( cvf::Math::abs(firstDecadeDomVal - cvf::Math::floor(firstDecadeDomVal)) < cvf::Math::abs(ceil(firstDecadeDomVal) - firstDecadeDomVal))
{
roundedFirstDecadeDomVal = cvf::Math::floor(firstDecadeDomVal);
}
else
{
roundedFirstDecadeDomVal = ceil(firstDecadeDomVal);
}
double newStep = decade*(roundedFirstDecadeDomVal)/decadeParts;
return newStep;
}
//--------------------------------------------------------------------------------------------------
/// Calculates a set of humanly readable levels. Works very well for linear, and ok for logarithmic.
/// The logarithmic needs a bit more tweaking, so should override this method for linear but not yet done.
//--------------------------------------------------------------------------------------------------
void ScalarMapperRangeBased::majorTickValues( std::vector<double>* domainValues) const
{
CVF_ASSERT(domainValues != NULL);
CVF_ASSERT(m_rangeMin != cvf::UNDEFINED_DOUBLE && m_rangeMax != cvf::UNDEFINED_DOUBLE);
if (m_userDefinedLevelValues.empty())
{
domainValues->push_back(m_rangeMin);
if (m_levelCount > 1)
{
double stepSizeNorm = 1.0/m_levelCount;
size_t i;
if (m_adjustLevels) // adjust levels
{
double prevDomValue = domainValue(0);
for (i = 1; i < m_levelCount + 5; ++i)
{
double prevNormPos = normalizedValue(prevDomValue);
double newNormPos = prevNormPos + stepSizeNorm;
double domValue = domainValue(newNormPos);
double domStep = domValue - prevDomValue;
double newLevel;
newLevel = prevDomValue + adjust(domStep, domStep, m_decadeLevelCount);
// Must handle first level specially to get a good absolute staring point
// For log domain this must be done all the time, and it does not hamper linear, so.. do it always
newLevel = adjust(newLevel, domStep, m_decadeLevelCount);
if (newLevel > m_rangeMax - domStep*0.4) break;
domainValues->push_back(newLevel);
prevDomValue = newLevel;
}
}
else
{
for (i = 1; i < m_levelCount; ++i)
{
domainValues->push_back(domainValue(stepSizeNorm*i));
}
}
}
domainValues->push_back(m_rangeMax);
}
else
{
// Use the user defined levels between max and min.
// (max and min values are set from the user defined levels if not set explicitly)
domainValues->push_back(m_rangeMin);
std::set<double>::iterator it;
for (it = m_userDefinedLevelValues.begin(); it != m_userDefinedLevelValues.end(); ++it)
{
if (*it <= m_rangeMin ) continue;
if (*it >= m_rangeMax ) continue;
domainValues->push_back(*it);
}
domainValues->push_back(m_rangeMax);
}
}
} // namespace cvf

View File

@@ -0,0 +1,68 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfScalarMapper.h"
namespace cvf {
//==================================================================================================
//
// A base class that implements the common things between ordinary range based legends.
//
//==================================================================================================
class ScalarMapperRangeBased : public ScalarMapper
{
public:
ScalarMapperRangeBased();
// Public interface for setting up the mapping
void setRange(double min, double max);
void setLevelCount(size_t colorCount, bool adjustLevels);
void setLevelsFromValues(const std::set<double>& levelValues);
void setColors(const Color3ubArray& colorArray);
void setColors(ColorTable colorTable);
// Implementing some of the Scalarmapper interface
virtual Vec2f mapToTextureCoord(double scalarValue) const;
virtual Color3ub mapToColor(double scalarValue) const;
virtual bool updateTexture(TextureImage* image) const;
virtual void majorTickValues(std::vector<double>* domainValues ) const;
protected:
double m_rangeMin;
double m_rangeMax;
unsigned int m_decadeLevelCount;
std::set<double> m_sortedLevels;
private:
void updateSortedLevels();
private:
size_t m_levelCount; //< Number of discrete colors between min and max or number of sections between major ticks
bool m_adjustLevels; //< Toggles wether to round tick positions to nice numbers
std::set<double> m_userDefinedLevelValues;
Color3ubArray m_colors;
uint m_textureSize; // The size of texture that updateTexture() will produce.
};
}

View File

@@ -269,6 +269,40 @@ Color3ub ScalarMapperUniformLevels::mapToColor(double scalarValue) const
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ScalarMapperUniformLevels::updateColorLegend(OverlayColorLegend* legend) const
{
CVF_ASSERT(legend);
size_t numTicks = m_colors.size() + 1;
if (numTicks < 2)
{
return false;
}
DoubleArray ticks;
ticks.reserve(numTicks);
double delta = (m_rangeMax - m_rangeMin)/static_cast<double>(numTicks - 1);
size_t i;
for (i = 0; i < numTicks - 1; i++)
{
double tickVal = m_rangeMin + static_cast<double>(i)*delta;
ticks.add(tickVal);
}
ticks.add(m_rangeMax);
Color3ubArray colorArr(m_colors);
legend->configureLevels(colorArr, ticks);
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -319,55 +353,5 @@ bool ScalarMapperUniformLevels::updateTexture(TextureImage* image) const
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperUniformLevels::majorLevels( std::vector<double>* domainValues) const
{
CVF_ASSERT(domainValues != NULL);
size_t numTicks = m_colors.size() + 1;
CVF_ASSERT(numTicks > 1);
double delta = (m_rangeMax - m_rangeMin)/static_cast<double>(numTicks - 1);
size_t i;
for (i = 0; i < numTicks - 1; i++)
{
double tickVal = m_rangeMin + static_cast<double>(i)*delta;
domainValues->push_back(tickVal);
}
domainValues->push_back(m_rangeMax);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperUniformLevels::normalizedLevelPosition(double scalarValue) const
{
double range = m_rangeMax - m_rangeMin;
if (range != 0)
{
return (scalarValue - m_rangeMin)/range;
}
else
{
return 0;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperUniformLevels::domainValue(double normalizedPosition) const
{
double range = m_rangeMax - m_rangeMin;
return normalizedPosition*range + m_rangeMin;
}
} // namespace cvf

View File

@@ -20,7 +20,7 @@
#pragma once
#include "cvfObject.h"
#include "cvfLegendScalarMapper.h"
#include "cvfScalarMapper.h"
namespace cvf {
@@ -32,7 +32,7 @@ class OverlayColorLegend;
// Maps scalar values to texture coordinates/colors
//
//==================================================================================================
class ScalarMapperUniformLevels : public LegendScalarMapper
class ScalarMapperUniformLevels : public ScalarMapper
{
public:
ScalarMapperUniformLevels();
@@ -43,27 +43,18 @@ public:
void setColors(const Color3ubArray& colorArray);
void setColors(ColorTable colorTable, uint levelCount);
void setTextureSize(uint textureSize);
uint textureSize() const;
// Scalarmapper interface
virtual Vec2f mapToTextureCoord(double scalarValue) const;
virtual Color3ub mapToColor(double scalarValue) const;
virtual bool updateTexture(TextureImage* image) const;
// LegendScalarmapper interface
virtual void majorLevels(std::vector<double>* domainValues ) const;
virtual double normalizedLevelPosition( double domainValue ) const;
virtual double domainValue( double normalizedPosition ) const;
bool updateColorLegend(OverlayColorLegend* legend) const;
private:
void recomputeMaxTexCoord();
private:
double m_rangeMin;
double m_rangeMax;

View File

@@ -611,7 +611,9 @@ void ShaderProgram::applyFixedUniforms(OpenGLContext* oglContext, const MatrixSt
case NORMAL_MATRIX: glUniformMatrix3fv(location, 1, GL_FALSE, matrixState.normalMatrix().ptr()); break;
case PIXEL_HEIGHT_AT_UNIT_DISTANCE: glUniform1f(location, matrixState.pixelHeightAtUnitDistance()); break;
case VIEWPORT_WIDTH: glUniform1i(location, static_cast<GLint>(matrixState.viewportSize().x())); break;
case VIEWPORT_HEIGHT: glUniform1i(location, static_cast<GLint>(matrixState.viewportSize().y())); break;
case PIXEL_HEIGHT_AT_UNIT_DISTANCE: glUniform1f(location, matrixState.pixelHeightAtUnitDistance()); break;
default:
CVF_FAIL_MSG("Unhandled fixed uniform");
@@ -790,6 +792,8 @@ bool ShaderProgram::mapUniformNameToFixedUniformEnum(const char* uniformName, Fi
else if (System::strcmp(uniformName, "cvfu_normalMatrix") == 0) { *fixedUniform = NORMAL_MATRIX; return true; }
else if (System::strcmp(uniformName, "cvfu_viewportWidth") == 0) { *fixedUniform = VIEWPORT_WIDTH; return true; }
else if (System::strcmp(uniformName, "cvfu_viewportHeight") == 0) { *fixedUniform = VIEWPORT_HEIGHT; return true; }
else if (System::strcmp(uniformName, "cvfu_pixelHeightAtUnitDistance") == 0) { *fixedUniform = PIXEL_HEIGHT_AT_UNIT_DISTANCE; return true; }
else

View File

@@ -53,6 +53,8 @@ public:
MODEL_VIEW_MATRIX_INVERSE,
MODEL_VIEW_PROJECTION_MATRIX,
NORMAL_MATRIX,
VIEWPORT_WIDTH,
VIEWPORT_HEIGHT,
PIXEL_HEIGHT_AT_UNIT_DISTANCE
};

View File

@@ -96,6 +96,7 @@ const char* ShaderSourceRepository::shaderIdentString(ShaderIdent shaderIdent)
CVF_IDENT_HANDLE_CASE(calcShadowCoord);
CVF_IDENT_HANDLE_CASE(src_Color);
CVF_IDENT_HANDLE_CASE(src_TwoSidedColor);
CVF_IDENT_HANDLE_CASE(src_Texture);
CVF_IDENT_HANDLE_CASE(src_TextureGlobalAlpha);
CVF_IDENT_HANDLE_CASE(src_TextureFromPointCoord);
@@ -104,8 +105,7 @@ const char* ShaderSourceRepository::shaderIdentString(ShaderIdent shaderIdent)
CVF_IDENT_HANDLE_CASE(light_Phong);
CVF_IDENT_HANDLE_CASE(light_PhongDual);
CVF_IDENT_HANDLE_CASE(light_SimpleHeadlight);
CVF_IDENT_HANDLE_CASE(light_SimpleHeadlight_spec_uniform);
CVF_IDENT_HANDLE_CASE(light_AmbientDiffuse);
CVF_IDENT_HANDLE_CASE(light_Headlight);
CVF_IDENT_HANDLE_CASE(checkDiscard_ClipDistances);
@@ -129,6 +129,11 @@ const char* ShaderSourceRepository::shaderIdentString(ShaderIdent shaderIdent)
CVF_IDENT_HANDLE_CASE(fs_ParticleTraceComets);
CVF_IDENT_HANDLE_CASE(fs_GradientTopBottom);
CVF_IDENT_HANDLE_CASE(fs_GradientTopMiddleBottom);
CVF_IDENT_HANDLE_CASE(fs_HighlightStencilBlur_v33);
CVF_IDENT_HANDLE_CASE(fs_HighlightStencilDraw);
CVF_IDENT_HANDLE_CASE(fs_HighlightStencilMix_v33);
CVF_IDENT_HANDLE_CASE(fs_GaussianBlur);
CVF_IDENT_HANDLE_CASE(fs_HighlightMix);
CVF_IDENT_HANDLE_CASE(gs_PassThroughTriangle_v33);
}
@@ -151,6 +156,7 @@ bool ShaderSourceRepository::rawShaderSource(ShaderIdent shaderIdent, CharArray*
CVF_SOURCE_HANDLE_CASE(calcShadowCoord);
CVF_SOURCE_HANDLE_CASE(src_Color);
CVF_SOURCE_HANDLE_CASE(src_TwoSidedColor);
CVF_SOURCE_HANDLE_CASE(src_Texture);
CVF_SOURCE_HANDLE_CASE(src_TextureGlobalAlpha);
CVF_SOURCE_HANDLE_CASE(src_TextureFromPointCoord);
@@ -159,8 +165,7 @@ bool ShaderSourceRepository::rawShaderSource(ShaderIdent shaderIdent, CharArray*
CVF_SOURCE_HANDLE_CASE(light_Phong);
CVF_SOURCE_HANDLE_CASE(light_PhongDual);
CVF_SOURCE_HANDLE_CASE(light_SimpleHeadlight);
CVF_SOURCE_HANDLE_CASE(light_SimpleHeadlight_spec_uniform);
CVF_SOURCE_HANDLE_CASE(light_AmbientDiffuse);
CVF_SOURCE_HANDLE_CASE(light_Headlight);
CVF_SOURCE_HANDLE_CASE(checkDiscard_ClipDistances);
@@ -184,6 +189,11 @@ bool ShaderSourceRepository::rawShaderSource(ShaderIdent shaderIdent, CharArray*
CVF_SOURCE_HANDLE_CASE(fs_ParticleTraceComets);
CVF_SOURCE_HANDLE_CASE(fs_GradientTopBottom);
CVF_SOURCE_HANDLE_CASE(fs_GradientTopMiddleBottom);
CVF_SOURCE_HANDLE_CASE(fs_HighlightStencilBlur_v33);
CVF_SOURCE_HANDLE_CASE(fs_HighlightStencilDraw);
CVF_SOURCE_HANDLE_CASE(fs_HighlightStencilMix_v33);
CVF_SOURCE_HANDLE_CASE(fs_GaussianBlur);
CVF_SOURCE_HANDLE_CASE(fs_HighlightMix);
CVF_SOURCE_HANDLE_CASE(gs_PassThroughTriangle_v33);
}

View File

@@ -41,6 +41,7 @@ public:
calcShadowCoord,
src_Color,
src_TwoSidedColor,
src_Texture,
src_TextureGlobalAlpha,
src_TextureFromPointCoord,
@@ -49,8 +50,7 @@ public:
light_Phong,
light_PhongDual,
light_SimpleHeadlight,
light_SimpleHeadlight_spec_uniform,
light_AmbientDiffuse,
light_Headlight,
checkDiscard_ClipDistances,
@@ -74,6 +74,11 @@ public:
fs_ParticleTraceComets,
fs_GradientTopBottom,
fs_GradientTopMiddleBottom,
fs_HighlightStencilBlur_v33,
fs_HighlightStencilDraw,
fs_HighlightStencilMix_v33,
fs_GaussianBlur,
fs_HighlightMix,
gs_PassThroughTriangle_v33
};

View File

@@ -139,6 +139,124 @@ static const char fs_FixedColorMagenta_inl[] =
//#############################################################################################################################
//#############################################################################################################################
static const char fs_GaussianBlur_inl[] =
" \n"
"#if defined(USE_TEXTURE_RECT) \n"
"#extension GL_ARB_texture_rectangle : enable \n"
"#endif \n"
" \n"
" \n"
"// Shader program based on source code in article: \n"
"// http://callumhay.blogspot.no/2010/09/gaussian-blur-shader-glsl.html \n"
"// Which in turn is based on GPU Gems 3; Chapter 40 ('Incremental Computation of the Gaussian' by Ken Turkowski). \n"
"// http://http.developer.nvidia.com/GPUGems3/gpugems3_ch40.html \n"
" \n"
" \n"
"// The sigma value is the standard deviation for the Gaussian distribution \n"
"// A higher sigma value means more blur, but the sigma value should be tuned to the kernel size. \n"
" \n"
"// Defensive rule of thumb when choosing sigma values vs kernel size (see first link below): \n"
"// The gaussian distribution will have the vast majority of values in the interval [-3*sigma, 3*sigma], \n"
"// so a kernel width of 6*sigma should suffice. Just make sure to round it up to the closest odd number, \n"
"// so your kernel will be symmetric. \n"
"// http://www.gamedev.net/topic/526122-gaussian-blur-calculating-kernel-weight/ \n"
"// http://en.wikipedia.org/wiki/Gaussian_blur \n"
"// \n"
"// See also for a discussion of sigma vs kernel size: \n"
"// http://theinstructionlimit.com/gaussian-blur-revisited-part-two \n"
"// His suggestions for sigma values based on kernel size \n"
"// 17-tap : 3.66 <20> 4.95 \n"
"// 15-tap : 2.85 <20> 3.34 \n"
"// 13-tap : 2.49 <20> 2.95 \n"
"// 11-tap : 2.18 <20> 2.54 \n"
"// 9-tap : 1.8 <20> 2.12 \n"
"// 7-tap : 1.55 <20> 1.78 \n"
"// 5-tap : 1.35 <20> 1.54 \n"
" \n"
"uniform float u_sigma; // The sigma value for the gaussian function: higher value means more blur \n"
" // A good value for 9x9 is around 3 to 5 \n"
" // A good value for 7x7 is around 2.5 to 4 \n"
" // A good value for 5x5 is around 2 to 3.5 \n"
" // ... play around with this based on what you need :) \n"
" \n"
" \n"
"// Texture that will be blurred by this shader \n"
"#if defined(USE_TEXTURE_RECT) \n"
"uniform sampler2DRect u_blurSampler; \n"
"#else \n"
"uniform sampler2D u_blurSampler; \n"
" \n"
"uniform float u_blurSize; // This should usually be equal to \n"
" // 1.0f / texture_pixel_width for a horizontal blur, and \n"
" // 1.0f / texture_pixel_height for a vertical blur. \n"
"varying vec2 v_texCoord; \n"
"#endif \n"
" \n"
" \n"
" \n"
"// The following are all mutually exclusive macros for various seperable blurs of varying kernel size \n"
"// The original code had these as constants and using defines to choose one. \n"
"// Currently we do more or less the same, but we should investigate using uniforms instead \n"
" \n"
"// Vertical or horizontal pass? \n"
"#if defined(VERTICAL_BLUR) \n"
"const vec2 blurMultiplyVec = vec2(0.0f, 1.0f); \n"
"#elif defined(HORIZONTAL_BLUR) \n"
"const vec2 blurMultiplyVec = vec2(1.0f, 0.0f); \n"
"#endif \n"
" \n"
"#if defined(KERNEL_SIZE) \n"
"const float numBlurPixelsPerSide = (KERNEL_SIZE - 1.0f)/2.0f; \n"
"#endif \n"
" \n"
"const float pi = 3.14159265f; \n"
" \n"
" \n"
" \n"
"//-------------------------------------------------------------------------------------------------- \n"
"/// Separable Gaussian blur shader \n"
"//-------------------------------------------------------------------------------------------------- \n"
"void main() \n"
"{ \n"
" // Incremental Gaussian Coefficent Calculation (See GPU Gems 3 pp. 877 - 889) \n"
" vec3 incrementalGaussian; \n"
" incrementalGaussian.x = 1.0f / (sqrt(2.0f * pi) * u_sigma); \n"
" incrementalGaussian.y = exp(-0.5f / (u_sigma * u_sigma)); \n"
" incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y; \n"
" \n"
" vec4 avgValue = vec4(0.0f, 0.0f, 0.0f, 0.0f); \n"
" float coefficientSum = 0.0f; \n"
" \n"
" // Take the central sample first... \n"
"#if defined(USE_TEXTURE_RECT) \n"
" avgValue += texture2DRect(u_blurSampler, gl_FragCoord.xy) * incrementalGaussian.x; \n"
"#else \n"
" avgValue += texture2D(u_blurSampler, v_texCoord) * incrementalGaussian.x; \n"
"#endif \n"
" coefficientSum += incrementalGaussian.x; \n"
" incrementalGaussian.xy *= incrementalGaussian.yz; \n"
" \n"
" // Go through the remaining 8 vertical samples (4 on each side of the center) \n"
" for (float i = 1.0f; i <= numBlurPixelsPerSide; i++) \n"
" { \n"
"#if defined(USE_TEXTURE_RECT) \n"
" avgValue += texture2DRect(u_blurSampler, gl_FragCoord.xy - i*blurMultiplyVec) * incrementalGaussian.x; \n"
" avgValue += texture2DRect(u_blurSampler, gl_FragCoord.xy + i*blurMultiplyVec) * incrementalGaussian.x; \n"
"#else \n"
" avgValue += texture2D(u_blurSampler, v_texCoord - i*u_blurSize*blurMultiplyVec) * incrementalGaussian.x; \n"
" avgValue += texture2D(u_blurSampler, v_texCoord + i*u_blurSize*blurMultiplyVec) * incrementalGaussian.x; \n"
"#endif \n"
" coefficientSum += 2*incrementalGaussian.x; \n"
" incrementalGaussian.xy *= incrementalGaussian.yz; \n"
" } \n"
" \n"
" gl_FragColor = avgValue / coefficientSum; \n"
"} \n";
//#############################################################################################################################
//#############################################################################################################################
static const char fs_GradientTopBottom_inl[] =
@@ -185,6 +303,137 @@ static const char fs_GradientTopMiddleBottom_inl[] =
//#############################################################################################################################
//#############################################################################################################################
static const char fs_HighlightMix_inl[] =
"//#extension GL_ARB_texture_rectangle : enable \n"
" \n"
"uniform vec3 u_highlightColor; \n"
" \n"
"//uniform sampler2DRect u_texture2DRect; \n"
"uniform sampler2D u_texture2D; \n"
" \n"
"varying vec2 v_texCoord; \n"
" \n"
" \n"
"//-------------------------------------------------------------------------------------------------- \n"
"/// Mix fragment shader for use with part highlighter \n"
"//-------------------------------------------------------------------------------------------------- \n"
"void main() \n"
"{ \n"
" const float interiorAlphaScaleFactor = 4.0; \n"
" const float exteriorAlphaScaleFactor = 2.0; \n"
" \n"
" //float alpha = texture2DRect(u_texture2DRect, gl_FragCoord.xy).a; \n"
" float alpha = texture2D(u_texture2D, v_texCoord).a; \n"
" \n"
" /* \n"
" // Naive version \n"
" if (alpha > 0.5) \n"
" { \n"
" alpha = interiorAlphaScaleFactor*(1.0 - alpha); \n"
" } \n"
" else \n"
" { \n"
" alpha *= exteriorAlphaScaleFactor; \n"
" } \n"
" */ \n"
" \n"
" // Better \n"
" //alpha = 0.5 - abs(alpha - 0.5); \n"
" \n"
" // Fra Jakob, doesn't compile, but rewrite with step function \n"
" //alpha = (alpha < 0.5)*alpha + (alpha >= 0.5)*(1 - alpha); \n"
" \n"
" float s = step(alpha, 0.5); \n"
" alpha = (s*alpha)*exteriorAlphaScaleFactor + ((1 - s)*(1 - alpha))*interiorAlphaScaleFactor ; \n"
" \n"
" \n"
" gl_FragColor = vec4(u_highlightColor, alpha); \n"
"} \n";
//#############################################################################################################################
//#############################################################################################################################
static const char fs_HighlightStencilBlur_v33_inl[] =
"#extension GL_ARB_texture_rectangle : enable \n"
" \n"
"uniform sampler2DRect u_texture2DRect; \n"
" \n"
" \n"
"vec4 selectBrightest() \n"
"{ \n"
" const int siz = 5; \n"
" const int halfSize = 2; \n"
" vec4 maxSample = vec4(0, 0, 0, 0); \n"
" for (int y = 0; y < siz; y++) \n"
" { \n"
" for (int x = 0; x < siz; x++) \n"
" { \n"
" vec4 t = texture2DRect(u_texture2DRect, gl_FragCoord.xy + vec2(x - halfSize, y - halfSize)); \n"
" if (t.a > maxSample.a) \n"
" { \n"
" maxSample = t; \n"
" } \n"
" } \n"
" } \n"
" \n"
" return maxSample; \n"
"} \n"
" \n"
" \n"
"//-------------------------------------------------------------------------------------------------- \n"
"/// \n"
"//-------------------------------------------------------------------------------------------------- \n"
"void main() \n"
"{ \n"
" gl_FragData[0] = selectBrightest(); \n"
"} \n";
//#############################################################################################################################
//#############################################################################################################################
static const char fs_HighlightStencilDraw_inl[] =
" \n"
"uniform vec4 u_color; \n"
" \n"
"//-------------------------------------------------------------------------------------------------- \n"
"/// Initial draw pass for highlighting \n"
"//-------------------------------------------------------------------------------------------------- \n"
"void main() \n"
"{ \n"
" gl_FragData[0] = u_color; \n"
"} \n";
//#############################################################################################################################
//#############################################################################################################################
static const char fs_HighlightStencilMix_v33_inl[] =
"#extension GL_ARB_texture_rectangle : enable \n"
" \n"
"uniform sampler2DRect u_texture2DRect; \n"
" \n"
"//-------------------------------------------------------------------------------------------------- \n"
"/// \n"
"//-------------------------------------------------------------------------------------------------- \n"
"void main() \n"
"{ \n"
" vec4 t = texture2DRect(u_texture2DRect, gl_FragCoord.xy); \n"
" if (t.a > 0.0) \n"
" { \n"
" gl_FragColor = t; \n"
" } \n"
" else \n"
" { \n"
" discard; \n"
" } \n"
"} \n";
//#############################################################################################################################
//#############################################################################################################################
static const char fs_ParticleTraceComets_inl[] =
@@ -398,23 +647,25 @@ static const char gs_PassThroughTriangle_v33_inl[] =
//#############################################################################################################################
//#############################################################################################################################
static const char light_AmbientDiffuse_inl[] =
static const char light_Headlight_inl[] =
" \n"
"varying vec3 v_ecPosition; \n"
"varying vec3 v_ecNormal; \n"
" \n"
"uniform float u_specularIntensity; \n"
"uniform float u_ambientIntensity; \n"
"uniform vec3 u_ecLightPosition; \n"
"uniform vec3 u_emissiveColor; \n"
" \n"
"//-------------------------------------------------------------------------------------------------- \n"
"/// lightFragment() - Simple Headlight \n"
"/// lightFragment() - Headlight with all params exposed as uniforms \n"
"/// \n"
"/// A fixed, two sided headlight \n"
"//-------------------------------------------------------------------------------------------------- \n"
"vec4 lightFragment(vec4 srcFragColor, float not_in_use_shadowFactor) \n"
"{ \n"
" const vec3 ecLightPosition = vec3(0.5, 5.0, 7.0); \n"
" const float ambientIntensity = 0.2; \n"
" \n"
" // Light vector (from point to light source) \n"
" vec3 L = normalize(ecLightPosition - v_ecPosition); \n"
" vec3 L = normalize(u_ecLightPosition - v_ecPosition); \n"
" \n"
" // Viewing vector (from point to eye) \n"
" // Since we are in eye space, the eye pos is at (0, 0, 0) \n"
@@ -423,10 +674,11 @@ static const char light_AmbientDiffuse_inl[] =
" vec3 N = normalize(v_ecNormal); \n"
" vec3 R = normalize(reflect(-L, N)); \n"
" \n"
" vec3 ambient = srcFragColor.rgb*ambientIntensity; \n"
" vec3 diffuse = srcFragColor.rgb*(1.0 - ambientIntensity)*abs(dot(N, L)); \n"
" vec3 ambient = srcFragColor.rgb*u_ambientIntensity; \n"
" vec3 diffuse = srcFragColor.rgb*(1.0 - u_ambientIntensity)*abs(dot(N, L)); \n"
" vec3 specular = vec3(u_specularIntensity*pow(max(dot(R, V), 0.0), 8.0)); \n"
" \n"
" return vec4(ambient + diffuse, srcFragColor.a); \n"
" return vec4(ambient + diffuse + specular + u_emissiveColor, srcFragColor.a); \n"
"} \n";
@@ -547,44 +799,6 @@ static const char light_SimpleHeadlight_inl[] =
//#############################################################################################################################
//#############################################################################################################################
static const char light_SimpleHeadlight_spec_uniform_inl[] =
" \n"
"varying vec3 v_ecPosition; \n"
"varying vec3 v_ecNormal; \n"
" \n"
"uniform float u_specularIntensity; \n"
" \n"
"//-------------------------------------------------------------------------------------------------- \n"
"/// lightFragment() - Simple Headlight with specular uniform \n"
"/// \n"
"/// A fixed, two sided headlight \n"
"//-------------------------------------------------------------------------------------------------- \n"
"vec4 lightFragment(vec4 srcFragColor, float not_in_use_shadowFactor) \n"
"{ \n"
" const vec3 ecLightPosition = vec3(0.5, 5.0, 7.0); \n"
" const float ambientIntensity = 0.2; \n"
" \n"
" // Light vector (from point to light source) \n"
" vec3 L = normalize(ecLightPosition - v_ecPosition); \n"
" \n"
" // Viewing vector (from point to eye) \n"
" // Since we are in eye space, the eye pos is at (0, 0, 0) \n"
" vec3 V = normalize(-v_ecPosition); \n"
" \n"
" vec3 N = normalize(v_ecNormal); \n"
" vec3 R = normalize(reflect(-L, N)); \n"
" \n"
" vec3 ambient = srcFragColor.rgb*ambientIntensity; \n"
" vec3 diffuse = srcFragColor.rgb*(1.0 - ambientIntensity)*abs(dot(N, L)); \n"
" vec3 specular = vec3(u_specularIntensity*pow(max(dot(R, V), 0.0), 8.0)); \n"
" \n"
" return vec4(ambient + diffuse + specular, srcFragColor.a); \n"
"} \n";
//#############################################################################################################################
//#############################################################################################################################
static const char src_Color_inl[] =
@@ -671,6 +885,30 @@ static const char src_TextureRectFromFragCoord_v33_inl[] =
//#############################################################################################################################
//#############################################################################################################################
static const char src_TwoSidedColor_inl[] =
" \n"
"uniform vec4 u_color; \n"
"uniform vec4 u_backColor; \n"
" \n"
"//-------------------------------------------------------------------------------------------------- \n"
"/// srcFragment() - Single color by uniform \n"
"//-------------------------------------------------------------------------------------------------- \n"
"vec4 srcFragment() \n"
"{ \n"
" if (gl_FrontFacing) \n"
" { \n"
" return u_color; \n"
" } \n"
" else \n"
" { \n"
" return u_backColor; \n"
" } \n"
"} \n";
//#############################################################################################################################
//#############################################################################################################################
static const char vs_DistanceScaledPoints_inl[] =

View File

@@ -26,13 +26,14 @@
#include "cvfOpenGLResourceManager.h"
#include "cvfShaderProgram.h"
#include "cvfUniform.h"
#include "cvfRenderState.h"
#include "cvfCamera.h"
#include "cvfViewport.h"
#include "cvfBoundingBox.h"
#include "cvfShaderProgramGenerator.h"
#include "cvfShaderSourceProvider.h"
#include "cvfMatrixState.h"
#include "cvfRenderStateDepth.h"
#include "cvfRenderStateBlending.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
@@ -191,6 +192,51 @@ void TextDrawer::setDrawBorder(bool drawBorder)
}
//--------------------------------------------------------------------------------------------------
/// Returns the color used to draw the text
//--------------------------------------------------------------------------------------------------
Color3f TextDrawer::textColor() const
{
return m_textColor;
}
//--------------------------------------------------------------------------------------------------
/// Returns the color of the background
//--------------------------------------------------------------------------------------------------
Color3f TextDrawer::backgroundColor() const
{
return m_backgroundColor;
}
//--------------------------------------------------------------------------------------------------
/// Returns the color of the border.
//--------------------------------------------------------------------------------------------------
Color3f TextDrawer::borderColor() const
{
return m_borderColor;
}
//--------------------------------------------------------------------------------------------------
/// Returns true if the background will be drawn
//--------------------------------------------------------------------------------------------------
bool TextDrawer::drawBackground() const
{
return m_drawBackground;
}
//--------------------------------------------------------------------------------------------------
/// Returns true if the border will be drawn
//--------------------------------------------------------------------------------------------------
bool TextDrawer::drawBorder() const
{
return m_drawBorder;
}
//--------------------------------------------------------------------------------------------------
/// Draw text based using OpenGL shader programs
//--------------------------------------------------------------------------------------------------
@@ -238,7 +284,7 @@ void TextDrawer::doRender2d(OpenGLContext* oglContext, const MatrixState& matrix
MatrixState projMatrixState(projCam);
// Turn off depth test
Depth depth(false, Depth::LESS, false);
RenderStateDepth depth(false, RenderStateDepth::LESS, false);
depth.applyOpenGL(oglContext);
// Setup viewport
@@ -252,11 +298,11 @@ void TextDrawer::doRender2d(OpenGLContext* oglContext, const MatrixState& matrix
}
#ifndef CVF_OPENGL_ES
Material_FF mat;
RenderStateMaterial_FF mat;
mat.enableColorMaterial(true);
mat.applyOpenGL(oglContext);
Lighting_FF light(false);
RenderStateLighting_FF light(false);
light.applyOpenGL(oglContext);
#endif
projCam.applyOpenGL();
@@ -268,6 +314,10 @@ void TextDrawer::doRender2d(OpenGLContext* oglContext, const MatrixState& matrix
glVertexAttribPointer(ShaderProgram::VERTEX, 3, GL_FLOAT, GL_FALSE, 0, vertexArray);
}
// Use a fixed line spacing
float lineSpacing = m_font->lineSpacing();
Vec2f offset(0,0);
// Render background and border
// -------------------------------------------------------------------------
if (m_drawBackground || m_drawBorder)
@@ -289,61 +339,18 @@ void TextDrawer::doRender2d(OpenGLContext* oglContext, const MatrixState& matrix
float charHeight = static_cast<float>(glyph->height());
float charWidth = static_cast<float>(glyph->width());
offset.x() = cvf::Math::floor(charWidth/2.0f);
offset.y() = cvf::Math::floor(charHeight/2.0f);
size_t numTexts = m_texts.size();
size_t i, j;
for (i = 0; i < numTexts; i++)
for (size_t i = 0; i < numTexts; i++)
{
Vec3f pos = m_positions[i];
String text = m_texts[i];
BoundingBox textBB;
Vec2ui textExtent = m_font->textExtent(text);
// Cursor incrementor
Vec2f cursor(pos);
size_t numCharacters = text.size();
for (j = 0; j < numCharacters; j++)
{
wchar_t character = text[j];
ref<Glyph> glyph = m_font->getGlyph(character);
float textureWidth = static_cast<float>(glyph->width());
float textureHeight = static_cast<float>(glyph->height());
// Lower left corner
v1[0] = cursor.x() + static_cast<float>(glyph->horizontalBearingX());
v1[1] = cursor.y() + static_cast<float>(glyph->horizontalBearingY()) - textureHeight + static_cast<float>(m_verticalAlignment);
// Lower right corner
v2[0] = v1[0] + textureWidth;
v2[1] = v1[1];
// Upper right corner
v3[0] = v2[0];
v3[1] = v1[1] + textureHeight;
// Upper left corner
v4[0] = v1[0];
v4[1] = v3[1];
textBB.add(Vec3f(v1[0], v1[1], 0.0f));
textBB.add(Vec3f(v2[0], v2[1], 0.0f));
textBB.add(Vec3f(v3[0], v3[1], 0.0f));
textBB.add(Vec3f(v4[0], v4[1], 0.0f));
// Jump to the next character in the string, if any
if (j < (numCharacters - 1))
{
float advance = static_cast<float>(m_font->advance(character, text[j + 1]));
cursor.x() += advance;
}
}
Vec3f min = Vec3f(textBB.min());
Vec3f max = Vec3f(textBB.max());
min.x() -= charWidth*0.5f;
max.x() += charWidth*0.5f;
min.y() -= charHeight*0.5f;
max.y() += charHeight*0.5f;
Vec3f min = pos;//Vec3f(textBB.min());
Vec3f max = Vec3f(min.x() + static_cast<float>(textExtent.x()) + offset.x()*2.0f, min.y() + static_cast<float>(textExtent.y()) + offset.y()*2.0f, 0.0f);
// Draw the background triangle
v1[0] = min.x(); v1[1] = min.y();
@@ -432,7 +439,7 @@ void TextDrawer::doRender2d(OpenGLContext* oglContext, const MatrixState& matrix
glActiveTexture(GL_TEXTURE0);
}
Blending blending;
RenderStateBlending blending;
blending.configureTransparencyBlending();
blending.applyOpenGL(oglContext);
@@ -444,6 +451,7 @@ void TextDrawer::doRender2d(OpenGLContext* oglContext, const MatrixState& matrix
for (i = 0; i < numTexts; i++)
{
Vec3f pos = m_positions[i];
String text = m_texts[i];
// Need to round off to integer positions to avoid buggy text drawing on iPad2
@@ -453,82 +461,94 @@ void TextDrawer::doRender2d(OpenGLContext* oglContext, const MatrixState& matrix
// Cursor incrementor
Vec2f cursor(pos);
cursor += offset;
numCharacters = text.size();
std::vector<cvf::String> lines = text.split("\n");
for (j = 0; j < numCharacters; j++)
for (size_t lineIdx = lines.size(); lineIdx-- > 0; )
{
character = text[j];
ref<Glyph> glyph = m_font->getGlyph(character);
String line = lines[lineIdx];
float textureWidth = static_cast<float>(glyph->width());
float textureHeight = static_cast<float>(glyph->height());
numCharacters = line.size();
// Lower left corner
v1[0] = cursor.x() + static_cast<float>(glyph->horizontalBearingX());
v1[1] = cursor.y() + static_cast<float>(glyph->horizontalBearingY()) - textureHeight + static_cast<float>(m_verticalAlignment);
// Lower right corner
v2[0] = v1[0] + textureWidth;
v2[1] = v1[1];
// Upper right corner
v3[0] = v2[0];
v3[1] = v1[1] + textureHeight;
// Upper left corner
v4[0] = v1[0];
v4[1] = v3[1];
glyph->setupAndBindTexture(oglContext, softwareRendering);
// Get texture coordinates
const FloatArray* textureCoordinates = glyph->textureCoordinates();
CVF_ASSERT(textureCoordinates);
CVF_ASSERT(textureCoordinates->size() == 8);
const float* textureCoordinatesPtr = textureCoordinates->ptr();
CVF_ASSERT(textureCoordinatesPtr);
int t;
for (t = 0; t < 8; t++)
for (j = 0; j < numCharacters; j++)
{
textureCoords[t] = textureCoordinatesPtr[t];
}
character = line[j];
ref<Glyph> glyph = m_font->getGlyph(character);
if (softwareRendering)
{
float textureWidth = static_cast<float>(glyph->width());
float textureHeight = static_cast<float>(glyph->height());
// Lower left corner
v1[0] = cursor.x() + static_cast<float>(glyph->horizontalBearingX());
v1[1] = cursor.y() + static_cast<float>(glyph->horizontalBearingY()) - textureHeight + static_cast<float>(m_verticalAlignment);
// Lower right corner
v2[0] = v1[0] + textureWidth;
v2[1] = v1[1];
// Upper right corner
v3[0] = v2[0];
v3[1] = v1[1] + textureHeight;
// Upper left corner
v4[0] = v1[0];
v4[1] = v3[1];
glyph->setupAndBindTexture(oglContext, softwareRendering);
// Get texture coordinates
const FloatArray* textureCoordinates = glyph->textureCoordinates();
CVF_ASSERT(textureCoordinates);
CVF_ASSERT(textureCoordinates->size() == 8);
const float* textureCoordinatesPtr = textureCoordinates->ptr();
CVF_ASSERT(textureCoordinatesPtr);
int t;
for (t = 0; t < 8; t++)
{
textureCoords[t] = textureCoordinatesPtr[t];
}
if (softwareRendering)
{
#ifndef CVF_OPENGL_ES
glBegin(GL_TRIANGLES);
glBegin(GL_TRIANGLES);
// First triangle in quad
glTexCoord2fv(&textureCoordinatesPtr[0]);
glVertex3fv(v1);
glTexCoord2fv(&textureCoordinatesPtr[2]);
glVertex3fv(v2);
glTexCoord2fv(&textureCoordinatesPtr[4]);
glVertex3fv(v3);
// First triangle in quad
glTexCoord2fv(&textureCoordinatesPtr[0]);
glVertex3fv(v1);
glTexCoord2fv(&textureCoordinatesPtr[2]);
glVertex3fv(v2);
glTexCoord2fv(&textureCoordinatesPtr[4]);
glVertex3fv(v3);
// Second triangle in quad
glTexCoord2fv(&textureCoordinatesPtr[0]);
glVertex3fv(v1);
glTexCoord2fv(&textureCoordinatesPtr[4]);
glVertex3fv(v3);
glTexCoord2fv(&textureCoordinatesPtr[6]);
glVertex3fv(v4);
// Second triangle in quad
glTexCoord2fv(&textureCoordinatesPtr[0]);
glVertex3fv(v1);
glTexCoord2fv(&textureCoordinatesPtr[4]);
glVertex3fv(v3);
glTexCoord2fv(&textureCoordinatesPtr[6]);
glVertex3fv(v4);
glEnd();
glEnd();
#endif
}
else
{
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, connects);
}
else
{
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, connects);
}
// Jump to the next character in the string, if any
if (j < (numCharacters - 1))
{
float advance = static_cast<float>(m_font->advance(character, text[j + 1]));
cursor.x() += advance;
}
}
// Jump to the next character in the string, if any
if (j < (numCharacters - 1))
{
float advance = static_cast<float>(m_font->advance(character, text[j + 1]));
cursor.x() += advance;
}
// CR
cursor.x() = pos.x() + offset.x();
cursor.y() += lineSpacing;
}
}
@@ -543,10 +563,10 @@ void TextDrawer::doRender2d(OpenGLContext* oglContext, const MatrixState& matrix
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(matrixState.viewMatrix().ptr());
Material_FF mat;
RenderStateMaterial_FF mat;
mat.applyOpenGL(oglContext);
Lighting_FF light;
RenderStateLighting_FF light;
light.applyOpenGL(oglContext);
#endif
}
@@ -559,11 +579,11 @@ void TextDrawer::doRender2d(OpenGLContext* oglContext, const MatrixState& matrix
}
// Reset render states
Blending resetBlending;
RenderStateBlending resetBlending;
resetBlending.applyOpenGL(oglContext);
// Turn off depth test
Depth resetDepth;
RenderStateDepth resetDepth;
resetDepth.applyOpenGL(oglContext);
CVF_CHECK_OGL(oglContext);

View File

@@ -54,18 +54,24 @@ public:
TextDrawer(Font* font);
virtual ~TextDrawer();
void addText(const String& text, const Vec2f& pos);
void removeAllTexts();
void addText(const String& text, const Vec2f& pos);
void removeAllTexts();
void setVerticalAlignment(Alignment alignment);
void setTextColor(const Color3f& color);
void setBackgroundColor(const Color3f& color);
void setBorderColor(const Color3f& color);
void setDrawBackground(bool drawBackground);
void setDrawBorder(bool drawBorder);
void setVerticalAlignment(Alignment alignment);
void setTextColor(const Color3f& color);
void setBackgroundColor(const Color3f& color);
void setBorderColor(const Color3f& color);
void setDrawBackground(bool drawBackground);
void setDrawBorder(bool drawBorder);
void render(OpenGLContext* oglContext, const MatrixState& matrixState);
void renderSoftware(OpenGLContext* oglContext, const MatrixState& matrixState);
Color3f textColor() const;
Color3f backgroundColor() const;
Color3f borderColor() const;
bool drawBackground() const;
bool drawBorder() const;
void render(OpenGLContext* oglContext, const MatrixState& matrixState);
void renderSoftware(OpenGLContext* oglContext, const MatrixState& matrixState);
private:
void doRender2d(OpenGLContext* oglContext, const MatrixState& matrixState, bool softwareRendering);

View File

@@ -243,9 +243,14 @@ bool Texture::setupTexture(OpenGLContext* oglContext)
}
else if (m_internalFormat == DEPTH24_STENCIL8)
{
#ifndef CVF_OPENGL_ES
CVF_ASSERT(m_image.isNull());
CVF_ASSERT(!m_enableMipmapGeneration);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormatOpenGL(), static_cast<GLsizei>(m_width), static_cast<GLsizei>(m_height), 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
#else
CVF_FAIL_MSG("Not supported on IOS");
#endif
}
else
{

View File

@@ -109,13 +109,24 @@ void TextureImage::setFromRgb(const UByteArray& rgbData, uint width, uint height
CVF_ASSERT(width > 0 && height > 0);
CVF_ASSERT(rgbData.size() == width*height*3);
m_dataRgba.reserve(width*height*4);
setFromRgb(rgbData.ptr(), width, height);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureImage::setFromRgb(const ubyte* rgbData, uint width, uint height)
{
CVF_ASSERT(rgbData);
CVF_ASSERT(width > 0 && height > 0);
const size_t numPixels = width*height;
m_dataRgba.reserve(4*numPixels);
m_width = width;
m_height = height;
size_t numPixels = rgbData.size()/3;
size_t i;
for (i = 0; i < numPixels; i++)
for (size_t i = 0; i < numPixels; i++)
{
m_dataRgba.add(rgbData[3*i + 0]);
m_dataRgba.add(rgbData[3*i + 1]);

View File

@@ -44,9 +44,10 @@ public:
void allocate(uint width, uint height);
void setData(const ubyte* rgbaData, uint width, uint height);
void setFromRgb(const UByteArray& rgbData, uint width, uint height);
void setFromRgb(const ubyte* rgbData, uint width, uint height);
const ubyte* ptr() const;
ref<UByteArray> toRgb() const;
const ubyte* ptr() const;
void setPixel(uint x, uint y, const Color4ub& clr);
Color4ub pixel(uint x, uint y) const;

View File

@@ -654,12 +654,16 @@ void VertexBundle::finishUseBundle(OpenGLContext* oglContext, VertexBundleUsage*
if (bundleUsage->fixedFunction())
{
#ifdef CVF_OPENGL_ES
CVF_FAIL_MSG("Not supported on OpenGL ES");
#else
CVF_TIGHT_ASSERT(oglContext->capabilities()->supportsFixedFunction());
if (m_vertexCount > 0) glDisableClientState(GL_VERTEX_ARRAY);
if (m_hasNormals) glDisableClientState(GL_NORMAL_ARRAY);
if (m_hasTexCoords) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (m_hasColors) glDisableClientState(GL_COLOR_ARRAY);
#endif
}
else
{

View File

@@ -0,0 +1,113 @@
#if defined(USE_TEXTURE_RECT)
#extension GL_ARB_texture_rectangle : enable
#endif
// Shader program based on source code in article:
// http://callumhay.blogspot.no/2010/09/gaussian-blur-shader-glsl.html
// Which in turn is based on GPU Gems 3; Chapter 40 ('Incremental Computation of the Gaussian' by Ken Turkowski).
// http://http.developer.nvidia.com/GPUGems3/gpugems3_ch40.html
// The sigma value is the standard deviation for the Gaussian distribution
// A higher sigma value means more blur, but the sigma value should be tuned to the kernel size.
// Defensive rule of thumb when choosing sigma values vs kernel size (see first link below):
// The gaussian distribution will have the vast majority of values in the interval [-3*sigma, 3*sigma],
// so a kernel width of 6*sigma should suffice. Just make sure to round it up to the closest odd number,
// so your kernel will be symmetric.
// http://www.gamedev.net/topic/526122-gaussian-blur-calculating-kernel-weight/
// http://en.wikipedia.org/wiki/Gaussian_blur
//
// See also for a discussion of sigma vs kernel size:
// http://theinstructionlimit.com/gaussian-blur-revisited-part-two
// His suggestions for sigma values based on kernel size
// 17-tap : 3.66 <20> 4.95
// 15-tap : 2.85 <20> 3.34
// 13-tap : 2.49 <20> 2.95
// 11-tap : 2.18 <20> 2.54
// 9-tap : 1.8 <20> 2.12
// 7-tap : 1.55 <20> 1.78
// 5-tap : 1.35 <20> 1.54
uniform float u_sigma; // The sigma value for the gaussian function: higher value means more blur
// A good value for 9x9 is around 3 to 5
// A good value for 7x7 is around 2.5 to 4
// A good value for 5x5 is around 2 to 3.5
// ... play around with this based on what you need :)
// Texture that will be blurred by this shader
#if defined(USE_TEXTURE_RECT)
uniform sampler2DRect u_blurSampler;
#else
uniform sampler2D u_blurSampler;
uniform float u_blurSize; // This should usually be equal to
// 1.0f / texture_pixel_width for a horizontal blur, and
// 1.0f / texture_pixel_height for a vertical blur.
varying vec2 v_texCoord;
#endif
// The following are all mutually exclusive macros for various seperable blurs of varying kernel size
// The original code had these as constants and using defines to choose one.
// Currently we do more or less the same, but we should investigate using uniforms instead
// Vertical or horizontal pass?
#if defined(VERTICAL_BLUR)
const vec2 blurMultiplyVec = vec2(0.0f, 1.0f);
#elif defined(HORIZONTAL_BLUR)
const vec2 blurMultiplyVec = vec2(1.0f, 0.0f);
#endif
#if defined(KERNEL_SIZE)
const float numBlurPixelsPerSide = (KERNEL_SIZE - 1.0f)/2.0f;
#endif
const float pi = 3.14159265f;
//--------------------------------------------------------------------------------------------------
/// Separable Gaussian blur shader
//--------------------------------------------------------------------------------------------------
void main()
{
// Incremental Gaussian Coefficent Calculation (See GPU Gems 3 pp. 877 - 889)
vec3 incrementalGaussian;
incrementalGaussian.x = 1.0f / (sqrt(2.0f * pi) * u_sigma);
incrementalGaussian.y = exp(-0.5f / (u_sigma * u_sigma));
incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
vec4 avgValue = vec4(0.0f, 0.0f, 0.0f, 0.0f);
float coefficientSum = 0.0f;
// Take the central sample first...
#if defined(USE_TEXTURE_RECT)
avgValue += texture2DRect(u_blurSampler, gl_FragCoord.xy) * incrementalGaussian.x;
#else
avgValue += texture2D(u_blurSampler, v_texCoord) * incrementalGaussian.x;
#endif
coefficientSum += incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
// Go through the remaining 8 vertical samples (4 on each side of the center)
for (float i = 1.0f; i <= numBlurPixelsPerSide; i++)
{
#if defined(USE_TEXTURE_RECT)
avgValue += texture2DRect(u_blurSampler, gl_FragCoord.xy - i*blurMultiplyVec) * incrementalGaussian.x;
avgValue += texture2DRect(u_blurSampler, gl_FragCoord.xy + i*blurMultiplyVec) * incrementalGaussian.x;
#else
avgValue += texture2D(u_blurSampler, v_texCoord - i*u_blurSize*blurMultiplyVec) * incrementalGaussian.x;
avgValue += texture2D(u_blurSampler, v_texCoord + i*u_blurSize*blurMultiplyVec) * incrementalGaussian.x;
#endif
coefficientSum += 2*incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
}
gl_FragColor = avgValue / coefficientSum;
}

View File

@@ -0,0 +1,45 @@
//#extension GL_ARB_texture_rectangle : enable
uniform vec3 u_highlightColor;
//uniform sampler2DRect u_texture2DRect;
uniform sampler2D u_texture2D;
varying vec2 v_texCoord;
//--------------------------------------------------------------------------------------------------
/// Mix fragment shader for use with part highlighter
//--------------------------------------------------------------------------------------------------
void main()
{
const float interiorAlphaScaleFactor = 4.0;
const float exteriorAlphaScaleFactor = 2.0;
//float alpha = texture2DRect(u_texture2DRect, gl_FragCoord.xy).a;
float alpha = texture2D(u_texture2D, v_texCoord).a;
/*
// Naive version
if (alpha > 0.5)
{
alpha = interiorAlphaScaleFactor*(1.0 - alpha);
}
else
{
alpha *= exteriorAlphaScaleFactor;
}
*/
// Better
//alpha = 0.5 - abs(alpha - 0.5);
// Fra Jakob, doesn't compile, but rewrite with step function
//alpha = (alpha < 0.5)*alpha + (alpha >= 0.5)*(1 - alpha);
float s = step(alpha, 0.5);
alpha = (s*alpha)*exteriorAlphaScaleFactor + ((1 - s)*(1 - alpha))*interiorAlphaScaleFactor ;
gl_FragColor = vec4(u_highlightColor, alpha);
}

View File

@@ -0,0 +1,34 @@
#extension GL_ARB_texture_rectangle : enable
uniform sampler2DRect u_texture2DRect;
vec4 selectBrightest()
{
const int siz = 5;
const int halfSize = 2;
vec4 maxSample = vec4(0, 0, 0, 0);
for (int y = 0; y < siz; y++)
{
for (int x = 0; x < siz; x++)
{
vec4 t = texture2DRect(u_texture2DRect, gl_FragCoord.xy + vec2(x - halfSize, y - halfSize));
if (t.a > maxSample.a)
{
maxSample = t;
}
}
}
return maxSample;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void main()
{
gl_FragData[0] = selectBrightest();
}

View File

@@ -0,0 +1,11 @@
uniform vec4 u_color;
//--------------------------------------------------------------------------------------------------
/// Initial draw pass for highlighting
//--------------------------------------------------------------------------------------------------
void main()
{
gl_FragData[0] = u_color;
}

View File

@@ -0,0 +1,19 @@
#extension GL_ARB_texture_rectangle : enable
uniform sampler2DRect u_texture2DRect;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void main()
{
vec4 t = texture2DRect(u_texture2DRect, gl_FragCoord.xy);
if (t.a > 0.0)
{
gl_FragColor = t;
}
else
{
discard;
}
}

View File

@@ -1,29 +0,0 @@
varying vec3 v_ecPosition;
varying vec3 v_ecNormal;
//--------------------------------------------------------------------------------------------------
/// lightFragment() - Simple Headlight
///
/// A fixed, two sided headlight
//--------------------------------------------------------------------------------------------------
vec4 lightFragment(vec4 srcFragColor, float not_in_use_shadowFactor)
{
const vec3 ecLightPosition = vec3(0.5, 5.0, 7.0);
const float ambientIntensity = 0.2;
// Light vector (from point to light source)
vec3 L = normalize(ecLightPosition - v_ecPosition);
// Viewing vector (from point to eye)
// Since we are in eye space, the eye pos is at (0, 0, 0)
vec3 V = normalize(-v_ecPosition);
vec3 N = normalize(v_ecNormal);
vec3 R = normalize(reflect(-L, N));
vec3 ambient = srcFragColor.rgb*ambientIntensity;
vec3 diffuse = srcFragColor.rgb*(1.0 - ambientIntensity)*abs(dot(N, L));
return vec4(ambient + diffuse, srcFragColor.a);
}

View File

@@ -0,0 +1,32 @@
varying vec3 v_ecPosition;
varying vec3 v_ecNormal;
uniform float u_specularIntensity;
uniform float u_ambientIntensity;
uniform vec3 u_ecLightPosition;
uniform vec3 u_emissiveColor;
//--------------------------------------------------------------------------------------------------
/// lightFragment() - Headlight with all params exposed as uniforms
///
/// A fixed, two sided headlight
//--------------------------------------------------------------------------------------------------
vec4 lightFragment(vec4 srcFragColor, float not_in_use_shadowFactor)
{
// Light vector (from point to light source)
vec3 L = normalize(u_ecLightPosition - v_ecPosition);
// Viewing vector (from point to eye)
// Since we are in eye space, the eye pos is at (0, 0, 0)
vec3 V = normalize(-v_ecPosition);
vec3 N = normalize(v_ecNormal);
vec3 R = normalize(reflect(-L, N));
vec3 ambient = srcFragColor.rgb*u_ambientIntensity;
vec3 diffuse = srcFragColor.rgb*(1.0 - u_ambientIntensity)*abs(dot(N, L));
vec3 specular = vec3(u_specularIntensity*pow(max(dot(R, V), 0.0), 8.0));
return vec4(ambient + diffuse + specular + u_emissiveColor, srcFragColor.a);
}

View File

@@ -1,32 +0,0 @@
varying vec3 v_ecPosition;
varying vec3 v_ecNormal;
uniform float u_specularIntensity;
//--------------------------------------------------------------------------------------------------
/// lightFragment() - Simple Headlight with specular uniform
///
/// A fixed, two sided headlight
//--------------------------------------------------------------------------------------------------
vec4 lightFragment(vec4 srcFragColor, float not_in_use_shadowFactor)
{
const vec3 ecLightPosition = vec3(0.5, 5.0, 7.0);
const float ambientIntensity = 0.2;
// Light vector (from point to light source)
vec3 L = normalize(ecLightPosition - v_ecPosition);
// Viewing vector (from point to eye)
// Since we are in eye space, the eye pos is at (0, 0, 0)
vec3 V = normalize(-v_ecPosition);
vec3 N = normalize(v_ecNormal);
vec3 R = normalize(reflect(-L, N));
vec3 ambient = srcFragColor.rgb*ambientIntensity;
vec3 diffuse = srcFragColor.rgb*(1.0 - ambientIntensity)*abs(dot(N, L));
vec3 specular = vec3(u_specularIntensity*pow(max(dot(R, V), 0.0), 8.0));
return vec4(ambient + diffuse + specular, srcFragColor.a);
}

View File

@@ -0,0 +1,18 @@
uniform vec4 u_color;
uniform vec4 u_backColor;
//--------------------------------------------------------------------------------------------------
/// srcFragment() - Single color by uniform
//--------------------------------------------------------------------------------------------------
vec4 srcFragment()
{
if (gl_FrontFacing)
{
return u_color;
}
else
{
return u_backColor;
}
}