Initial commit of ResInsight version 0.4.8

This commit is contained in:
Alf B. Rustad committed 2012-05-18 09:45:23 +02:00
1 parent a680bf941e
commit dfe97efb1b
657 files changed
+176690

No files matched your search

@@ -0,0 +1,145 @@
cmake_minimum_required(VERSION 2.8)
project(LibRender)
# Use our strict compile flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STRICT_CXX_FLAGS}")
# For now, remove pedantic flag for OSX since it clashes with glew
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
string(REPLACE "-pedantic" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
endif()
include_directories(../LibCore)
include_directories(../LibGeometry)
include_directories(glew)
set(CEE_HEADER_FILES
cvfBufferObjectManaged.h
cvfCamera.h
cvfDrawable.h
cvfDrawableGeo.h
cvfDrawableText.h
cvfDrawableVectors.h
cvfFixedAtlasFont.h
cvfFont.h
cvfFontManager.h
cvfFramebufferObject.h
cvfGeometryBuilderDrawableGeo.h
cvfGlyph.h
cvfHitDetail.h
cvfLegendScalarMapper.h
cvfLibRender.h
cvfMatrixState.h
cvfOglRc.h
cvfOpenGL.h
cvfOpenGLCapabilities.h
cvfOpenGLContext.h
cvfOpenGLContextGroup.h
cvfOpenGLResourceManager.h
cvfOpenGLTypes.h
cvfOverlayAxisCross.h
cvfOverlayColorLegend.h
cvfOverlayItem.h
cvfOverlayTextBox.h
cvfPrimitiveSet.h
cvfPrimitiveSetDirect.h
cvfPrimitiveSetIndexedUInt.h
cvfPrimitiveSetIndexedUIntScoped.h
cvfPrimitiveSetIndexedUShort.h
cvfPrimitiveSetIndexedUShortScoped.h
cvfRenderbufferObject.h
cvfRenderState.h
cvfRenderStateSet.h
cvfRenderStateTracker.h
cvfRenderState_FF.h
cvfSampler.h
cvfScalarMapper.h
cvfScalarMapperContinuousLog.h
cvfScalarMapperContinuousLinear.h
cvfScalarMapperDiscreteLinear.h
cvfScalarMapperDiscreteLog.h
cvfScalarMapperUniformLevels.h
cvfShader.h
cvfShaderProgram.h
cvfShaderProgramGenerator.h
cvfShaderSourceProvider.h
cvfShaderSourceRepository.h
cvfShaderSourceRepositoryFile.h
cvfShaderSourceStrings.h
cvfTextDrawer.h
cvfTexture.h
cvfTexture2D_FF.h
cvfTextureImage.h
cvfUniform.h
cvfUniformSet.h
cvfVertexAttribute.h
cvfVertexBundle.h
cvfViewport.h
)
set(CEE_SOURCE_FILES
cvfBufferObjectManaged.cpp
cvfCamera.cpp
cvfDrawable.cpp
cvfDrawableGeo.cpp
cvfDrawableVectors.cpp
cvfDrawableText.cpp
cvfFramebufferObject.cpp
cvfFixedAtlasFont.cpp
cvfFont.cpp
cvfFontManager.cpp
cvfGeometryBuilderDrawableGeo.cpp
cvfGlyph.cpp
cvfHitDetail.cpp
#cvfLegendScalarMapper.cpp
cvfMatrixState.cpp
cvfOglRc.cpp
cvfOpenGLCapabilities.cpp
cvfOpenGLContext.cpp
cvfOpenGLContextGroup.cpp
cvfOpenGLResourceManager.cpp
cvfOpenGL.cpp
cvfOverlayAxisCross.cpp
cvfOverlayColorLegend.cpp
cvfOverlayTextBox.cpp
cvfPrimitiveSet.cpp
cvfPrimitiveSetDirect.cpp
cvfPrimitiveSetIndexedUInt.cpp
cvfPrimitiveSetIndexedUShort.cpp
cvfPrimitiveSetIndexedUIntScoped.cpp
cvfPrimitiveSetIndexedUShortScoped.cpp
cvfRenderbufferObject.cpp
cvfRenderState.cpp
cvfRenderState_FF.cpp
cvfRenderStateSet.cpp
cvfRenderStateTracker.cpp
cvfScalarMapper.cpp
cvfScalarMapperContinuousLog.cpp
cvfScalarMapperContinuousLinear.cpp
cvfScalarMapperDiscreteLinear.cpp
cvfScalarMapperDiscreteLog.cpp
cvfScalarMapperUniformLevels.cpp
cvfSampler.cpp
cvfShader.cpp
cvfShaderSourceProvider.cpp
cvfShaderProgram.cpp
cvfShaderProgramGenerator.cpp
cvfShaderSourceRepository.cpp
cvfShaderSourceRepositoryFile.cpp
cvfTextDrawer.cpp
cvfTexture.cpp
cvfTexture2D_FF.cpp
cvfTextureImage.cpp
cvfUniform.cpp
cvfUniformSet.cpp
cvfVertexAttribute.cpp
cvfVertexBundle.cpp
cvfViewport.cpp
)
add_library(${PROJECT_NAME} ${CEE_HEADER_FILES} ${CEE_SOURCE_FILES})
@@ -0,0 +1,197 @@
//##################################################################################################
//
// 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 "cvfBufferObjectManaged.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLCapabilities.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::BufferObjectManaged
/// \ingroup Render
///
/// Class for handling OpenGL Buffer Objects managed by OpenGLResourceManager
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
BufferObjectManaged::BufferObjectManaged()
: m_target(0),
m_bufferId(0),
m_sizeInBytes(0)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
BufferObjectManaged::~BufferObjectManaged()
{
// Should already be deleted by manager through explicit call to deleteBuffer()
CVF_ASSERT(m_bufferId == 0);
}
//--------------------------------------------------------------------------------------------------
/// Static method for creating new BufferObjectManaged object instances
///
/// The function will call glGenBuffers() to create the buffer object (BO) name, and then use
/// glBufferData() to allocate memory and copy the passed data to the BO.
///
/// \return Returns NULL if an error occurred (out of memory)
//--------------------------------------------------------------------------------------------------
ref<BufferObjectManaged> BufferObjectManaged::create(OpenGLContext* oglContext, cvfGLenum target, size_t sizeInBytes, const void* data)
{
CVF_CALLSITE_OPENGL(oglContext);
OglId id = 0;
glGenBuffers(1, &id);
if (id == 0)
{
return NULL;
}
glBindBuffer(target, id);
// Allocate memory for buffer object AND copy data into it
// Currently we always use the GL_STATIC_DRAW usage hint for our buffers!
glBufferData(target, static_cast<GLsizeiptr>(sizeInBytes), data, GL_STATIC_DRAW);
// Do we want to unbind after each call?
glBindBuffer(target, 0);
// Should we always do a check here?
// Only way to detect out-of-memory issues, but not very performance friendly. Is there a better way of detecting errors for this case?
cvfGLenum err = glGetError();
if (err != GL_NO_ERROR)
{
glDeleteBuffers(1, &id);
return NULL;
}
BufferObjectManaged* bo = new BufferObjectManaged;
bo->m_target = target;
bo->m_bufferId = id;
bo->m_sizeInBytes = sizeInBytes;
return bo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool BufferObjectManaged::isUploaded() const
{
if (m_bufferId != 0)
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool BufferObjectManaged::bindBuffer(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
if (m_bufferId != 0)
{
glBindBuffer(m_target, m_bufferId);
// We can probably skip OpenGL error checking here.
// The only errors resulting from glBindBuffer relate to illegal use of target and calling between glBegin()/glEnd()
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void BufferObjectManaged::unbindBuffer(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
glBindBuffer(m_target, 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void BufferObjectManaged::unbindAllBuffers(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t BufferObjectManaged::byteCount() const
{
return m_sizeInBytes;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void BufferObjectManaged::deleteBuffer(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
if (m_bufferId != 0)
{
glDeleteBuffers(1, &m_bufferId);
m_bufferId = 0;
}
m_sizeInBytes = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool BufferObjectManaged::supportedOpenGL(OpenGLContext* oglContext)
{
// We'll require baseline support even if the actual requirement is only OpenGL 1.5
return oglContext->capabilities()->supportsOpenGL2();
}
} // namespace cvf
@@ -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 "cvfObject.h"
#include "cvfOpenGLTypes.h"
namespace cvf {
class OpenGLContext;
//==================================================================================================
//
// Class for buffer objects being managed by the OpenGLResourceManager
//
//==================================================================================================
class BufferObjectManaged : public Object
{
public:
~BufferObjectManaged();
static ref<BufferObjectManaged> create(OpenGLContext* oglContext, cvfGLenum target, size_t sizeInBytes, const void* data);
bool isUploaded() const;
bool bindBuffer(OpenGLContext* oglContext) const;
void unbindBuffer(OpenGLContext* oglContext) const;
static void unbindAllBuffers(OpenGLContext* oglContext);
size_t byteCount() const;
void deleteBuffer(OpenGLContext* oglContext);
static bool supportedOpenGL(OpenGLContext* oglContext);
private:
BufferObjectManaged();
private:
cvfGLenum m_target; // The target to which the buffer object will be bound (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, etc)
OglId m_bufferId; // The id (OpenGL name of the buffer object)
size_t m_sizeInBytes; // Size of buffer in bytes
};
}
@@ -0,0 +1,906 @@
//##################################################################################################
//
// 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 "cvfCamera.h"
#include "cvfOpenGL.h"
#include "cvfRay.h"
#include "cvfViewport.h"
#include "cvfBoundingBox.h"
#include "cvfGeometryUtils.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Camera
/// \ingroup Render
///
/// A Camera defines a view matrix (viewpoint) and a projection matrix
///
/// The camera stores and applies the view matrix and the projection matrix to OpenGL. A camera
/// has a reference to a Viewport that is associated with the camera. The camera needs the viewport
/// to be able to setup the projection matrix.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Camera::Camera()
: m_projectionType(PERSPECTIVE),
m_fieldOfViewYDeg(40.0),
m_frontPlaneFrustumHeight(0),
m_nearPlane(0.05),
m_farPlane(10000.0),
m_cachedFrontPlanePixelHeight(0)
{
m_viewport = new Viewport;
// Default perspective projection. This will update the cached values
setProjectionAsPerspective(m_fieldOfViewYDeg, m_nearPlane, m_farPlane);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Camera::~Camera()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
/// The Camera's view matrix.
///
/// This is what you would pass to OpenGL with:
/// \code
/// glMatrixMode(GL_MODELVIEW);
/// glLoadMatrix(camera.viewMatrix().ptr());
/// \endcode
//--------------------------------------------------------------------------------------------------
void Camera::setViewMatrix(const Mat4d& mat)
{
m_viewMatrix = mat;
updateCachedValues();
}
//--------------------------------------------------------------------------------------------------
/// Set the view matrix from the standard OpenGL lookat specification.
///
/// View direction will be (center - eye). Center is not stored in this class.
//--------------------------------------------------------------------------------------------------
void Camera::setFromLookAt(const Vec3d& eye, const Vec3d& center, const Vec3d& up)
{
Mat4d invViewMatrix = createLookAtMatrix(eye, center, up);
m_viewMatrix = invViewMatrix.getInverted();
updateCachedValues();
}
//--------------------------------------------------------------------------------------------------
/// Get the eye point, vrp and up vector. Params can be NULL if not needed.
//--------------------------------------------------------------------------------------------------
void Camera::toLookAt(Vec3d* eye, Vec3d* vrp, Vec3d* up) const
{
Vec3d vEye(0, 0, 0);
Vec3d vVrp(0, 0, -1);
Vec3d vUp(0, 1, 0);
vEye.transformPoint(m_cachedInvertedViewMatrix);
vVrp.transformPoint(m_cachedInvertedViewMatrix);
vUp.transformVector(m_cachedInvertedViewMatrix);
if (eye) *eye = vEye;
if (vrp) *vrp = vVrp;
if (up) *up = vUp;
}
//--------------------------------------------------------------------------------------------------
/// Retrieves the camera's position (eye point)
//--------------------------------------------------------------------------------------------------
Vec3d Camera::position() const
{
Vec3d pos(0, 0, 0);
pos.transformPoint(m_cachedInvertedViewMatrix);
return pos;
}
//--------------------------------------------------------------------------------------------------
/// Get the camera's forward direction vector. Vector is normalized
//--------------------------------------------------------------------------------------------------
Vec3d Camera::direction() const
{
Vec3d dir(0, 0, -1.0);
dir.transformVector(m_cachedInvertedViewMatrix);
return dir;
}
//--------------------------------------------------------------------------------------------------
/// Get the camera's up vector. Vector is normalized
//--------------------------------------------------------------------------------------------------
Vec3d Camera::up() const
{
Vec3d up(0, 1.0, 0);
up.transformVector(m_cachedInvertedViewMatrix);
return up;
}
//--------------------------------------------------------------------------------------------------
/// Get the camera's right vector. Vector is normalized
//--------------------------------------------------------------------------------------------------
Vec3d Camera::right() const
{
Vec3d right(1.0, 0, 0);
right.transformVector(m_cachedInvertedViewMatrix);
return right;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Camera::ProjectionType Camera::projection() const
{
return m_projectionType;
}
//--------------------------------------------------------------------------------------------------
/// Setup a perspective projection.
///
/// The fieldOfViewYDeg parameter is the total field of view angle (in degrees) in the Y direction.
/// Works similar to gluPerspective().
//--------------------------------------------------------------------------------------------------
void Camera::setProjectionAsPerspective(double fieldOfViewYDeg, double nearPlane, double farPlane)
{
CVF_ASSERT(fieldOfViewYDeg > 0 && fieldOfViewYDeg < 180);
CVF_ASSERT(nearPlane > 0);
CVF_ASSERT(farPlane > nearPlane);
m_projectionType = PERSPECTIVE;
m_fieldOfViewYDeg = fieldOfViewYDeg;
m_nearPlane = nearPlane;
m_farPlane = farPlane;
m_frontPlaneFrustumHeight = 2*m_nearPlane*Math::tan(Math::toRadians(m_fieldOfViewYDeg/2.0));
m_projectionMatrix = createPerspectiveMatrix(Math::toRadians(m_fieldOfViewYDeg), aspectRatio(), m_nearPlane, m_farPlane);
updateCachedValues();
}
//--------------------------------------------------------------------------------------------------
/// Setup an orthographic projection
///
/// This works similar to glOrtho().
//--------------------------------------------------------------------------------------------------
void Camera::setProjectionAsOrtho(double height, double nearPlane, double farPlane)
{
CVF_ASSERT(height > 0);
double width = height * aspectRatio();
m_projectionType = ORTHO;
m_fieldOfViewYDeg = UNDEFINED_DOUBLE;
m_frontPlaneFrustumHeight = height;
m_nearPlane = nearPlane;
m_farPlane = farPlane;
m_projectionMatrix = createOrthoMatrix(-width/2.0, width/2.0, -height/2.0, height/2.0, m_nearPlane, m_farPlane);
updateCachedValues();
}
//--------------------------------------------------------------------------------------------------
/// Setup an orthographic projection
///
/// This works similar to glOrtho().
//--------------------------------------------------------------------------------------------------
void Camera::setProjectionAsUnitOrtho()
{
m_projectionType = ORTHO;
m_fieldOfViewYDeg = UNDEFINED_DOUBLE;
m_frontPlaneFrustumHeight = 1;
m_nearPlane = -1.0;
m_farPlane = 1.0;
m_projectionMatrix = createOrthoMatrix(0.0, 1.0, 0.0, 1.0, m_nearPlane, m_farPlane);
updateCachedValues();
}
//--------------------------------------------------------------------------------------------------
/// Setup a pixel exact two-dimensional orthographic viewing region
///
/// Sets a 2D projection where each unit corresponds to a pixel.
//--------------------------------------------------------------------------------------------------
void Camera::setProjectionAsPixelExact2D()
{
m_projectionType = ORTHO;
m_fieldOfViewYDeg = UNDEFINED_DOUBLE;
m_frontPlaneFrustumHeight = m_viewport->height();
m_nearPlane = -1.0;
m_farPlane = 1.0;
m_projectionMatrix = createOrthoMatrix(0, m_viewport->width(), 0, m_viewport->height(), m_nearPlane, m_farPlane);
updateCachedValues();
}
//--------------------------------------------------------------------------------------------------
/// Setup the view to contain the passed bounding box, with the camera looking from the given
/// direction (dir) and with the given up vector (up).
///
/// The passed boundingBox should be the bounding box of the object/model you would like to fit
/// 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)
{
double boxRadius = boundingBox.radius();
// Determine needed distance from center of model to eye point
double fovY = m_fieldOfViewYDeg;
double fovX = m_fieldOfViewYDeg*aspectRatio();
// The return values are the complete angle in degrees, get half in radians
fovX = Math::toRadians(fovX/2);
fovY = Math::toRadians(fovY/2);
// Use the largest distance
double dist1 = (fovX != 0) ? boxRadius*relativeDistance/Math::sin(fovX) : -1;
double dist2 = (fovY != 0) ? boxRadius*relativeDistance/Math::sin(fovY) : -1;
double dist = CVF_MAX(dist1, dist2);
// Avoid distances of 0 when model has no extent
if (!(dist > 0))
{
dist = 1.0;
}
// Use old view direction, but look towards model center
Vec3d eye = boundingBox.center()- dir*dist;
// Will update cached values
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)
{
CVF_ASSERT(minNearPlaneDistance > 0);
Vec3d eye, vrp, up;
toLookAt(&eye, &vrp, &up);
Vec3d viewdir = (vrp - eye).getNormalized();
double distEyeBoxCenterAlongViewDir = (boundingBox.center() - eye)*viewdir;
double nearPlane = distEyeBoxCenterAlongViewDir - boundingBox.radius();
double farPlane = distEyeBoxCenterAlongViewDir + boundingBox.radius();
if (nearPlane < minNearPlaneDistance) nearPlane = minNearPlaneDistance;
if (farPlane <= nearPlane) farPlane = nearPlane + 1.0;
setProjectionAsPerspective(m_fieldOfViewYDeg, nearPlane, farPlane);
}
//--------------------------------------------------------------------------------------------------
/// Returns the current view matrix
//--------------------------------------------------------------------------------------------------
const Mat4d& Camera::viewMatrix() const
{
return m_viewMatrix;
}
//--------------------------------------------------------------------------------------------------
/// Returns the inverted current view matrix
///
/// The inverted view matrix is cached for performance reasons.
//--------------------------------------------------------------------------------------------------
const Mat4d& Camera::invertedViewMatrix() const
{
return m_cachedInvertedViewMatrix;
}
//--------------------------------------------------------------------------------------------------
/// Returns the current projection matrix
//--------------------------------------------------------------------------------------------------
const Mat4d& Camera::projectionMatrix() const
{
return m_projectionMatrix;
}
//--------------------------------------------------------------------------------------------------
/// Returns the total field of view in Y direction in degrees.
///
/// If projection is orthographic, this function will return UNDEFINED_DOUBLE
//--------------------------------------------------------------------------------------------------
double Camera::fieldOfViewYDeg() const
{
return m_fieldOfViewYDeg;
}
//--------------------------------------------------------------------------------------------------
/// Returns the near clipping plane
//--------------------------------------------------------------------------------------------------
double Camera::nearPlane() const
{
return m_nearPlane;
}
//--------------------------------------------------------------------------------------------------
/// Returns the far clipping plane
//--------------------------------------------------------------------------------------------------
double Camera::farPlane()const
{
return m_farPlane;
}
//--------------------------------------------------------------------------------------------------
/// Returns the aspect ratio (width / height) of the corresponding viewport.
//--------------------------------------------------------------------------------------------------
double Camera::aspectRatio() const
{
CVF_ASSERT(m_viewport.notNull());
return viewport()->aspectRatio();
}
//--------------------------------------------------------------------------------------------------
/// Specify the position and dimensions of the viewport, and update the projection matrix.
///
/// This method calls Viewport::set() and then updates the projection matrix, as this is depending
/// on the viewport dimensions.
/// This method is usually used as a response to a Resize message from the window system
//--------------------------------------------------------------------------------------------------
void Camera::setViewport(uint x, uint y, uint width, uint height)
{
CVF_ASSERT(m_viewport.notNull());
m_viewport->set(x, y, width, height);
// Update projection:
if (m_projectionType == PERSPECTIVE)
{
setProjectionAsPerspective(m_fieldOfViewYDeg, m_nearPlane, m_farPlane);
}
else if (m_projectionType == ORTHO)
{
setProjectionAsOrtho(m_frontPlaneFrustumHeight, m_nearPlane, m_farPlane);
}
}
//--------------------------------------------------------------------------------------------------
/// Get the viewport used by this camera.
//--------------------------------------------------------------------------------------------------
Viewport* Camera::viewport()
{
return m_viewport.p();
}
//--------------------------------------------------------------------------------------------------
/// Get the viewport used by this camera.
//--------------------------------------------------------------------------------------------------
const Viewport* Camera::viewport() const
{
return m_viewport.p();
}
//--------------------------------------------------------------------------------------------------
/// Create a Ray from window coordinates
///
/// The coordinates (winCoordX & winCoordY) are assumed to be in the window coordinate system
/// where <0,0> if in the top left corner.
//--------------------------------------------------------------------------------------------------
ref<Ray> Camera::rayFromWinCoord(int winCoordX, int winCoordY) const
{
// Unproject works in OpenGL coord system with (0,0) in lower left corner, so flip the y-coordinate
winCoordY = static_cast<int>(m_viewport->height()) - winCoordY;
Vec3d coord0(0, 0, 0);
if (!unproject(Vec3d(static_cast<double>(winCoordX), static_cast<double>(winCoordY), 0), &coord0))
{
return NULL;
}
Vec3d coord1(0, 0, 0);
if (!unproject(Vec3d(static_cast<double>(winCoordX), static_cast<double>(winCoordY), 1), &coord1))
{
return NULL;
}
Ray* ray = new Ray;
ray->setOrigin(coord0);
Vec3d dir = (coord1 - coord0).getNormalized();
ray->setDirection(dir);
return ray;
}
//--------------------------------------------------------------------------------------------------
/// Computes the maximum pixel area that the projected bounding box will occupy with the current camera settings.
///
/// The current implementation gives the area of the 2D bounding box of the projected corners of the
/// 3D bounding box, this not exact but at least >=
//--------------------------------------------------------------------------------------------------
double Camera::computeProjectedBoundingBoxPixelArea(const BoundingBox& box) const
{
Vec3d corner[8];
box.cornerVertices(corner);
BoundingBox projBB;
// project the 8 corners in the viewport
int i;
for (i = 0; i < 8; i++)
{
Vec3d v;
if (project(corner[i], &v))
{
projBB.add(v);
}
}
Vec3d extent = projBB.extent();
double pixels = extent.x() * extent.y();
return pixels;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Camera::computeProjectedBoundingSpherePixelArea(const Vec3d& center, double radius) const
{
if (m_cachedFrontPlanePixelHeight > 0)
{
Vec3d currentEye = position();
double eyeDist = (currentEye - center).length();
if (eyeDist > 0)
{
double radiusNearWorld = ((m_nearPlane*radius)/eyeDist);
double pixels = radiusNearWorld/m_cachedFrontPlanePixelHeight;
return PI_D*pixels*pixels;
}
else
{
// We should be returning a large value here, right?
return std::numeric_limits<double>::max();
}
}
else
{
return 0;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Camera::isProjectedBoundingBoxLessThanThreshold(const BoundingBox& box, double pixelThreshold) const
{
Vec3d currentEye = position();
double l2Dist = (currentEye - box.center()).lengthSquared();
double thresholdDist = distanceWhereObjectProjectsToPixelExtent(2*box.radius(), pixelThreshold) + box.radius();
if (l2Dist > thresholdDist*thresholdDist)
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
/// Get height of the view frustum in the front plane in world coordinates
//--------------------------------------------------------------------------------------------------
double Camera::frontPlaneFrustumHeight() const
{
return m_frontPlaneFrustumHeight;
}
//--------------------------------------------------------------------------------------------------
/// Get the height of a pixel in the front plane in world coordinates
///
/// This value is cached for performance reasons.
//--------------------------------------------------------------------------------------------------
double Camera::frontPlanePixelHeight() const
{
return m_cachedFrontPlanePixelHeight;
}
//--------------------------------------------------------------------------------------------------
/// Get the distance to where the object with the given extent projected onto the front clipping plane
/// would have the specified pixel extent.
///
/// \param objectExtentWorld The largest object extent in world coordinates
/// \param objectExtentPixels The requested pixel extent in the front clipping plane
//--------------------------------------------------------------------------------------------------
double Camera::distanceWhereObjectProjectsToPixelExtent(double objectExtentWorld, double objectExtentPixels) const
{
CVF_ASSERT(objectExtentPixels > 0);
if (m_cachedFrontPlanePixelHeight > 0)
{
double distance = (objectExtentWorld*m_nearPlane)/(m_cachedFrontPlanePixelHeight*objectExtentPixels);
return distance;
}
else
{
return 0;
}
}
//--------------------------------------------------------------------------------------------------
/// OpenGL like unproject.
///
/// The input (window) coordinates \a coord must be specified in OpenGL style coordinates, which means
/// a right handed coordinate system with the origin in the lower left corner of the window.
//--------------------------------------------------------------------------------------------------
bool Camera::unproject(const Vec3d& coord, Vec3d* out) const
{
CVF_ASSERT(out);
Vec4d v(coord, 1.0);
// map from viewport to 0-1
v.x() = (v.x() - m_viewport->x()) / m_viewport->width();
v.y() = (v.y() - m_viewport->y()) / m_viewport->height();
// map to range -1 to 1
v.x() = v.x() * 2.0f - 1.0f;
v.y() = v.y() * 2.0f - 1.0f;
v.z() = v.z() * 2.0f - 1.0f;
bool invertible=true;
Mat4d inverse = m_cachedProjectionMultViewMatrix.getInverted(&invertible);
if (!invertible)
{
return false;
}
v = inverse * v;
if (v.w() == 0.0)
{
return false;
}
out->x() = v.x() / v.w();
out->y() = v.y() / v.w();
out->z() = v.z() / v.w();
return true;
}
//--------------------------------------------------------------------------------------------------
/// Maps object coordinates to window coordinates
///
/// The returned window coordinates \a out are in OpenGL style coordinates, which means a right handed
/// coordinate system with the origin in the lower left corner of the window.
//--------------------------------------------------------------------------------------------------
bool Camera::project(const Vec3d& point, Vec3d* out) const
{
return GeometryUtils::project(m_cachedProjectionMultViewMatrix, Vec2ui(m_viewport->x(), m_viewport->y()), Vec2ui(m_viewport->width(), m_viewport->height()), point, out);
}
//--------------------------------------------------------------------------------------------------
/// Get camera's Frustum. Planes have an inward pointing normal
///
/// \sa
/// computeViewFrustum()
//--------------------------------------------------------------------------------------------------
Frustum Camera::frustum() const
{
return m_cachedViewFrustum;
}
//--------------------------------------------------------------------------------------------------
/// Update the various cached variables stored in the view.
///
/// This needs to be called whenever one of the following items are updated:
/// - View matrix
/// - Projection matrix
/// - Clip planes
/// - Viewport dimensions (NB!), as this could be done directly in cvf::Viewport
///
/// The following values are cached:
/// - m_cachedInvertedViewMatrix
/// - m_cachedProjectionMultViewMatrix
/// - m_cachedViewFrustum
/// - m_cachedFrontPlanePixelSize
//--------------------------------------------------------------------------------------------------
void Camera::updateCachedValues()
{
// Update cached matrices
m_cachedProjectionMultViewMatrix = m_projectionMatrix * m_viewMatrix;
m_cachedInvertedViewMatrix = m_viewMatrix.getInverted();
// Update the cached frustum
m_cachedViewFrustum = computeViewFrustum();
m_cachedViewFrustum.isOutside(Vec3d(0,0,0));
// Update the front plane pixel size (height)
CVF_ASSERT(m_viewport.notNull());
uint vpWidth = m_viewport->width();
uint vpHeight = m_viewport->height();
if (vpWidth > 0 && vpHeight > 0)
{
// The height/size of a pixel in the front clipping plane
m_cachedFrontPlanePixelHeight = m_frontPlaneFrustumHeight/vpHeight;
}
else
{
// Technically we could compute a pixel height as long as the viewport height is non-zero,
// but considering normal usage of the pixel height it makes sense to only compute it
// when the viewport area is non-zero
m_cachedFrontPlanePixelHeight = 0;
}
}
//--------------------------------------------------------------------------------------------------
/// Get camera's Frustum. Planes have an inward pointing normal
//--------------------------------------------------------------------------------------------------
Frustum Camera::computeViewFrustum() const
{
// See also
// http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf
// http://zach.in.tu-clausthal.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
Frustum f;
const Mat4d& m = m_cachedProjectionMultViewMatrix;
Plane left = Plane(m.rowCol(3, 0) + m.rowCol(0, 0),
m.rowCol(3, 1) + m.rowCol(0, 1),
m.rowCol(3, 2) + m.rowCol(0, 2),
m.rowCol(3, 3) + m.rowCol(0, 3));
Plane right = Plane(m.rowCol(3, 0) - m.rowCol(0, 0),
m.rowCol(3, 1) - m.rowCol(0, 1),
m.rowCol(3, 2) - m.rowCol(0, 2),
m.rowCol(3, 3) - m.rowCol(0, 3));
Plane bot = Plane(m.rowCol(3, 0) + m.rowCol(1, 0),
m.rowCol(3, 1) + m.rowCol(1, 1),
m.rowCol(3, 2) + m.rowCol(1, 2),
m.rowCol(3, 3) + m.rowCol(1, 3));
Plane top = Plane(m.rowCol(3, 0) - m.rowCol(1, 0),
m.rowCol(3, 1) - m.rowCol(1, 1),
m.rowCol(3, 2) - m.rowCol(1, 2),
m.rowCol(3, 3) - m.rowCol(1, 3));
Plane front = Plane(m.rowCol(3, 0) + m.rowCol(2, 0),
m.rowCol(3, 1) + m.rowCol(2, 1),
m.rowCol(3, 2) + m.rowCol(2, 2),
m.rowCol(3, 3) + m.rowCol(2, 3));
Plane back = Plane(m.rowCol(3, 0) - m.rowCol(2, 0),
m.rowCol(3, 1) - m.rowCol(2, 1),
m.rowCol(3, 2) - m.rowCol(2, 2),
m.rowCol(3, 3) - m.rowCol(2, 3));
// Assign planes if all are valid
if (left.isValid() && right.isValid() && top.isValid() && bot.isValid() && front.isValid() && back.isValid())
{
// Left clipping plane
f.setPlane(Frustum::LEFT, left);
// Right clipping plane
f.setPlane(Frustum::RIGHT, right);
// Top clipping plane
f.setPlane(Frustum::TOP, top);
// Bottom clipping plane
f.setPlane(Frustum::BOTTOM, bot);
// Near clipping plane
f.setPlane(Frustum::FRONT, front);
// Far clipping plane
f.setPlane(Frustum::BACK, back);
}
return f;
}
//--------------------------------------------------------------------------------------------------
/// Helper class to compute the projection matrix based on the given view frustum
//--------------------------------------------------------------------------------------------------
Mat4d Camera::createFrustumMatrix(double left, double right, double bottom, double top, double zNear, double zFar)
{
Matrix4<double> m;
if (zNear <= 0 || zFar <= 0 || zNear == zFar || left == right || top == bottom)
{
return Mat4d::ZERO;
}
double x = (2.0 * zNear) / (right - left);
double y = (2.0 * zNear) / (top - bottom);
double a = (right + left) / (right - left);
double b = (top + bottom) / (top - bottom);
double c = -(zFar + zNear) / (zFar - zNear);
double d = -(2.0 * zFar * zNear) / (zFar - zNear);
m.setRowCol(0, 0, x); m.setRowCol(0, 1, 0); m.setRowCol(0, 2, a); m.setRowCol(0, 3, 0);
m.setRowCol(1, 0, 0); m.setRowCol(1, 1, y); m.setRowCol(1, 2, b); m.setRowCol(1, 3, 0);
m.setRowCol(2, 0, 0); m.setRowCol(2, 1, 0); m.setRowCol(2, 2, c); m.setRowCol(2, 3, d);
m.setRowCol(3, 0, 0); m.setRowCol(3, 1, 0); m.setRowCol(3, 2, -1.0); m.setRowCol(3, 3, 0);
return m;
}
//--------------------------------------------------------------------------------------------------
/// Helper class to create a perspective projection matrix
//--------------------------------------------------------------------------------------------------
Mat4d Camera::createPerspectiveMatrix(double fovy, double aspect_ratio, double znear, double zfar)
{
Mat4d m;
double rads = fovy / 2.0;
double dz = zfar - znear;
double sa = Math::sin(rads);
if ((dz == 0) || (sa == 0) || (aspect_ratio == 0))
{
return Mat4d::ZERO;
}
double ctan = Math::cos(rads) / sa;
m.setRowCol(0,0, ctan / aspect_ratio);
m.setRowCol(1,1, ctan);
m.setRowCol(2,2, -(zfar + znear)/dz);
m.setRowCol(2,3, -(2.0*znear* zfar)/dz);
m.setRowCol(3,2, -1.0);
m.setRowCol(3,3, 0);
// A (0,2) and B (1,2) are zero due to the frustum being symmetrical around zero
return m;
}
//--------------------------------------------------------------------------------------------------
/// Helper class to create a orthographic projection matrix
//--------------------------------------------------------------------------------------------------
Mat4d Camera::createOrthoMatrix(double left, double right, double bottom, double top, double nearPlane, double farPlane)
{
Mat4d m;
m.setRowCol(0,0, 2.0 / (right - left));
m.setRowCol(0,1, 0);
m.setRowCol(0,2, 0);
m.setRowCol(0,3, -(right + left) / (right - left));
m.setRowCol(1,0, 0);
m.setRowCol(1,1, 2.0 / (top-bottom));
m.setRowCol(1,2, 0);
m.setRowCol(1,3, -(top + bottom) / (top - bottom));
m.setRowCol(2,0, 0);
m.setRowCol(2,1, 0);
m.setRowCol(2,2, -2.0 / (farPlane - nearPlane));
m.setRowCol(2,3, -(farPlane + nearPlane) / (farPlane-nearPlane));
m.setRowCol(3,0, 0);
m.setRowCol(3,1, 0);
m.setRowCol(3,2, 0);
m.setRowCol(3,3, 1.0);
return m;
}
//--------------------------------------------------------------------------------------------------
/// Helper class to create a view matrix from an OpenGL "lookat" specification
//--------------------------------------------------------------------------------------------------
Mat4d Camera::createLookAtMatrix(Vec3d eye, Vec3d vrp, Vec3d up)
{
Vec3d y = up.getNormalized();
Vec3d z = (eye - vrp).getNormalized(); // == -(vrp-eye)
Vec3d x = (y^z).getNormalized();
y = (z^x).getNormalized();
Mat4d m;
m.setRowCol(0, 0, x.x()); m.setRowCol(0, 1, y.x()); m.setRowCol(0, 2, z.x()); m.setRowCol(0, 3, eye.x());
m.setRowCol(1, 0, x.y()); m.setRowCol(1, 1, y.y()); m.setRowCol(1, 2, z.y()); m.setRowCol(1, 3, eye.y());
m.setRowCol(2, 0, x.z()); m.setRowCol(2, 1, y.z()); m.setRowCol(2, 2, z.z()); m.setRowCol(2, 3, eye.z());
m.setRowCol(3, 0, 0); m.setRowCol(3, 1, 0); m.setRowCol(3, 2, 0); m.setRowCol(3, 3, 1);
return m;
}
//--------------------------------------------------------------------------------------------------
/// Apply the camera settings to OpenGL. Note that the Viewport settings are not applied
//--------------------------------------------------------------------------------------------------
void Camera::applyOpenGL() const
{
#ifndef CVF_OPENGL_ES
// apply the projection matrix
glMatrixMode(GL_PROJECTION);
glLoadMatrixd(m_projectionMatrix.ptr());
// apply the view matrix
glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(viewMatrix().ptr());
#endif
}
} // namespace cvf
+125
View File
@@ -0,0 +1,125 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfMatrix4.h"
#include "cvfFrustum.h"
namespace cvf {
class BoundingBox;
class Viewport;
class Ray;
//==================================================================================================
//
// A camera defines the view point, view direction and the up vector
//
//==================================================================================================
class Camera : public Object
{
public:
enum ProjectionType
{
PERSPECTIVE, ///< Perspective projection
ORTHO ///< Orthographic (parallel) projection
};
public:
Camera();
~Camera();
void setViewMatrix(const Mat4d& mat);
void setFromLookAt(const Vec3d& eye, const Vec3d& vrp, const Vec3d& up);
void toLookAt(Vec3d* eye, Vec3d* vrp, Vec3d* up) const;
Vec3d position() const;
Vec3d direction() const;
Vec3d up() const;
Vec3d right() const;
ProjectionType projection() const;
void setProjectionAsPerspective(double fieldOfViewYDeg, double nearPlane, double farPlane);
void setProjectionAsOrtho(double height, double nearPlane, double farPlane);
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);
const Mat4d& viewMatrix() const;
const Mat4d& invertedViewMatrix() const;
const Mat4d& projectionMatrix() const;
double fieldOfViewYDeg() const;
double nearPlane() const;
double farPlane()const;
double aspectRatio() const;
double frontPlaneFrustumHeight() const;
double frontPlanePixelHeight() const;
double distanceWhereObjectProjectsToPixelExtent(double objectExtentWorld, double objectExtentPixels) const;
void setViewport(uint x, uint y, uint width, uint height);
Viewport* viewport();
const Viewport* viewport() const;
ref<Ray> rayFromWinCoord(int winCoordX, int winCoordY) const;
bool unproject(const Vec3d& coord, Vec3d* out) const;
bool project(const Vec3d& point, Vec3d* out) const;
double computeProjectedBoundingBoxPixelArea(const BoundingBox& box) const;
double computeProjectedBoundingSpherePixelArea(const Vec3d& center, double radius) const;
bool isProjectedBoundingBoxLessThanThreshold(const BoundingBox& box, double pixelThreshold) const;
Frustum frustum() const;
void applyOpenGL() const;
private:
void updateCachedValues();
Frustum computeViewFrustum() const;
static Mat4d createFrustumMatrix(double left, double right, double bottom, double top, double zNear, double zFar);
static Mat4d createPerspectiveMatrix(double fovy, double aspect_ratio, double znear, double zfar);
static Mat4d createOrthoMatrix(double left, double right, double bottom, double top, double near, double far);
static Mat4d createLookAtMatrix(Vec3d eye, Vec3d vrp, Vec3d up);
private:
Mat4d m_viewMatrix;
Mat4d m_cachedInvertedViewMatrix; // Cached inverted version of the m_viewMatrix
Mat4d m_projectionMatrix;
Mat4d m_cachedProjectionMultViewMatrix; // Caching projMat*viewMat, as this is used in many tight loops (eps. computeBoundingBoxPixelSize)
ProjectionType m_projectionType;
double m_fieldOfViewYDeg; // Stored for perspective projection
double m_frontPlaneFrustumHeight; // Height of view frustum in the front plane
double m_nearPlane;
double m_farPlane;
ref<Viewport> m_viewport;
double m_cachedFrontPlanePixelHeight; // Height of a pixel in the front clipping plane given in world coordinates
Frustum m_cachedViewFrustum;
};
}
@@ -0,0 +1,76 @@
//##################################################################################################
//
// 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 "cvfDrawable.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Drawable
/// \ingroup Render
///
/// Drawable is the base class for drawable items in a part. A part has one drawable for each lod level.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Drawable::Drawable()
{
}
//--------------------------------------------------------------------------------------------------
/// \fn virtual size_t Drawable::vertexCount() const = 0;
///
/// Get the number of vertices (nodes, points) in the drawable
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
/// \fn virtual size_t Drawable::triangleCount() const = 0;
///
/// Get the number of triangles in the drawable. A quad is not 2 triangles.
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
/// \fn virtual size_t Drawable::faceCount() const = 0;
///
/// Get the total number of OpenGL primitives (sum of lines, points, quads, etc.)
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
/// \fn virtual bool Drawable::rayIntersect(const Ray& ray, Vec3d* intersectionPoint) const = 0;
///
/// Intersect the drawable with the ray and return the closest intersection point.
///
/// Returns true if anything was hit.
//--------------------------------------------------------------------------------------------------
} // namespace cvf
@@ -0,0 +1,63 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfVector3.h"
namespace cvf {
class BoundingBox;
class Ray;
class OpenGLResourceManager;
class ShaderProgram;
class MatrixState;
class HitDetail;
class OpenGLContext;
//==================================================================================================
//
// Drawable is the base class for drawable items in a part.
//
//==================================================================================================
class Drawable : public Object
{
public:
Drawable();
virtual void render(OpenGLContext* oglContext, ShaderProgram* shaderProgram, const MatrixState& matrixState) = 0;
virtual void renderFixedFunction(OpenGLContext* oglContext, const MatrixState& matrixState) = 0;
virtual void renderImmediateMode(OpenGLContext* oglContext, const MatrixState& matrixState) = 0;
virtual void createUploadBufferObjectsGPU(OpenGLContext* oglContext) = 0;
virtual void releaseBufferObjectsGPU() = 0;
virtual size_t vertexCount() const = 0;
virtual size_t triangleCount() const = 0;
virtual size_t faceCount() const = 0;
virtual BoundingBox boundingBox() const = 0;
virtual bool rayIntersectCreateDetail(const Ray& ray, Vec3d* intersectionPoint, ref<HitDetail>* hitDetail) const = 0;
};
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,136 @@
//##################################################################################################
//
// 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 "cvfDrawable.h"
#include "cvfArray.h"
#include "cvfMatrix4.h"
#include "cvfBoundingBox.h"
#include "cvfCollection.h"
#include "cvfHitDetail.h"
namespace cvf {
class VertexBundle;
class VertexAttribute;
class PrimitiveSet;
//==================================================================================================
//
// A polygon based drawable
//
//==================================================================================================
class DrawableGeo : public Drawable
{
public:
enum RenderMode
{
VERTEX_ARRAY, ///< Rendering using client vertex arrays (copy arrays from client memory to graphics memory on each draw)
BUFFER_OBJECT ///< Rendering using buffer objects (arrays stored in graphics memory)
};
public:
DrawableGeo();
virtual ~DrawableGeo();
ref<DrawableGeo> shallowCopy() const;
virtual void render(OpenGLContext* oglContext, ShaderProgram* shaderProgram, const MatrixState& matrixState);
virtual void renderFixedFunction(OpenGLContext* oglContext, const MatrixState& matrixState);
virtual void renderImmediateMode(OpenGLContext* oglContext, const MatrixState& matrixState);
virtual void createUploadBufferObjectsGPU(OpenGLContext* oglContext);
virtual void releaseBufferObjectsGPU();
virtual size_t vertexCount() const;
virtual size_t triangleCount() const;
virtual size_t faceCount() const;
void setRenderMode(RenderMode renderMode);
RenderMode renderMode() const;
void setVertexArray(Vec3fArray* vertexArray);
void setNormalArray(Vec3fArray* normalArray);
void setColorArray(Color3ubArray* colorArray);
const Vec3fArray* vertexArray() const;
const Vec3fArray* normalArray() const;
void setTextureCoordArray(Vec2fArray* textureCoordArray);
const Vec2fArray* textureCoordArray() const;
void setVertexAttribute(VertexAttribute* vertexAttrib);
size_t primitiveSetCount() const;
void addPrimitiveSet(PrimitiveSet* primitiveSet);
const PrimitiveSet* primitiveSet(size_t index) const;
PrimitiveSet* primitiveSet(size_t index);
int convertFromUIntToUShort();
void getFaceIndices(size_t indexOfFace, UIntArray* indices) const;
void setFromFaceList(const UIntArray& faceList);
ref<UIntArray> toFaceList() const;
void setFromTriangleVertexArray(Vec3fArray* vertexArray);
void setFromQuadVertexArray(Vec3fArray* vertexArray);
void weldVertices(double weldDistance);
void mergeInto(const Collection<DrawableGeo>& drawableGeos);
void mergeInto(const DrawableGeo& drawableGeo, const Mat4d* transformation);
void transform(const Mat4d& transformation);
void computeNormals();
virtual BoundingBox boundingBox() const;
void recomputeBoundingBox();
bool rayIntersect(const Ray& ray, Vec3d* intersectionPoint, uint* faceHit) const;
bool rayIntersect(const Ray& ray, Vec3dArray* intersectionPoints, UIntArray* facesHit) const;
virtual bool rayIntersectCreateDetail(const Ray& ray, Vec3d* intersectionPoint, ref<HitDetail>* hitDetail) const;
private:
ref<VertexBundle> m_vertexBundle; // Contains all the per-vertex data, both fixed attributes such as vertices and normals and generic attributes. Bundle always exists.
Collection<PrimitiveSet> m_primitiveSets; // Collection of primitive sets with the connectivity indices
BoundingBox m_boundingBox; // Computed bounding box
RenderMode m_renderMode; // Render using client memory or buffer objects?
};
//==================================================================================================
//
//
//
//==================================================================================================
class HitDetailDrawableGeo : public HitDetail
{
public:
HitDetailDrawableGeo(uint faceIndex);
uint faceIndex() const;
private:
uint m_faceIndex; // Index of the face that was hit
};
}
@@ -0,0 +1,423 @@
//##################################################################################################
//
// 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 "cvfDrawableText.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfBufferObjectManaged.h"
#include "cvfDrawableGeo.h"
#include "cvfQuat.h"
#include "cvfUniform.h"
#include "cvfRay.h"
#include "cvfFont.h"
#include "cvfGlyph.h"
#include "cvfCamera.h"
#include "cvfShaderProgram.h"
#include "cvfRenderState.h"
#include "cvfViewport.h"
#include "cvfGeometryUtils.h"
#include "cvfMatrixState.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#endif
namespace cvf {
//==================================================================================================
///
/// \class cvf::DrawableText
/// \ingroup Render
///
/// DrawableText implements drawing of text strings in 2D space.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
DrawableText::DrawableText()
: m_verticalAlignment(TextDrawer::BASELINE),
m_textColor(Color3::BLACK),
m_backgroundColor(1.0f, 1.0f, 0.8f),
m_borderColor(Color3::BLACK),
m_drawBackground(true),
m_drawBorder(true),
m_checkPosVisible(true)
{
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
DrawableText::~DrawableText()
{
}
//--------------------------------------------------------------------------------------------------
/// Set font to be used for drawing text
//--------------------------------------------------------------------------------------------------
void DrawableText::setFont(Font* font)
{
m_font = font;
}
//--------------------------------------------------------------------------------------------------
/// Get font used to draw text
//--------------------------------------------------------------------------------------------------
ref<Font> DrawableText::font() const
{
return m_font;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableText::setVerticalAlignment(TextDrawer::Alignment alignment)
{
m_verticalAlignment = alignment;
}
//--------------------------------------------------------------------------------------------------
/// Set color of the text to be rendered
//--------------------------------------------------------------------------------------------------
void DrawableText::setTextColor(const Color3f& color)
{
m_textColor = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableText::setBackgroundColor(const Color3f& color)
{
m_backgroundColor = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableText::setBorderColor(const Color3f& color)
{
m_borderColor = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableText::setDrawBackground(bool drawBackground)
{
m_drawBackground = drawBackground;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableText::setDrawBorder(bool drawBorder)
{
m_drawBorder = drawBorder;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableText::setCheckPosVisible(bool checkpos)
{
m_checkPosVisible = checkpos;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableText::addText(const String& text, const Vec3f& position)
{
m_positions.push_back(position);
m_texts.push_back(text);
m_boundingBox.add(position);
}
//--------------------------------------------------------------------------------------------------
/// Main shader based rendering path for the geometry
//--------------------------------------------------------------------------------------------------
void DrawableText::render(OpenGLContext* oglContext, ShaderProgram* shaderProgram, const MatrixState& matrixState)
{
renderText(oglContext, shaderProgram, matrixState);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableText::renderSoftware(OpenGLContext* oglContext, const MatrixState& matrixState)
{
renderText(oglContext, NULL, matrixState);
}
//--------------------------------------------------------------------------------------------------
/// Get total number of vertices for all texts
//--------------------------------------------------------------------------------------------------
size_t DrawableText::vertexCount() const
{
return faceCount() * 4; // Four vertices per face/quad
}
//--------------------------------------------------------------------------------------------------
/// Get total number of triangles for all texts
//--------------------------------------------------------------------------------------------------
size_t DrawableText::triangleCount() const
{
size_t numCharacters = 0;
size_t numTexts = m_texts.size();
size_t i;
for (i = 0; i < numTexts; i++)
{
numCharacters += m_texts[i].size();
}
return faceCount() * 2; // Two triangles per face/quad
}
//--------------------------------------------------------------------------------------------------
/// Get total number of faces for all texts
//--------------------------------------------------------------------------------------------------
size_t DrawableText::faceCount() const
{
size_t numCharacters = 0;
size_t numTexts = m_texts.size();
size_t i;
for (i = 0; i < numTexts; i++)
{
numCharacters += m_texts[i].size();
}
return numCharacters; // One face/quad per character/glyph
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
BoundingBox DrawableText::boundingBox() const
{
return m_boundingBox;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool DrawableText::rayIntersectCreateDetail(const Ray& ray, Vec3d* intersectionPoint, ref<HitDetail>* hitDetail) const
{
CVF_UNUSED(ray);
CVF_UNUSED(intersectionPoint);
CVF_UNUSED(hitDetail);
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableText::renderText(OpenGLContext* oglContext, ShaderProgram* shaderProgram, const MatrixState& matrixState)
{
CVF_ASSERT(m_font.notNull());
CVF_ASSERT(!m_font->isEmpty());
CVF_ASSERT(oglContext);
CVF_ASSERT(!shaderProgram || ShaderProgram::supportedOpenGL(oglContext));
if (m_texts.size() == 0) return;
CVF_ASSERT(m_positions.size() == m_texts.size());
if (m_checkPosVisible)
{
if (shaderProgram)
{
ref<ShaderProgram> nudgeShader = oglContext->resourceManager()->getLinkedNudgeShaderProgram(oglContext);
nudgeShader->useProgram(oglContext);
nudgeShader->clearUniformApplyTracking();
nudgeShader->applyFixedUniforms(oglContext, matrixState);
Point point(Point::PROGRAM_SIZE);
point.applyOpenGL(oglContext);
}
else
{
if (ShaderProgram::supportedOpenGL(oglContext))
{
ShaderProgram::useNoProgram(oglContext);
}
#ifndef CVF_OPENGL_ES
Material_FF mat;
mat.enableColorMaterial(true);
Lighting_FF noLight(false);
noLight.applyOpenGL(oglContext);
#endif
}
Depth visibleCheckDepthRS(true, Depth::LEQUAL, false);
visibleCheckDepthRS.applyOpenGL(oglContext);
PolygonOffset po;
po.enablePointMode(true);
po.setFactor(-3.0f);
po.setUnits(-3.0f);
po.applyOpenGL(oglContext);
Blending addBlend;
addBlend.enableBlending(true);
addBlend.setFunction(Blending::ONE, Blending::ONE);
addBlend.setEquation(Blending::FUNC_ADD);
addBlend.applyOpenGL(oglContext);
}
Mat4d modelViewProjectionMatrix = Mat4d(matrixState.modelViewProjectionMatrix());
std::vector<Vec3f> projCoords;
std::vector<String> textsToDraw; // Text strings to be drawn
size_t pos;
for (pos = 0; pos < m_positions.size(); pos++)
{
Vec3d proj;
GeometryUtils::project(modelViewProjectionMatrix, matrixState.viewportPosition(), matrixState.viewportSize(), Vec3d(m_positions[pos]), &proj);
if (!m_checkPosVisible || labelAnchorVisible(oglContext, proj, m_positions[pos], shaderProgram == NULL))
{
// Note: Need to adjust for the current viewport, as the coords returned from project are in global windows coordinates
projCoords.push_back(Vec3f(static_cast<float>(proj.x() - matrixState.viewportPosition().x()), static_cast<float>(proj.y() - matrixState.viewportPosition().y()), 0.0f));
textsToDraw.push_back(m_texts[pos]);
}
}
if (m_checkPosVisible)
{
PolygonOffset resetPO;
resetPO.applyOpenGL(oglContext);
Blending resetBlend;
resetBlend.applyOpenGL(oglContext);
#ifndef CVF_OPENGL_ES
if (!shaderProgram)
{
Material_FF mat;
mat.applyOpenGL(oglContext);
Lighting_FF light;
light.applyOpenGL(oglContext);
}
#endif
}
TextDrawer drawer(m_font.p());
drawer.setVerticalAlignment(m_verticalAlignment);
drawer.setTextColor(m_textColor);
drawer.setBackgroundColor(m_backgroundColor);
drawer.setBorderColor(m_borderColor);
drawer.setDrawBorder(m_drawBorder);
drawer.setDrawBackground(m_drawBackground);
size_t i;
for (i = 0; i < textsToDraw.size(); i++)
{
Vec3f pos = projCoords[i];
drawer.addText(textsToDraw[i], Vec2f(pos));
}
if (shaderProgram)
{
drawer.render(oglContext, matrixState);
// Keep current program in use when we exit
shaderProgram->useProgram(oglContext);
}
else
{
drawer.renderSoftware(oglContext, matrixState);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool DrawableText::labelAnchorVisible(OpenGLContext* oglContext, const Vec3d winCoord, const Vec3f& worldCoord, bool softwareRendering) const
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_UNUSED(worldCoord);
Vec2i coord(static_cast<GLint>(winCoord.x()), static_cast<GLint>(winCoord.y()));
// Read out current z buffer contents
GLubyte bufferBefore[9*4];
glReadPixels(coord.x() - 1, coord.y() - 1, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, bufferBefore);
if (softwareRendering)
{
#ifndef CVF_OPENGL_ES
glPointSize(3);
glColor3f(0.02f, 0.02f, 0.02f);
glBegin(GL_POINTS);
glVertex3fv(worldCoord.ptr());
glEnd();
#endif
}
else
{
glEnableVertexAttribArray(ShaderProgram::VERTEX);
glVertexAttribPointer(ShaderProgram::VERTEX, 3, GL_FLOAT, GL_FALSE, 0, worldCoord.ptr());
glDrawArrays(GL_POINTS, 0, 1);
}
// Now compare with previous z buffer contents to see if marker is visible
GLubyte bufferAfter[9*4];
glReadPixels(coord.x() - 1, coord.y() - 1, 3, 3, GL_RGBA, GL_UNSIGNED_BYTE, bufferAfter);
size_t j;
for (j = 0; j < 9*4; j++)
{
if (bufferBefore[j] != bufferAfter[j]) return true;
}
return false;
}
} // namespace cvf
@@ -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 "cvfDrawable.h"
#include "cvfArray.h"
#include "cvfBoundingBox.h"
#include "cvfTextDrawer.h"
namespace cvf {
class Font;
class DrawableGeo;
class ShaderProgram;
class BufferObjectManaged;
//==================================================================================================
//
// DrawableText implements drawing of text strings attached to a 3D point
//
//==================================================================================================
class DrawableText : public Drawable
{
public:
DrawableText();
virtual ~DrawableText();
void setFont(Font* font);
ref<Font> font() const;
void addText(const String& text, const Vec3f& position);
void setVerticalAlignment(TextDrawer::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 setCheckPosVisible(bool checkpos);
virtual void createUploadBufferObjectsGPU(OpenGLContext* /*oglContext*/) {}
virtual void releaseBufferObjectsGPU() {}
virtual void render(OpenGLContext* oglContext, ShaderProgram* shaderProgram, const MatrixState& matrixState);
/*virtual*/ void renderSoftware(OpenGLContext* oglContext, const MatrixState& matrixState);
virtual size_t vertexCount() const;
virtual size_t triangleCount() const;
virtual size_t faceCount() const;
virtual BoundingBox boundingBox() const;
virtual bool rayIntersectCreateDetail(const Ray& ray, Vec3d* intersectionPoint, ref<HitDetail>* hitDetail) const;
// TO BE REMOVED!
virtual void renderFixedFunction(OpenGLContext* oglContext, const MatrixState& matrixState) { renderSoftware(oglContext, matrixState); }
virtual void renderImmediateMode(OpenGLContext* oglContext, const MatrixState& matrixState) { renderSoftware(oglContext, matrixState); }
private:
void renderText(OpenGLContext* oglContext, ShaderProgram* shaderProgram, const MatrixState& matrixState);
bool labelAnchorVisible(OpenGLContext* oglContext, const Vec3d winCoord, const Vec3f& worldCoord, bool softwareRendering) const;
private:
std::vector<Vec3f> m_positions; // Coordinate of the lower left corner of where to place the text in pixel coordinates
std::vector<String> m_texts; // Text strings to be drawn
ref<Font> m_font; // Font used to draw text
TextDrawer::Alignment m_verticalAlignment;
Color3f m_textColor;
Color3f m_backgroundColor;
Color3f m_borderColor;
bool m_drawBackground;
bool m_drawBorder;
bool m_checkPosVisible;
BoundingBox m_boundingBox; //
};
} // namespace cvf
@@ -0,0 +1,543 @@
//##################################################################################################
//
// 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 "cvfDrawableVectors.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfBufferObjectManaged.h"
#include "cvfDrawableGeo.h"
#include "cvfQuat.h"
#include "cvfShaderProgram.h"
#include "cvfUniform.h"
#include "cvfPrimitiveSetIndexedUShort.h"
#include "cvfRay.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#endif
namespace cvf {
//==================================================================================================
///
/// \class cvf::DrawableVectors
/// \ingroup Render
///
/// DrawableVectors implements drawing of vector arrows.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor to use when using fixed function rendering
//--------------------------------------------------------------------------------------------------
DrawableVectors::DrawableVectors()
: m_singleColor(Color3f(Color3::WHITE)),
m_renderWithVBO(true)
{
}
//--------------------------------------------------------------------------------------------------
/// Constructor to use when using shader based rendering
//--------------------------------------------------------------------------------------------------
DrawableVectors::DrawableVectors(String vectorMatrixUniformName, String colorUniformName)
: m_vectorMatrixUniformName(vectorMatrixUniformName),
m_colorUniformName(colorUniformName),
m_singleColor(Color3f(Color3::WHITE)),
m_renderWithVBO(true)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
DrawableVectors::~DrawableVectors()
{
releaseBufferObjectsGPU();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableVectors::setGlyph(UShortArray* triangles, Vec3fArray* vertices)
{
m_vectorGlyph = new DrawableGeo;
m_vectorGlyphPrimSet = new PrimitiveSetIndexedUShort(PT_TRIANGLES);
m_vectorGlyphPrimSet->setIndices(triangles);
m_vectorGlyph->setVertexArray(vertices);
m_vectorGlyph->addPrimitiveSet(m_vectorGlyphPrimSet.p());
m_vectorGlyph->computeNormals();
if (m_renderWithVBO)
{
m_vectorGlyph->setRenderMode(DrawableGeo::BUFFER_OBJECT);
}
releaseBufferObjectsGPU();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableVectors::setSingleColor(Color3f color)
{
m_singleColor = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableVectors::setVectors(Vec3fArray* vertexArray, Vec3fArray* vectorArray)
{
CVF_ASSERT(vertexArray && vectorArray);
CVF_ASSERT(vertexArray->size() && vectorArray->size());
m_vertexArray = vertexArray;
m_vectorArray = vectorArray;
m_boundingBox.add(*m_vertexArray);
}
//--------------------------------------------------------------------------------------------------
/// Set color of each corresponding vector
///
/// \param vectorColorArray Array of colors to be mapped one-by-one to the vector array
/// \param colorUniformName Name of uniform when used by a shader program. Ignored if not.
///
/// \sa setVectors
//--------------------------------------------------------------------------------------------------
void DrawableVectors::setColors(Color3fArray* vectorColorArray)
{
m_colorArray = vectorColorArray;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t DrawableVectors::vectorCount() const
{
CVF_ASSERT(m_vertexArray->size() == m_vectorArray->size());
return m_vertexArray->size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableVectors::render(OpenGLContext* oglContext, ShaderProgram* shaderProgram, const MatrixState&)
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_ASSERT(shaderProgram);
CVF_ASSERT(shaderProgram->isProgramUsed(oglContext));
CVF_ASSERT(m_vertexArray->size() == m_vectorArray->size());
CVF_ASSERT(m_colorArray.isNull() || (m_colorArray->size() == m_vectorArray->size()));
CVF_ASSERT(m_vectorGlyph.notNull());
CVF_ASSERT(m_vectorGlyph->primitiveSetCount() == 1);
// Setup Vertex Arrays/vbos
const GLvoid* ptrOrOffset = 0;
if (m_renderWithVBO && m_glyphVerticesAndNormalsBO.notNull() && m_glyphVerticesAndNormalsBO->isUploaded())
{
// Bind VBO for vertex and normal data
m_glyphVerticesAndNormalsBO->bindBuffer(oglContext);
glVertexAttribPointer(ShaderProgram::NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(float)*6, (void*)(sizeof(float)*3));
glVertexAttribPointer(ShaderProgram::VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(float)*6, 0);
glEnableVertexAttribArray(ShaderProgram::NORMAL);
glEnableVertexAttribArray(ShaderProgram::VERTEX);
m_indicesBO->bindBuffer(oglContext);
}
else
{
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribPointer(ShaderProgram::NORMAL, 3, GL_FLOAT, GL_FALSE, 0, m_vectorGlyph->normalArray()->ptr()->ptr());
glEnableVertexAttribArray(ShaderProgram::NORMAL);
glVertexAttribPointer(ShaderProgram::VERTEX, 3, GL_FLOAT, GL_FALSE, 0, m_vectorGlyph->vertexArray()->ptr()->ptr());
glEnableVertexAttribArray(ShaderProgram::VERTEX);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
ptrOrOffset = m_vectorGlyphPrimSet->indices()->ptr();
}
// Must use manual uniform setting, as setting the uniform through the Uniform* class requires a lookup for location
// every time, and this is always the same
GLint vectorMatrixUniformLocation = shaderProgram->uniformLocation(m_vectorMatrixUniformName.toAscii().ptr());
CVF_ASSERT(vectorMatrixUniformLocation != -1);
GLint colorUniformLocation = shaderProgram->uniformLocation(m_colorUniformName.toAscii().ptr());
CVF_ASSERT(colorUniformLocation != -1);
#ifndef CVF_OPENGL_ES
uint minIndex = m_vectorGlyphPrimSet->minIndex();
uint maxIndex = m_vectorGlyphPrimSet->maxIndex();
#endif
GLsizei indexCount = static_cast<GLsizei>(m_vectorGlyphPrimSet->indexCount());
// Set the single color to use
if (m_colorArray.isNull())
{
glUniform3fv(colorUniformLocation, 1, m_singleColor.ptr());
}
float vectorMat[16];
size_t numVectors = m_vectorArray->size();
size_t i;
for (i = 0; i < numVectors; i++)
{
// Compute the transformation matrix
vectorMatrix(i, vectorMat);
// Set this as a uniform to the shader program
glUniformMatrix4fv(vectorMatrixUniformLocation, 1, GL_FALSE, vectorMat);
if (m_colorArray.notNull())
{
glUniform3fv(colorUniformLocation, 1, m_colorArray->get(i).ptr());
}
// Draw the arrow
#ifdef CVF_OPENGL_ES
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, ptrOrOffset);
#else
glDrawRangeElements(GL_TRIANGLES, minIndex, maxIndex, indexCount, GL_UNSIGNED_SHORT, ptrOrOffset);
#endif
}
// Cleanup
glDisableVertexAttribArray(ShaderProgram::VERTEX);
glDisableVertexAttribArray(ShaderProgram::NORMAL);
CVF_CHECK_OGL(oglContext);
// Things to consider for performance:
// 1) Uniform arrays evt. Uniform buffer objects
// 2) Texture
// 3) Texture array
// GL_ARB_draw_instanced();
// glDrawElementsInstanced
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableVectors::renderFixedFunction(OpenGLContext* oglContext, const MatrixState& matrixState)
{
#ifdef CVF_OPENGL_ES
CVF_FAIL_MSG("Not supported on OpenGL ES");
#else
CVF_ASSERT(oglContext);
CVF_ASSERT(m_vertexArray->size() == m_vectorArray->size());
CVF_ASSERT(m_vectorGlyph.notNull());
glEnable(GL_NORMALIZE);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
if (m_colorArray.isNull())
{
glColor3fv(m_singleColor.ptr());
}
float vectorMat[16];
size_t numVectors = m_vectorArray->size();
size_t i;
for (i = 0; i < numVectors; i++)
{
// Compute/retrieve "matrix"
vectorMatrix(i, vectorMat);
glPushMatrix();
glMultMatrixf(vectorMat);
if (m_colorArray.notNull())
{
glColor3fv(m_colorArray->get(i).ptr());
}
// Draw the geometry
m_vectorGlyph->renderFixedFunction(oglContext, matrixState);
glPopMatrix();
}
glDisable(GL_NORMALIZE);
CVF_CHECK_OGL(oglContext);
#endif // CVF_OPENGL_ES
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableVectors::renderImmediateMode(OpenGLContext* oglContext, const MatrixState& matrixState)
{
#ifdef CVF_OPENGL_ES
CVF_FAIL_MSG("Not supported on OpenGL ES");
#else
CVF_ASSERT(oglContext);
CVF_ASSERT(m_vertexArray->size() == m_vectorArray->size());
CVF_ASSERT(m_vectorGlyph.notNull());
glEnable(GL_NORMALIZE);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
if (m_colorArray.isNull())
{
glColor3fv(m_singleColor.ptr());
}
float vectorMat[16];
size_t numVectors = m_vectorArray->size();
size_t i;
for (i = 0; i < numVectors; i++)
{
// Compute/retrieve "matrix"
vectorMatrix(i, vectorMat);
glPushMatrix();
glMultMatrixf(vectorMat);
if (m_colorArray.notNull())
{
glColor3fv(m_colorArray->get(i).ptr());
}
// Draw the geometry
m_vectorGlyph->renderImmediateMode(oglContext, matrixState);
glPopMatrix();
}
glDisable(GL_NORMALIZE);
CVF_CHECK_OGL(oglContext);
#endif // CVF_OPENGL_ES
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableVectors::createUploadBufferObjectsGPU(OpenGLContext* oglContext)
{
if (!m_renderWithVBO || m_vertexArray->size() == 0 || m_vectorGlyph.isNull() || m_vectorGlyphPrimSet.isNull())
{
return;
}
if (m_glyphVerticesAndNormalsBO.isNull() || !m_glyphVerticesAndNormalsBO->isUploaded())
{
// Build a interleaved VBO for glyphs vertices and normals to get better performance
// during the main shader based draw path
size_t numVertices = m_vectorGlyph->vertexArray()->size();
Vec3fArray data;
data.reserve(numVertices*2);
size_t i;
for (i = 0; i < numVertices; i++)
{
data.add(m_vectorGlyph->vertexArray()->get(i));
data.add(m_vectorGlyph->normalArray()->get(i));
}
GLuint uiSizeInBytes = static_cast<GLuint>(data.size()*3*sizeof(float));
m_glyphVerticesAndNormalsBO = oglContext->resourceManager()->getOrCreateManagedBufferObject(oglContext, GL_ARRAY_BUFFER, uiSizeInBytes, data.ptr()->ptr());
}
if (m_indicesBO.isNull() || !m_indicesBO->isUploaded())
{
const UShortArray* indices = m_vectorGlyphPrimSet->indices();
size_t numIndices = indices->size();
if (numIndices > 0)
{
GLuint uiSizeInBytes = static_cast<GLuint>(numIndices*sizeof(GLushort));
m_indicesBO = oglContext->resourceManager()->getOrCreateManagedBufferObject(oglContext, GL_ELEMENT_ARRAY_BUFFER, uiSizeInBytes, indices->ptr());
CVF_CHECK_OGL(oglContext);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableVectors::releaseBufferObjectsGPU()
{
m_glyphVerticesAndNormalsBO = NULL;
if (m_vectorGlyph.notNull())
{
m_vectorGlyph->releaseBufferObjectsGPU();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t DrawableVectors::vertexCount() const
{
if (m_vectorGlyph.isNull())
{
return 0;
}
return m_vectorGlyph->vertexCount()*vectorCount();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t DrawableVectors::triangleCount() const
{
if (m_vectorGlyph.isNull())
{
return 0;
}
return m_vectorGlyph->triangleCount()*vectorCount();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t DrawableVectors::faceCount() const
{
if (m_vectorGlyph.isNull())
{
return 0;
}
return m_vectorGlyph->faceCount()*vectorCount();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
BoundingBox DrawableVectors::boundingBox() const
{
return m_boundingBox;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool DrawableVectors::rayIntersectCreateDetail(const Ray& ray, Vec3d* intersectionPoint, ref<HitDetail>* hitDetail) const
{
CVF_UNUSED(ray);
CVF_UNUSED(intersectionPoint);
CVF_UNUSED(hitDetail);
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DrawableVectors::vectorMatrix(size_t vectorIndex, float vectorMatArray[16])
{
const Vec3f& anchorPt = m_vertexArray->get(vectorIndex);
Vec3f vec = m_vectorArray->get(vectorIndex);
float length = vec.length();
Quatf rotQuat;
// This should really be a ratio eval based on length of vector
// Copied from VTOVectorDrawer.cpp. TODO: refactor
static const float TINY_VEC_COMP = 0.0000000001f;
bool negZOnly = vec.z() < 0.0f && Math::abs(vec.x()) < TINY_VEC_COMP && Math::abs(vec.y()) < TINY_VEC_COMP;
if (negZOnly)
{
rotQuat.set(0.0f, 1.0f, 0.0f, 0.0f);
}
else
{
const Vec3f s = Vec3f::Z_AXIS;
Vec3f d = vec/length;
Vec3f v = s + d;
Vec3f cross = v ^ d;
float dot = v*d;
rotQuat.set(cross.x(), cross.y(), cross.z(), dot);
}
float Nq = rotQuat.x()*rotQuat.x() + rotQuat.y()*rotQuat.y() + rotQuat.z()*rotQuat.z() + rotQuat.w()*rotQuat.w();
float s = (Nq > 0.0f) ? (2.0f/Nq) : 0.0f;
float xs = rotQuat.x()*s;
float ys = rotQuat.y()*s;
float zs = rotQuat.z()*s;
float wx = rotQuat.w()*xs;
float wy = rotQuat.w()*ys;
float wz = rotQuat.w()*zs;
float xx = rotQuat.x()*xs;
float xy = rotQuat.x()*ys;
float xz = rotQuat.x()*zs;
float yy = rotQuat.y()*ys;
float yz = rotQuat.y()*zs;
float zz = rotQuat.z()*zs;
vectorMatArray[0] = length*(1.0f - (yy + zz));
vectorMatArray[1] = length*(xy + wz);
vectorMatArray[2] = length*(xz - wy);
vectorMatArray[3] = 0.0f;
vectorMatArray[4] = length*(xy - wz);
vectorMatArray[5] = length*(1.0f - (xx + zz));
vectorMatArray[6] = length*(yz + wx);
vectorMatArray[7] = 0.0f;
vectorMatArray[8] = length*(xz + wy);
vectorMatArray[9] = length*(yz - wx);
vectorMatArray[10] = length*(1.0f - (xx + yy));
vectorMatArray[11] = 0.0f;
// Set the translation
vectorMatArray[12] = anchorPt.x();
vectorMatArray[13] = anchorPt.y();
vectorMatArray[14] = anchorPt.z();
vectorMatArray[15] = 1.0f;
}
} // namespace cvf
@@ -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.
//
//##################################################################################################
#pragma once
#include "cvfDrawable.h"
#include "cvfArray.h"
#include "cvfBoundingBox.h"
namespace cvf {
class DrawableGeo;
class ShaderProgram;
class BufferObjectManaged;
class PrimitiveSetIndexedUShort;
//==================================================================================================
//
// DrawableVectors implements drawing of vector arrows
//
//==================================================================================================
class DrawableVectors : public Drawable
{
public:
DrawableVectors();
DrawableVectors(String vectorMatrixUniformName, String colorUniformName);
virtual ~DrawableVectors();
void setGlyph(UShortArray* triangles, Vec3fArray* vertices);
void setSingleColor(Color3f color);
void setVectors(Vec3fArray* vertexArray, Vec3fArray* vectorArray);
void setColors(Color3fArray* vectorColorArray);
size_t vectorCount() const;
virtual void render(OpenGLContext* oglContext, ShaderProgram* shaderProgram, const MatrixState& matrixState);
virtual void renderFixedFunction(OpenGLContext* oglContext, const MatrixState& matrixState);
virtual void renderImmediateMode(OpenGLContext* oglContext, const MatrixState& matrixState);
virtual void createUploadBufferObjectsGPU(OpenGLContext* oglContext);
virtual void releaseBufferObjectsGPU();
virtual size_t vertexCount() const;
virtual size_t triangleCount() const;
virtual size_t faceCount() const;
virtual BoundingBox boundingBox() const;
virtual bool rayIntersectCreateDetail(const Ray& ray, Vec3d* intersectionPoint, ref<HitDetail>* hitDetail) const;
private:
void vectorMatrix(size_t vectorIndex, float vectorMatArray[16]);
private:
String m_vectorMatrixUniformName;
String m_colorUniformName;
Color3f m_singleColor; // Color used by all vectors if no color array is specified
ref<Vec3fArray> m_vertexArray; // Positions of the vectors
ref<Vec3fArray> m_vectorArray; // Direction & magnitude of the vectors.
// A vector is drawn from m_vertexArray[i] to (m_vertexArray[i] + m_vectorArray[i])
ref<Color3fArray> m_colorArray;
ref<DrawableGeo> m_vectorGlyph; // A drawable representing one arrow with the current config
ref<PrimitiveSetIndexedUShort> m_vectorGlyphPrimSet; // A drawable representing one arrow with the current config
BoundingBox m_boundingBox;
bool m_renderWithVBO;
ref<BufferObjectManaged> m_glyphVerticesAndNormalsBO; // Buffer object for holding the glyph vertices and normals for uploading data to GPU
ref<BufferObjectManaged> m_indicesBO;
};
} // namespace cvf
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,82 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfFont.h"
#include "cvfGlyph.h"
#include "cvfString.h"
#include <map>
namespace cvf {
class TextureImage;
class Glyph;
//==================================================================================================
//
// Fixed atlas font class used to generate glyphs for a given character
//
//==================================================================================================
class FixedAtlasFont : public Font
{
public:
enum FontSize
{
STANDARD, // 8pt
LARGE // 16pt
};
public:
FixedAtlasFont(FontSize size);
virtual ~FixedAtlasFont();
virtual const String& name() const;
virtual ref<Glyph> getGlyph(wchar_t character);
virtual uint advance(wchar_t character, wchar_t nextCharacter);
virtual bool isEmpty();
private:
// Load/unload font
bool load(const char* name, size_t numGlyphs,
const short* horizontalBearingsX, const short* horizontalBearingsY,
const uint* horizontalAdvances, const uint* characterWidths, const uint* characterHeightss,
const size_t textureImageWidth, const size_t textureImageHeight,
const size_t numTextureImageDataBlockCount, const char** textureImageData);
void unload();
private:
String m_name;
size_t m_numGlyphs;
std::vector<short> m_horizontalBearingsX;
std::vector<short> m_horizontalBearingsY;
std::vector<uint> m_horizontalAdvances;
std::vector<uint> m_characterWidths;
std::vector<uint> m_characterHeights;
ref<TextureImage> m_textureImage;
// Glyph cache
typedef std::map<size_t, ref<Glyph> > MapType;
MapType m_atlasMap;
};
} // namespace cvf
+100
View File
@@ -0,0 +1,100 @@
//##################################################################################################
//
// 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 "cvfFont.h"
#include "cvfGlyph.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Font
/// \ingroup Render
///
/// Pure virtual font base class used to generate glyphs for a given character.
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
Font::Font()
{
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
Font::~Font()
{
}
//--------------------------------------------------------------------------------------------------
/// 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);
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
+50
View File
@@ -0,0 +1,50 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfString.h"
#include "cvfVector2.h"
namespace cvf {
class Glyph;
//==================================================================================================
//
// Pure virtual font base class used to generate glyphs for a given character.
//
//==================================================================================================
class Font : public Object
{
public:
Font();
virtual ~Font();
virtual const String& name() const = 0;
virtual ref<Glyph> getGlyph(wchar_t character) = 0;
virtual uint advance(wchar_t character, wchar_t nextCharacter) = 0;
virtual bool isEmpty() = 0;
Vec2ui textExtent(const String& text);
};
} // namespace cvf
@@ -0,0 +1,93 @@
//##################################################################################################
//
// 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 "cvfFontManager.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::FontManager
/// \ingroup Render
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
FontManager::FontManager()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
FontManager::~FontManager()
{
}
//--------------------------------------------------------------------------------------------------
/// Get number of loaded fonts
//--------------------------------------------------------------------------------------------------
uint FontManager::numFonts() const
{
return 0;//m_fonts.size();
}
//--------------------------------------------------------------------------------------------------
/// Get already loaded font
//--------------------------------------------------------------------------------------------------
ref<Font> FontManager::getFontById(uint id)
{
CVF_UNUSED(id);
return NULL;
}
//--------------------------------------------------------------------------------------------------
/// Get embedded font. Load if needed
//--------------------------------------------------------------------------------------------------
ref<Font> FontManager::getEmbeddedFont(EmbeddedFont font)
{
CVF_UNUSED(font);
return NULL;
}
//--------------------------------------------------------------------------------------------------
/// Get font located on file. Load if needed.
//--------------------------------------------------------------------------------------------------
ref<Font> FontManager::getFontFromFile(const String& path)
{
CVF_UNUSED(path);
CVF_ASSERT(!path.isEmpty());
// Not supported in this class
return NULL;
}
} // namespace cvf
@@ -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.
//
//##################################################################################################
#pragma once
#include "cvfObject.h"
#include "cvfString.h"
#include "cvfFont.h"
#include <map>
namespace cvf {
//==================================================================================================
//
// Font management
//
//==================================================================================================
class FontManager : public Object
{
public:
enum EmbeddedFont
{
DEFAULT,
CVF_1,
CVF_2
};
public:
FontManager();
virtual ~FontManager();
uint numFonts() const;
virtual ref<Font> getFontById(uint id);
virtual ref<Font> getEmbeddedFont(EmbeddedFont font);
virtual ref<Font> getFontFromFile(const String& path);
private:
static uint uniqueIdCounter;
std::map<uint, ref<Font> > m_fonts;
};
} // namespace cvf
@@ -0,0 +1,607 @@
//##################################################################################################
//
// 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 "cvfFramebufferObject.h"
#include "cvfRenderbufferObject.h"
#include "cvfTexture.h"
#include "cvfOpenGL.h"
#include "cvfString.h"
#include "cvfOglRc.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfOpenGLCapabilities.h"
namespace cvf {
//==================================================================================================
///
/// \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
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
FramebufferObject::FramebufferObject()
: m_depthAttachmentVersionTick(0)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
FramebufferObject::~FramebufferObject()
{
// Just release our reference
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcBuffer.p()));
m_oglRcBuffer = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::attachColorRenderbuffer(uint index, RenderbufferObject* renderbuffer)
{
// Not legal to have both a texture and a render buffer attachment
CVF_ASSERT(m_colorTextures.size() <= index || m_colorTextures[index].isNull());
if (index >= m_colorRenderBuffers.size())
{
m_colorRenderBuffers.resize(index + 1);
}
m_colorRenderBuffers[index] = renderbuffer;
setColorBufferVersionTick(index, 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::attachColorTexture2d(uint index, Texture* texture)
{
// Not legal to have both a texture and a render buffer attachment
CVF_ASSERT(m_colorRenderBuffers.size() <= index || m_colorRenderBuffers[index].isNull());
if (index >= m_colorTextures.size())
{
m_colorTextures.resize(index + 1);
}
m_colorTextures[index] = texture;
setColorBufferVersionTick(index, 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::attachColorTexture2dCubeMap(uint index, Texture::CubeMapFace face, Texture* texture)
{
// Not legal to have both a texture and a render buffer attachment
CVF_ASSERT(m_colorRenderBuffers.size() <= index || m_colorRenderBuffers[index].isNull());
if (index >= m_colorTextures.size())
{
m_colorTextures.resize(index + 1);
}
m_colorTextures[index] = texture;
m_colorCubeMapFaces[index] = face;
setColorBufferVersionTick(index, 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::attachDepthRenderbuffer(RenderbufferObject* renderbuffer)
{
m_depthRenderBuffer = renderbuffer;
m_depthTexture2d = NULL;
m_depthStencilTexture2d = NULL;
m_depthStencilRenderBuffer = NULL;
m_depthAttachmentVersionTick = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::attachDepthTexture2d(Texture* texture)
{
m_depthTexture2d = texture;
m_depthRenderBuffer = NULL;
m_depthStencilRenderBuffer = NULL;
m_depthStencilTexture2d = NULL;
m_depthAttachmentVersionTick = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::attachDepthStencilRenderbuffer(RenderbufferObject* renderbuffer)
{
m_depthStencilRenderBuffer = renderbuffer;
m_depthStencilTexture2d = NULL;
m_depthTexture2d = NULL;
m_depthRenderBuffer = NULL;
m_depthAttachmentVersionTick = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::attachDepthStencilTexture2d(Texture* texture)
{
m_depthStencilTexture2d = texture;
m_depthStencilRenderBuffer = NULL;
m_depthTexture2d = NULL;
m_depthRenderBuffer = NULL;
m_depthAttachmentVersionTick = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::resizeAttachedBuffers(uint width, uint height)
{
size_t i;
for (i = 0; i < m_colorRenderBuffers.size(); i++)
{
RenderbufferObject* buffer = m_colorRenderBuffers[i].p();
if (buffer)
{
buffer->setSize(width, height);
}
}
for (i = 0; i < m_colorTextures.size(); i++)
{
Texture* texture = m_colorTextures[i].p();
if (texture)
{
texture->setSize(width, height);
}
}
if (m_depthRenderBuffer.notNull())
{
m_depthRenderBuffer->setSize(width, height);
}
if (m_depthTexture2d.notNull())
{
m_depthTexture2d->setSize(width, height);
}
if (m_depthStencilTexture2d.notNull())
{
m_depthStencilTexture2d->setSize(width, height);
}
if (m_depthStencilRenderBuffer.notNull())
{
m_depthStencilRenderBuffer->setSize(width, height);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::applyOpenGL(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_ASSERT(FramebufferObject::supportedOpenGL(oglContext));
bool createdNewFrameBuffer = false;
if (OglRc::safeOglId(m_oglRcBuffer.p()) == 0)
{
m_oglRcBuffer = oglContext->resourceManager()->createOglRcFramebuffer(oglContext);
createdNewFrameBuffer = true;
}
glBindFramebuffer(GL_FRAMEBUFFER, OglRc::safeOglId(m_oglRcBuffer.p()));
bool attachmentsModified = createdNewFrameBuffer;
uint i;
for (i = 0; i < m_colorRenderBuffers.size(); i++)
{
RenderbufferObject* renderBuffer = m_colorRenderBuffers[i].p();
if (renderBuffer)
{
if (renderBuffer->versionTick() != m_colorAttachmentVersionTicks[i])
{
if (renderBuffer->renderbufferOglId() == 0)
{
if (!renderBuffer->create(oglContext))
{
return;
}
}
glFramebufferRenderbuffer(GL_FRAMEBUFFER, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i), GL_RENDERBUFFER, renderBuffer->renderbufferOglId());
setColorBufferVersionTick(i, renderBuffer->versionTick());
attachmentsModified = true;
}
}
}
for (i = 0; i < m_colorTextures.size(); i++)
{
Texture* texture = m_colorTextures[i].p();
if (texture)
{
if (texture->versionTick() != m_colorAttachmentVersionTicks[i])
{
if (texture->textureOglId() == 0)
{
if (!texture->setupTexture(oglContext))
{
return;
}
}
// Assume we'll change the texture so flag mipmaps as invalid
texture->removeMipmap();
std::map<uint, Texture::CubeMapFace>::iterator faceIt = m_colorCubeMapFaces.find(i);
if (faceIt != m_colorCubeMapFaces.end())
{
glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i), static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIt->second), texture->textureOglId(), 0);
}
else
{
if (texture->textureType() == Texture::TEXTURE_RECTANGLE)
{
#ifndef CVF_OPENGL_ES
glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i), GL_TEXTURE_RECTANGLE, texture->textureOglId(), 0);
#else
CVF_FAIL_MSG("Not supported on iOS");
#endif
}
else
{
glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i), GL_TEXTURE_2D, texture->textureOglId(), 0);
}
}
setColorBufferVersionTick(i, texture->versionTick());
attachmentsModified = true;
}
}
}
// Setup draw buffers. Drawbuffer settings are stored in the FBO, so we only need to do this whenever the FBO attachments are changed.
#ifndef CVF_OPENGL_ES
if (attachmentsModified)
{
size_t maxAttachmentIndex = CVF_MAX(m_colorRenderBuffers.size(), m_colorTextures.size());
if (maxAttachmentIndex > 0)
{
GLenum* drawBuffers = new GLenum[maxAttachmentIndex];
size_t i;
for (i = 0; i < maxAttachmentIndex; i++)
{
bool attachmentInUse = false;
if (m_colorRenderBuffers.size() > i && m_colorRenderBuffers[i].notNull())
{
attachmentInUse = true;
}
if (m_colorTextures.size() > i && m_colorTextures[i].notNull())
{
attachmentInUse = true;
}
if (attachmentInUse)
{
drawBuffers[i] = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
}
else
{
drawBuffers[i] = GL_NONE;
}
}
glDrawBuffers(static_cast<GLsizei>(maxAttachmentIndex), drawBuffers);
delete[] drawBuffers;
}
else
{
glDrawBuffer(GL_NONE);
}
}
#endif
// Depth attachment, can only have one
CVF_ASSERT(!(m_depthTexture2d.notNull() && m_depthRenderBuffer.notNull()));
if (m_depthRenderBuffer.notNull())
{
if (m_depthRenderBuffer->versionTick() != m_depthAttachmentVersionTick)
{
if (m_depthRenderBuffer->renderbufferOglId() == 0)
{
if (!m_depthRenderBuffer->create(oglContext))
{
return;
}
}
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthRenderBuffer->renderbufferOglId());
m_depthAttachmentVersionTick = m_depthRenderBuffer->versionTick();
}
}
if (m_depthTexture2d.notNull())
{
if (m_depthTexture2d->versionTick() != m_depthAttachmentVersionTick)
{
if (m_depthTexture2d->textureOglId() == 0)
{
if (!m_depthTexture2d->setupTexture(oglContext))
{
return;
}
}
if (m_depthTexture2d->textureType() == Texture::TEXTURE_2D)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture2d->textureOglId(), 0);
}
else if (m_depthTexture2d->textureType() == Texture::TEXTURE_RECTANGLE)
{
#ifndef CVF_OPENGL_ES
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_RECTANGLE, m_depthTexture2d->textureOglId(), 0);
#else
CVF_FAIL_MSG("Not supported on iOS");
#endif
}
else
{
CVF_FAIL_MSG("Not implemented");
}
m_depthAttachmentVersionTick = m_depthTexture2d->versionTick();
}
}
if (m_depthStencilRenderBuffer.notNull())
{
if (m_depthStencilRenderBuffer->versionTick() != m_depthAttachmentVersionTick)
{
if (m_depthStencilRenderBuffer->renderbufferOglId() == 0)
{
if (!m_depthStencilRenderBuffer->create(oglContext))
{
return;
}
}
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilRenderBuffer->renderbufferOglId());
m_depthAttachmentVersionTick = m_depthStencilRenderBuffer->versionTick();
}
}
if (m_depthStencilTexture2d.notNull())
{
if (m_depthStencilTexture2d->versionTick() != m_depthAttachmentVersionTick)
{
if (m_depthStencilTexture2d->textureOglId() == 0)
{
if (!m_depthStencilTexture2d->setupTexture(oglContext))
{
return;
}
}
if (m_depthStencilTexture2d->textureType() == Texture::TEXTURE_2D)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilTexture2d->textureOglId(), 0);
}
else if (m_depthStencilTexture2d->textureType() == Texture::TEXTURE_RECTANGLE)
{
#ifndef CVF_OPENGL_ES
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_RECTANGLE, m_depthStencilTexture2d->textureOglId(), 0);
#else
CVF_FAIL_MSG("Not supported on iOS");
#endif
}
else
{
CVF_FAIL_MSG("Not implemented");
}
m_depthAttachmentVersionTick = m_depthStencilTexture2d->versionTick();
}
}
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::useDefaultWindowFramebuffer(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
#ifdef CVF_OPENGL_ES
CVF_FAIL_MSG("FrameBufferObject::useDefaultWindowFramebuffer() not supported on OpenGL ES");
#else
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::deleteFramebuffer(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
if (m_oglRcBuffer.notNull())
{
m_oglRcBuffer->deleteResource(oglContext);
CVF_CHECK_OGL(oglContext);
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcBuffer.p()));
m_oglRcBuffer = NULL;
m_colorAttachmentVersionTicks.clear();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::deleteOrReleaseOpenGLResources(OpenGLContext* oglContext)
{
deleteFramebuffer(oglContext);
size_t i;
for (i = 0; i < m_colorRenderBuffers.size(); i++)
{
RenderbufferObject* buffer = m_colorRenderBuffers[i].p();
if (buffer)
{
buffer->deleteRenderbuffer(oglContext);
}
}
for (i = 0; i < m_colorTextures.size(); i++)
{
Texture* texture = m_colorTextures[i].p();
if (texture)
{
texture->deleteTexture(oglContext);
}
}
if (m_depthRenderBuffer.notNull())
{
m_depthRenderBuffer->deleteRenderbuffer(oglContext);
}
if (m_depthTexture2d.notNull())
{
m_depthTexture2d->deleteTexture(oglContext);
}
if (m_depthStencilTexture2d.notNull())
{
m_depthStencilTexture2d->deleteTexture(oglContext);
}
if (m_depthStencilRenderBuffer.notNull())
{
m_depthStencilRenderBuffer->deleteRenderbuffer(oglContext);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool FramebufferObject::supportedOpenGL(OpenGLContext* oglContext)
{
return oglContext->capabilities()->hasCapability(OpenGLCapabilities::FRAMEBUFFER_OBJECT);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool FramebufferObject::isFramebufferComplete(OpenGLContext* oglContext, String* failReason) const
{
CVF_CALLSITE_OPENGL(oglContext);
glBindFramebuffer(GL_FRAMEBUFFER, OglRc::safeOglId(m_oglRcBuffer.p()));
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
switch (status)
{
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: *failReason = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT is returned if any of the framebuffer attachment points are framebuffer incomplete."; break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: *failReason = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT is returned if the framebuffer does not have at least one image attached to it."; break;
case GL_FRAMEBUFFER_UNSUPPORTED: *failReason = "GL_FRAMEBUFFER_UNSUPPORTED is returned if the combination of internal formats of the attached images violates an implementation-dependent set of restrictions."; break;
#ifdef CVF_OPENGL_ES
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: *failReason = "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS. Not all attached images has same width and height."; break;
#else
case GL_FRAMEBUFFER_UNDEFINED: *failReason = "GL_FRAMEBUFFER_UNDEFINED is returned if target is the default framebuffer, but the default framebuffer does not exist."; break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: *failReason = "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER is returned if the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE for any color attachment point(s) named by GL_DRAWBUFFERi."; break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: *failReason = "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER is returned if GL_READ_BUFFER is not GL_NONE and the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE for the color attachment point named by GL_READ_BUFFER."; break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: *failReason = "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE is returned if the value of GL_RENDERBUFFER_SAMPLES is not the same for all attached renderbuffers; if the value of GL_TEXTURE_SAMPLES is the not same for all attached textures; or, if the attached images are a mix of renderbuffers and textures, the value of GL_RENDERBUFFER_SAMPLES does not match the value of GL_TEXTURE_SAMPLES."; break;
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: *failReason = "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS is returned if any framebuffer attachment is layered, and any populated attachment is not layered, or if all populated color attachments are not from textures of the same target."; break;
#endif
}
}
return status == GL_FRAMEBUFFER_COMPLETE;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void FramebufferObject::setColorBufferVersionTick(uint index, uint versionTick)
{
if (index >= m_colorAttachmentVersionTicks.size())
{
m_colorAttachmentVersionTicks.resize(index + 1, 0);
}
m_colorAttachmentVersionTicks[index] = versionTick;
}
} // namespace cvf
@@ -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.
//
//##################################################################################################
#pragma once
#include "cvfObject.h"
#include "cvfOpenGLTypes.h"
#include "cvfTexture.h"
#include <map>
namespace cvf {
class OpenGLContext;
class RenderbufferObject;
class String;
class OglRcFramebuffer;
//==================================================================================================
//
// Wrapper for OpenGL Frame Buffer Object
//
//==================================================================================================
class FramebufferObject : public Object
{
public:
FramebufferObject();
~FramebufferObject();
void resizeAttachedBuffers(uint width, uint height);
void attachColorRenderbuffer(uint index, RenderbufferObject* renderbuffer);
void attachColorTexture2d(uint index, Texture* texture);
void attachColorTexture2dCubeMap(uint index, Texture::CubeMapFace face, Texture* texture);
void attachDepthRenderbuffer(RenderbufferObject* renderbuffer);
void attachDepthTexture2d(Texture* texture);
void attachDepthStencilRenderbuffer(RenderbufferObject* renderbuffer);
void attachDepthStencilTexture2d(Texture* texture);
void applyOpenGL(OpenGLContext* oglContext);
static void useDefaultWindowFramebuffer(OpenGLContext* oglContext);
void deleteFramebuffer(OpenGLContext* oglContext);
bool isFramebufferComplete(OpenGLContext* oglContext, String* failReason) const;
void deleteOrReleaseOpenGLResources(OpenGLContext* oglContext);
static bool supportedOpenGL(OpenGLContext* oglContext);
private:
void setColorBufferVersionTick(uint index, uint versionTick);
private:
Collection<RenderbufferObject> m_colorRenderBuffers;
Collection<Texture> m_colorTextures;
std::map<uint, Texture::CubeMapFace> m_colorCubeMapFaces;
ref<RenderbufferObject> m_depthRenderBuffer;
ref<Texture> m_depthTexture2d;
ref<RenderbufferObject> m_depthStencilRenderBuffer;
ref<Texture> m_depthStencilTexture2d;
std::vector<uint> m_colorAttachmentVersionTicks;
uint m_depthAttachmentVersionTick;
ref<OglRcFramebuffer> m_oglRcBuffer;
};
}
@@ -0,0 +1,167 @@
//##################################################################################################
//
// 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 "cvfGeometryBuilderDrawableGeo.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::GeometryBuilderDrawableGeo
/// \ingroup Render
///
/// Builds geometry represented as a drawable geo.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
GeometryBuilderDrawableGeo::GeometryBuilderDrawableGeo()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint GeometryBuilderDrawableGeo::addVertices(const Vec3fArray& vertices)
{
uint numExistingVerts = static_cast<uint>(m_vertices.size());
size_t numNewVertices = vertices.size();
size_t i;
for (i = 0; i < numNewVertices; i++)
{
m_vertices.push_back(vertices[i]);
}
return numExistingVerts;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint GeometryBuilderDrawableGeo::vertexCount() const
{
return static_cast<uint>(m_vertices.size());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void GeometryBuilderDrawableGeo::transformVertexRange(uint startIdx, uint endIdx, const Mat4f& mat)
{
uint i;
for (i = startIdx; i <= endIdx; i++)
{
m_vertices[i].transformPoint(mat);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void GeometryBuilderDrawableGeo::addTriangle(uint i0, uint i1, uint i2)
{
m_faceList.push_back(3);
m_faceList.push_back(i0);
m_faceList.push_back(i1);
m_faceList.push_back(i2);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void GeometryBuilderDrawableGeo::addQuad(uint i0, uint i1, uint i2, uint i3)
{
m_faceList.push_back(4);
m_faceList.push_back(i0);
m_faceList.push_back(i1);
m_faceList.push_back(i2);
m_faceList.push_back(i3);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
/*
void GeometryBuilderDrawableGeo::addQuadByVertices(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2, const Vec3f& v3)
{
uint numExistingVerts = static_cast<uint>(m_vertices.size());
m_vertices.push_back(v0);
m_vertices.push_back(v1);
m_vertices.push_back(v2);
m_vertices.push_back(v3);
m_faceList.push_back(3);
m_faceList.push_back(numExistingVerts);
m_faceList.push_back(numExistingVerts + 1);
m_faceList.push_back(numExistingVerts + 2);
m_faceList.push_back(3);
m_faceList.push_back(numExistingVerts);
m_faceList.push_back(numExistingVerts + 2);
m_faceList.push_back(numExistingVerts + 3);
}
*/
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<DrawableGeo> GeometryBuilderDrawableGeo::drawableGeo() const
{
ref<DrawableGeo> geo = new DrawableGeo;
if (m_vertices.size() > 0)
{
ref<Vec3fArray> newVertexArray = new Vec3fArray(m_vertices);
geo->setVertexArray(newVertexArray.p());
}
size_t numFaceListEntries = m_faceList.size();
if (numFaceListEntries > 0)
{
// Need to cast away the const pointer, but should be safe since the UIntArray only has a short life in this scope
const uint* dataPtr = &m_faceList[0];
UIntArray faceList;
faceList.setSharedPtr(const_cast<uint*>(dataPtr), numFaceListEntries);
geo->setFromFaceList(faceList);
}
geo->computeNormals();
return geo;
}
} // namespace cvf
@@ -0,0 +1,54 @@
//##################################################################################################
//
// 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 "cvfGeometryBuilder.h"
#include "cvfDrawableGeo.h"
namespace cvf {
//==================================================================================================
//
// Concrete geometry builder class for building geometry to a drawable geo
//
//==================================================================================================
class GeometryBuilderDrawableGeo : public GeometryBuilder
{
public:
GeometryBuilderDrawableGeo();
//GeometryBuilderDrawableGeo(bool requireVerticesBeforeAdd = true);
virtual uint addVertices(const Vec3fArray& vertices);
virtual uint vertexCount() const;
virtual void transformVertexRange(uint startIdx, uint endIdx, const Mat4f& mat);
virtual void addTriangle(uint i0, uint i1, uint i2);
virtual void addQuad(uint i0, uint i1, uint i2, uint i3);
//virtual void addQuadByVertices(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2, const Vec3f& v3);
ref<DrawableGeo> drawableGeo() const;
private:
std::vector<Vec3f> m_vertices;
std::vector<uint> m_faceList;
};
}
+363
View File
@@ -0,0 +1,363 @@
//##################################################################################################
//
// 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 "cvfOpenGL.h"
#include "cvfGlyph.h"
#include "cvfMath.h"
#include "cvfTextureImage.h"
#include "cvfTexture.h"
#include "cvfRenderState.h"
#include "cvfSampler.h"
#ifndef CVF_OPENGL_ES
#include "cvfTexture2D_FF.h"
#include "cvfRenderState_FF.h"
#endif
namespace cvf {
//==================================================================================================
///
/// \class cvf::Glyph
/// \ingroup Render
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
/// \param character The character this glyph is generated from
//--------------------------------------------------------------------------------------------------
Glyph::Glyph(wchar_t character)
: m_character(character),
m_width(0),
m_height(0),
m_horizontalBearingX(0),
m_horizontalBearingY(0),
m_horizontalAdvance(0),
m_textureImage(new TextureImage),
m_textureCoordinates(new FloatArray(8))
{
// Lower left
m_textureCoordinates->set(0, 0.0f);
m_textureCoordinates->set(1, 0.0f);
// Lower right
m_textureCoordinates->set(2, 1.0f);
m_textureCoordinates->set(3, 0.0f);
// Upper right
m_textureCoordinates->set(4, 1.0f);
m_textureCoordinates->set(5, 1.0f);
// Upper left
m_textureCoordinates->set(6, 0.0f);
m_textureCoordinates->set(7, 1.0f);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Glyph::~Glyph()
{
}
//--------------------------------------------------------------------------------------------------
/// Get character this glyph is generated from
//--------------------------------------------------------------------------------------------------
wchar_t Glyph::character() const
{
return m_character;
}
//--------------------------------------------------------------------------------------------------
/// Set width of the pre-rendered character, in pixels.
///
/// \note May be smaller than texture image width. Use the texture coordinates to identify the glyph pixels.
///
/// \sa width(), setHeight(), height(), textureImage(), textureCoordinates()
//--------------------------------------------------------------------------------------------------
void Glyph::setWidth(uint width)
{
m_width = width;
}
//--------------------------------------------------------------------------------------------------
/// Get width of the pre-rendered character, in pixels.
///
/// \note May be smaller than texture image width. Use the texture coordinates to identify the glyph pixels.
///
/// \sa setWidth(), setHeight(), height(), textureImage(), textureCoordinates()
//--------------------------------------------------------------------------------------------------
uint Glyph::width() const
{
return m_width;
}
//--------------------------------------------------------------------------------------------------
/// Set height of the pre-rendered character, in pixels.
///
/// \note May be smaller than texture image height. Use the texture coordinates to identify the glyph pixels.
///
/// \sa height(), setWidth(), width(), textureImage(), textureCoordinates()
//--------------------------------------------------------------------------------------------------
void Glyph::setHeight(uint height)
{
m_height = height;
}
//--------------------------------------------------------------------------------------------------
/// Get height of the pre-rendered character, in pixels.
///
/// \note May be smaller than texture image height. Use the texture coordinates to identify the glyph pixels.
///
/// \sa setHeight(), setWidth(), width(), textureImage(), textureCoordinates()
//--------------------------------------------------------------------------------------------------
uint Glyph::height() const
{
return m_height;
}
//--------------------------------------------------------------------------------------------------
/// Set pre-rendered image of m_character
///
/// \sa textureImage(), width(), height()
//--------------------------------------------------------------------------------------------------
void Glyph::setTextureImage(TextureImage* textureImage)
{
m_textureImage = textureImage;
}
//--------------------------------------------------------------------------------------------------
/// Get pre-rendered image of m_character
///
/// \sa textureCoordinates(), width(), height()
//--------------------------------------------------------------------------------------------------
const TextureImage* Glyph::textureImage() const
{
return m_textureImage.p();
}
//--------------------------------------------------------------------------------------------------
/// Get texture coordinates
///
/// \sa textureImage(), width(), height()
//--------------------------------------------------------------------------------------------------
const FloatArray* Glyph::textureCoordinates() const
{
return m_textureCoordinates.p();
}
//--------------------------------------------------------------------------------------------------
/// Set horizontal distance from the current cursor position to the leftmost
/// border of the glyph image's bounding box
//--------------------------------------------------------------------------------------------------
void Glyph::setHorizontalBearingX(short bearing)
{
m_horizontalBearingX = bearing;
}
//--------------------------------------------------------------------------------------------------
/// Get horizontal distance from the current cursor position to the leftmost
/// border of the glyph image's bounding box
//--------------------------------------------------------------------------------------------------
short Glyph::horizontalBearingX() const
{
return m_horizontalBearingX;
}
//--------------------------------------------------------------------------------------------------
/// Set vertical distance from the current cursor position (on the baseline)
/// to the topmost border of the glyph image's bounding box.
//--------------------------------------------------------------------------------------------------
void Glyph::setHorizontalBearingY(short bearing)
{
m_horizontalBearingY = bearing;
}
//--------------------------------------------------------------------------------------------------
/// Get vertical distance from the current cursor position (on the baseline)
/// to the topmost border of the glyph image's bounding box.
//--------------------------------------------------------------------------------------------------
short Glyph::horizontalBearingY() const
{
return m_horizontalBearingY;
}
//--------------------------------------------------------------------------------------------------
/// Set horizontal distance used to increment the pen position
/// when the glyph is drawn as part of a string of text.
//--------------------------------------------------------------------------------------------------
void Glyph::setHorizontalAdvance(uint advance)
{
m_horizontalAdvance = advance;
}
//--------------------------------------------------------------------------------------------------
/// Get horizontal distance used to increment the pen position
/// when the glyph is drawn as part of a string of text.
//--------------------------------------------------------------------------------------------------
uint Glyph::horizontalAdvance() const
{
return m_horizontalAdvance;
}
//--------------------------------------------------------------------------------------------------
/// Setup and bind texture
//--------------------------------------------------------------------------------------------------
void Glyph::setupAndBindTexture(OpenGLContext* oglContext, bool software)
{
// Short path first if everything is in place
if (m_textureBindings.notNull())
{
RenderState::Type renderStateType = m_textureBindings->type();
if (software)
{
#ifndef CVF_OPENGL_ES
if (renderStateType == RenderState::TEXTURE_MAPPING_FF)
{
TextureMapping_FF* texMapping = static_cast<TextureMapping_FF*>(m_textureBindings.p());
texMapping->setupTexture(oglContext);
texMapping->applyOpenGL(oglContext);
return;
}
#else
CVF_FAIL_MSG("Not supported on OpenGL ES");
#endif
}
else
{
if (renderStateType == RenderState::TEXTURE_BINDINGS)
{
TextureBindings* texBindings = static_cast<TextureBindings*>(m_textureBindings.p());
texBindings->setupTextures(oglContext);
texBindings->applyOpenGL(oglContext);
return;
}
}
}
m_textureBindings = NULL;
if (m_textureBindings.isNull())
{
// TODO
// Revisit the code that sets up the texture image
// The code below ends up modifying the stored texture image
// Is this intentional - there is an external getter for the image!!
CVF_TIGHT_ASSERT(0 < m_textureImage->width());
CVF_TIGHT_ASSERT(0 < m_textureImage->height());
uint pow2Width = Math::roundUpPow2(m_width);
uint pow2Height = Math::roundUpPow2(m_height);
TextureImage* pow2Image = new TextureImage;
pow2Image->allocate(pow2Width, pow2Height);
pow2Image->fill(Color4ub(255, 255, 255, 0));
uint i, j;
for (j = 0; j < m_height; j++)
{
for (i = 0; i < m_width; i++)
{
pow2Image->setPixel(i, j, m_textureImage->pixel(i, j));
}
}
float textureCoordinateMaxX = static_cast<float>(m_width) / static_cast<float>(pow2Width);
float textureCoordinateMaxY = static_cast<float>(m_height) / static_cast<float>(pow2Height);
// Lower left
m_textureCoordinates->set(0, 0.0f);
m_textureCoordinates->set(1, 0.0f);
// Lower right
m_textureCoordinates->set(2, textureCoordinateMaxX);
m_textureCoordinates->set(3, 0.0f);
// Upper right
m_textureCoordinates->set(4, textureCoordinateMaxX);
m_textureCoordinates->set(5, textureCoordinateMaxY);
// Upper left
m_textureCoordinates->set(6, 0.0f);
m_textureCoordinates->set(7, textureCoordinateMaxY);
m_textureImage = pow2Image;
if (software)
{
#ifdef CVF_OPENGL_ES
CVF_FAIL_MSG("Not supported on OpenGL ES");
#else
// Use fixed function texture setup
ref<Texture2D_FF> texture = new Texture2D_FF(m_textureImage.p());
texture->setWrapMode(Texture2D_FF::CLAMP);
texture->setMinFilter(Texture2D_FF::NEAREST);
texture->setMagFilter(Texture2D_FF::NEAREST);
texture->setupTexture(oglContext);
texture->setupTextureParams(oglContext);
ref<TextureMapping_FF> textureMapping = new TextureMapping_FF(texture.p());
textureMapping->setTextureFunction(TextureMapping_FF::MODULATE);
m_textureBindings = textureMapping;
#endif
}
else
{
ref<Sampler> sampler = new Sampler;
sampler->setWrapMode(Sampler::CLAMP_TO_EDGE);
sampler->setMinFilter(Sampler::NEAREST);
sampler->setMagFilter(Sampler::NEAREST);
ref<Texture> texture = new Texture(m_textureImage.p());
texture->setupTexture(oglContext);
TextureBindings* textureBindings = new TextureBindings(texture.p(), sampler.p(), "dummy");
textureBindings->setupTextures(oglContext);
m_textureBindings = textureBindings;
}
}
if (m_textureBindings.notNull())
{
m_textureBindings->applyOpenGL(oglContext);
}
}
} // namespace cvf
+82
View File
@@ -0,0 +1,82 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfArray.h"
namespace cvf {
class TextureImage;
class RenderState;
class OpenGLContext;
//==================================================================================================
//
// Pre-rendered text character
//
//==================================================================================================
class Glyph : public Object
{
public:
Glyph(wchar_t character);
virtual ~Glyph();
wchar_t character() const;
void setWidth(uint width);
uint width() const;
void setHeight(uint height);
uint height() const;
void setTextureImage(TextureImage* textureImage);
const TextureImage* textureImage() const;
const FloatArray* textureCoordinates() const;
void setHorizontalBearingX(short bearing);
short horizontalBearingX() const;
void setHorizontalBearingY(short bearing);
short horizontalBearingY() const;
void setHorizontalAdvance(uint advance);
uint horizontalAdvance() const;
void setupAndBindTexture(OpenGLContext* oglContext, bool software);
private:
wchar_t m_character; // Character this glyph is generated from
// Size of the pre-rendered character in pixels.
// Note: May be smaller than the size of m_textureImage since this may contain alpha's and even more characters
uint m_width;
uint m_height;
// For horizontal text layouts
short m_horizontalBearingX; // Horizontal distance from the current cursor position to the leftmost border of the glyph image's bounding box.
short m_horizontalBearingY; // Vertical distance from the current cursor position (on the baseline) to the topmost border of the glyph image's bounding box.
uint m_horizontalAdvance; // Horizontal distance used to increment the pen position when the glyph is drawn as part of a string of text.
// 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
};
} // namespace cvf
@@ -0,0 +1,52 @@
//##################################################################################################
//
// 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 "cvfHitDetail.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::HitDetail
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
HitDetail::HitDetail()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
HitDetail::~HitDetail()
{
}
} // namespace cvf
@@ -0,0 +1,41 @@
//##################################################################################################
//
// 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 "cvfObject.h"
namespace cvf {
//==================================================================================================
//
// Base class for providing details from ray intersections with drawables
//
//==================================================================================================
class HitDetail : public Object
{
public:
HitDetail();
virtual ~HitDetail();
};
}
@@ -0,0 +1,39 @@
//##################################################################################################
//
// 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 "cvfLegendScalarMapper.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::LegendScalarMapper
/// \ingroup Render
///
/// Abstract base class for ScalarMapper's that communicate with a legend
///
//==================================================================================================
} // namespace cvf
@@ -0,0 +1,48 @@
//##################################################################################################
//
// 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 "cvfBase.h"
#include "cvfObject.h"
#include "cvfArray.h"
#include "cvfScalarMapper.h"
#include <vector>
namespace cvf {
//==================================================================================================
//
// Abstract base class for scalar mappers that communicate with a legend
//
//==================================================================================================
class LegendScalarMapper : public ScalarMapper
{
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;
};
}
@@ -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.
//
//##################################################################################################
// Doxygen module definition
/// \ingroup CeeVizFramework
/// @{
/// \defgroup Render Render module
/// @}
#include "cvfBufferObjectManaged.h"
#include "cvfCamera.h"
#include "cvfDrawable.h"
#include "cvfDrawableGeo.h"
#include "cvfDrawableText.h"
#include "cvfDrawableVectors.h"
#include "cvfFixedAtlasFont.h"
#include "cvfFont.h"
#include "cvfFontManager.h"
#include "cvfFramebufferObject.h"
#include "cvfGeometryBuilderDrawableGeo.h"
#include "cvfGlyph.h"
#include "cvfHitDetail.h"
#include "cvfMatrixState.h"
#include "cvfOpenGL.h"
#include "cvfOglRc.h"
#include "cvfOpenGLCapabilities.h"
#include "cvfOpenGLContext.h"
#include "cvfOpenGLContextGroup.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfOpenGLTypes.h"
#include "cvfOverlayAxisCross.h"
#include "cvfOverlayColorLegend.h"
#include "cvfOverlayItem.h"
#include "cvfOverlayTextBox.h"
#include "cvfPrimitiveSet.h"
#include "cvfPrimitiveSetDirect.h"
#include "cvfPrimitiveSetIndexedUInt.h"
#include "cvfPrimitiveSetIndexedUShort.h"
#include "cvfPrimitiveSetIndexedUIntScoped.h"
#include "cvfRenderbufferObject.h"
#include "cvfRenderState.h"
#include "cvfRenderStateSet.h"
#include "cvfRenderStateTracker.h"
#include "cvfSampler.h"
#include "cvfScalarMapper.h"
#include "cvfScalarMapperUniformLevels.h"
#include "cvfShader.h"
#include "cvfShaderSourceProvider.h"
#include "cvfShaderProgram.h"
#include "cvfShaderProgramGenerator.h"
#include "cvfShaderSourceRepository.h"
#include "cvfShaderSourceRepositoryFile.h"
#include "cvfTexture.h"
#include "cvfTextureImage.h"
#include "cvfUniform.h"
#include "cvfUniformSet.h"
#include "cvfVertexAttribute.h"
#include "cvfVertexBundle.h"
#include "cvfViewport.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#include "cvfTexture2D_FF.h"
#endif
@@ -0,0 +1,312 @@
//##################################################################################################
//
// 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 "cvfMatrixState.h"
#include "cvfCamera.h"
#include "cvfViewport.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::MatrixState
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
MatrixState::MatrixState(const Camera& camera)
: m_projectionMatrix(camera.projectionMatrix()),
m_viewMatrix(camera.viewMatrix()),
m_modelMatrix(),
m_modelMatrixIsSet(false),
m_viewProjectionMatrix(m_projectionMatrix*m_viewMatrix),
m_viewportPosition(static_cast<uint>(camera.viewport()->x()), static_cast<uint>(camera.viewport()->y())),
m_viewportSize(static_cast<uint>(camera.viewport()->width()), static_cast<uint>(camera.viewport()->height())),
m_pixelHeightAtUnitDistance(0.0f),
m_versionTick(1)
{
// This won't work for orthographic
//m_pixelSize = static_cast<float>(2.0*Math::tan(Math::toRadians(camera.fieldOfViewYDeg()/2.0))/m_viewportSize.y());
computePixelHeight();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
MatrixState::MatrixState(const Vec2ui& viewportPosition, const Vec2ui& viewportSize, const Mat4d& projectionMatrix, const Mat4d& viewMatrix)
: m_projectionMatrix(projectionMatrix),
m_viewMatrix(viewMatrix),
m_modelMatrix(),
m_modelMatrixIsSet(false),
m_viewProjectionMatrix(m_projectionMatrix*m_viewMatrix),
m_viewportPosition(viewportPosition),
m_viewportSize(viewportSize),
m_pixelHeightAtUnitDistance(0.0f),
m_versionTick(1)
{
computePixelHeight();
}
//--------------------------------------------------------------------------------------------------
/// Computes height of a pixel at unit distance in world system
//--------------------------------------------------------------------------------------------------
void MatrixState::computePixelHeight()
{
// We're computing a pixelSize at a distance of 1 from camera/eye.
// Strategy is to transform a sample point using the projection matrix, and then determine it's relative height in the viewport
Vec4f p = m_projectionMatrix*Vec4f(0, 1, -1, 1);
p /= p.w();
// We're now in normalized device coordinates. (cube of (-1, 1))
// Divide to find relative height
float relHeight = p.y()/2.0f;
float viewportHeight = static_cast<float>(m_viewportSize.y());
if (relHeight*viewportHeight > 0.0f)
{
m_pixelHeightAtUnitDistance = 1.0f/(relHeight*viewportHeight);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void MatrixState::setModelMatrix(const Mat4d& modelMatrix)
{
m_modelMatrix.set(modelMatrix);
m_modelMatrixIsSet = true;
m_versionTick++;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void MatrixState::clearModelMatrix()
{
if (m_modelMatrixIsSet)
{
m_modelMatrixIsSet = false;
m_versionTick++;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Mat4f& MatrixState::projectionMatrix() const
{
return m_projectionMatrix;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Mat4f& MatrixState::viewMatrix() const
{
return m_viewMatrix;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Mat4f MatrixState::viewMatrixInverse() const
{
return m_viewMatrix.getInverted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Mat4f& MatrixState::modelMatrix() const
{
if (m_modelMatrixIsSet)
{
return m_modelMatrix;
}
else
{
return Mat4f::IDENTITY;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Mat4f MatrixState::modelMatrixInverse() const
{
if (m_modelMatrixIsSet)
{
return m_modelMatrix.getInverted();
}
else
{
return Mat4f::IDENTITY;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Mat4f MatrixState::modelMatrixInverseTranspose() const
{
if (m_modelMatrixIsSet)
{
return m_modelMatrix.getInverted().getTransposed();
}
else
{
return Mat4f::IDENTITY;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Mat4f MatrixState::modelViewMatrix() const
{
if (m_modelMatrixIsSet)
{
return m_viewMatrix*m_modelMatrix;
}
else
{
return m_viewMatrix;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Mat4f MatrixState::modelViewMatrixInverse() const
{
if (m_modelMatrixIsSet)
{
return (m_viewMatrix*m_modelMatrix).getInverted();
}
else
{
return m_viewMatrix.getInverted();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Mat4f MatrixState::modelViewProjectionMatrix() const
{
if (m_modelMatrixIsSet)
{
return m_viewProjectionMatrix*m_modelMatrix;
}
else
{
return m_viewProjectionMatrix;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Mat4f MatrixState::modelViewProjectionMatrixInverse() const
{
if (m_modelMatrixIsSet)
{
return (m_viewProjectionMatrix*m_modelMatrix).getInverted();
}
else
{
return m_viewProjectionMatrix.getInverted();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Mat3f MatrixState::normalMatrix() const
{
Mat3f normMatr = modelViewMatrix().toMatrix3();
normMatr.invert();
normMatr.transpose();
return normMatr;
}
//--------------------------------------------------------------------------------------------------
/// Height (size) of a pixel at unit distance in world system.
///
/// For perspective projections this value must be multiplied by the distance to the point in question
//--------------------------------------------------------------------------------------------------
float MatrixState::pixelHeightAtUnitDistance() const
{
return m_pixelHeightAtUnitDistance;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Vec2ui MatrixState::viewportPosition() const
{
return m_viewportPosition;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Vec2ui MatrixState::viewportSize() const
{
return m_viewportSize;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint MatrixState::versionTick() const
{
return m_versionTick;
}
} // namespace cvf
@@ -0,0 +1,82 @@
//##################################################################################################
//
// 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 "cvfMatrix4.h"
namespace cvf {
class Camera;
//==================================================================================================
//
//
//
//==================================================================================================
class MatrixState
{
public:
MatrixState(const Camera& camera);
MatrixState(const Vec2ui& viewportPosition, const Vec2ui& viewportSize, const Mat4d& projectionMatrix, const Mat4d& viewMatrix);
void setModelMatrix(const Mat4d& modelMatrix);
void clearModelMatrix();
const Mat4f& projectionMatrix() const;
const Mat4f& viewMatrix() const;
Mat4f viewMatrixInverse() const;
const Mat4f& modelMatrix() const;
Mat4f modelMatrixInverse() const;
Mat4f modelMatrixInverseTranspose() const;
Mat4f modelViewMatrix() const;
Mat4f modelViewMatrixInverse() const;
Mat4f modelViewProjectionMatrix() const;
Mat4f modelViewProjectionMatrixInverse() const;
Mat3f normalMatrix() const;
float pixelHeightAtUnitDistance() const;
Vec2ui viewportPosition() const;
Vec2ui viewportSize() const;
uint versionTick() const;
private:
void computePixelHeight();
private:
Mat4f m_projectionMatrix; // Float version of projection matrix (as specified by user)
Mat4f m_viewMatrix; // Float version of view matrix (as specified by user)
Mat4f m_modelMatrix; // Float version of model matrix (as specified by user)
bool m_modelMatrixIsSet; // Set to true when a model matrix is set, false when no model matrix is currently set
Mat4f m_viewProjectionMatrix; // Combined view matrix and projection matrix
Vec2ui m_viewportPosition; // Position of the viewport
Vec2ui m_viewportSize; // Size of the viewport
float m_pixelHeightAtUnitDistance;// Height of a pixel at unit distance (distance of 1.0 from camera) in world system. For perspective projections this value must be multiplied by the distance to the point in question
uint m_versionTick; // Versioning to be able to detect changes
};
}
+317
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 "cvfOglRc.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::OglRc
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OglRc::OglRc()
: m_openGLObjId(0)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OglRc::~OglRc()
{
// The actual OpenGL object should be gone by now!
CVF_ASSERT(m_openGLObjId == 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OglId OglRc::oglId() const
{
return m_openGLObjId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OglId OglRc::safeOglId(const OglRc* oglRcObj)
{
if (oglRcObj)
{
return oglRcObj->oglId();
}
else
{
return 0;
}
}
//--------------------------------------------------------------------------------------------------
/// Is it safe to release and potentially trigger the destructor
///
/// The requirement is that the object either
/// * doesn't contain any OpenGL resource
/// * that someone else is holding a reference to the object (assuming they will do proper cleanup)
//--------------------------------------------------------------------------------------------------
bool OglRc::isSafeToRelease(const OglRc* oglRcObj)
{
if (oglRcObj)
{
if (oglRcObj->refCount() == 1)
{
if (oglRcObj->oglId() != 0)
{
return false;
}
}
}
return true;
}
//==================================================================================================
///
/// \class cvf::OglRcShader
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<OglRcShader> OglRcShader::create(OpenGLContext* oglContext, cvfGLenum shaderType)
{
CVF_CALLSITE_OPENGL(oglContext);
ref<OglRcShader> rcObj = new OglRcShader;
rcObj->m_openGLObjId = glCreateShader(shaderType);
if (rcObj->m_openGLObjId != 0)
{
return rcObj;
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OglRcShader::deleteResource(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
if (m_openGLObjId != 0)
{
glDeleteShader(m_openGLObjId);
m_openGLObjId = 0;
}
}
//==================================================================================================
///
/// \class cvf::OglRcProgram
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<OglRcProgram> OglRcProgram::create(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
ref<OglRcProgram> rcObj = new OglRcProgram;
rcObj->m_openGLObjId = glCreateProgram();
if (rcObj->m_openGLObjId != 0)
{
return rcObj;
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OglRcProgram::deleteResource(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
if (m_openGLObjId != 0)
{
glDeleteProgram(m_openGLObjId);
m_openGLObjId = 0;
}
}
//==================================================================================================
///
/// \class cvf::OglRcTexture
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<OglRcTexture> OglRcTexture::create(OpenGLContext* /*oglContext*/)
{
ref<OglRcTexture> rcObj = new OglRcTexture;
glGenTextures(1, &rcObj->m_openGLObjId);
if (rcObj->m_openGLObjId != 0)
{
return rcObj;
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OglRcTexture::deleteResource(OpenGLContext* /*oglContext*/)
{
if (m_openGLObjId != 0)
{
glDeleteTextures(1, &m_openGLObjId);
m_openGLObjId = 0;
}
}
//==================================================================================================
///
/// \class cvf::OglRcRenderbuffer
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<OglRcRenderbuffer> OglRcRenderbuffer::create(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
ref<OglRcRenderbuffer> rcObj = new OglRcRenderbuffer;
glGenRenderbuffers(1, &rcObj->m_openGLObjId);
if (rcObj->m_openGLObjId != 0)
{
return rcObj;
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OglRcRenderbuffer::deleteResource(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
if (m_openGLObjId != 0)
{
glDeleteRenderbuffers(1, &m_openGLObjId);
m_openGLObjId = 0;
}
}
//==================================================================================================
///
/// \class cvf::OglRcFramebuffer
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<OglRcFramebuffer> OglRcFramebuffer::create(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
ref<OglRcFramebuffer> rcObj = new OglRcFramebuffer;
glGenFramebuffers(1, &rcObj->m_openGLObjId);
if (rcObj->m_openGLObjId != 0)
{
return rcObj;
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OglRcFramebuffer::deleteResource(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
if (m_openGLObjId != 0)
{
glDeleteFramebuffers(1, &m_openGLObjId);
m_openGLObjId = 0;
}
}
} // namespace cvf
+122
View File
@@ -0,0 +1,122 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfOpenGLTypes.h"
namespace cvf {
class OpenGLContext;
//==================================================================================================
//
//
//
//==================================================================================================
class OglRc : public Object
{
public:
~OglRc();
OglId oglId() const;
virtual void deleteResource(OpenGLContext* oglContext) = 0;
static OglId safeOglId(const OglRc* oglRcObj);
static bool isSafeToRelease(const OglRc* oglRcObj);
protected:
OglRc();
protected:
OglId m_openGLObjId; // The OpenGL object identifier (object name in OGL lingo). 0 means that no handle exists
};
//==================================================================================================
//
//
//
//==================================================================================================
class OglRcShader : public OglRc
{
public:
static ref<OglRcShader> create(OpenGLContext* oglContext, cvfGLenum shaderType);
virtual void deleteResource(OpenGLContext* oglContext);
};
//==================================================================================================
//
//
//
//==================================================================================================
class OglRcProgram : public OglRc
{
public:
static ref<OglRcProgram> create(OpenGLContext* oglContext);
virtual void deleteResource(OpenGLContext* oglContext);
};
//==================================================================================================
//
//
//
//==================================================================================================
class OglRcTexture : public OglRc
{
public:
static ref<OglRcTexture> create(OpenGLContext* oglContext);
virtual void deleteResource(OpenGLContext* oglContext);
};
//==================================================================================================
//
//
//
//==================================================================================================
class OglRcRenderbuffer : public OglRc
{
public:
static ref<OglRcRenderbuffer> create(OpenGLContext* oglContext);
virtual void deleteResource(OpenGLContext* oglContext);
};
//==================================================================================================
//
//
//
//==================================================================================================
class OglRcFramebuffer : public OglRc
{
public:
static ref<OglRcFramebuffer> create(OpenGLContext* oglContext);
virtual void deleteResource(OpenGLContext* oglContext);
};
}
@@ -0,0 +1,217 @@
//##################################################################################################
//
// 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 "cvfOpenGL.h"
#include "cvfSystem.h"
// Get rid of warnings from glew
#ifdef WIN32
#pragma warning (disable: 4706 4365 4191 4668)
#endif
CVF_GCC_DIAGNOSTIC_IGNORE("-Wconversion")
#ifndef CVF_OPENGL_ES
#undef glewGetContext
extern "C"
{
#include "glew/glew.c"
}
#endif // CVF_OPENGL_ES
namespace cvf {
//==================================================================================================
///
/// \class cvf::OpenGL
/// \ingroup Render
///
/// Static class providing OpenGL wrappers and helpers
///
//==================================================================================================
bool OpenGL::m_enableCheckOgl = true;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGL::hasOpenGLError(OpenGLContext* oglContext)
{
// glGetError will end up in an endless loop if no context is current
CVF_ASSERT(oglContext);
CVF_ASSERT(oglContext->isCurrent());
CVF_UNUSED(oglContext);
cvfGLenum err = glGetError();
if (err == GL_NO_ERROR)
{
return false;
}
else
{
// Empty all error flags
while (err != GL_NO_ERROR)
{
err = glGetError();
}
return true;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OpenGL::clearOpenGLError(OpenGLContext* oglContext)
{
// glGetError will end up in an endless loop if no context is current
CVF_ASSERT(oglContext);
CVF_ASSERT(oglContext->isCurrent());
CVF_UNUSED(oglContext);
cvfGLenum err = glGetError();
// Empty all error flags
while (err != GL_NO_ERROR)
{
err = glGetError();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String OpenGL::mapOpenGLErrorToString(cvfGLenum errorCode)
{
String errCodeStr;
switch (errorCode)
{
case GL_INVALID_ENUM: errCodeStr = "GL_INVALID_ENUM"; break;
case GL_INVALID_VALUE: errCodeStr = "GL_INVALID_VALUE"; break;
case GL_INVALID_OPERATION: errCodeStr = "GL_INVALID_OPERATION"; break;
case GL_OUT_OF_MEMORY: errCodeStr = "GL_OUT_OF_MEMORY"; break;
#ifndef CVF_OPENGL_ES
case GL_STACK_OVERFLOW: errCodeStr = "GL_STACK_OVERFLOW"; break;
case GL_STACK_UNDERFLOW: errCodeStr = "GL_STACK_UNDERFLOW"; break;
#endif
case GL_NO_ERROR: errCodeStr = "GL_NO_ERROR"; break;
default:
{
char szBuf[101];
System::sprintf(szBuf, 100, "0x%04x", errorCode);
errCodeStr = szBuf;
}
}
return errCodeStr;
}
//--------------------------------------------------------------------------------------------------
/// Returns false if no error.
//--------------------------------------------------------------------------------------------------
bool OpenGL::testAndReportOpenGLError(OpenGLContext* oglContext, const char* operation, const char* fileName, int line)
{
// glGetError will end up in an endless loop if no context is current
CVF_ASSERT(oglContext);
CVF_ASSERT(oglContext->isCurrent());
cvfGLenum err = glGetError();
if (err == GL_NO_ERROR)
{
return false;
}
Logger* logger = oglContext->group()->logger();
while (err != GL_NO_ERROR)
{
if (logger)
{
String errCodeStr = mapOpenGLErrorToString(err);
String msg = String("Operation: ") + operation;
msg += "OGL(" + errCodeStr + "): ";
logger->error(msg, fileName, line);
}
err = glGetError();
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OpenGL::cvf_check_ogl(OpenGLContext* oglContext, const char* fileName, int line)
{
if (OpenGL::m_enableCheckOgl)
{
cvfGLenum err = glGetError();
while (err != GL_NO_ERROR)
{
// glGetError will end up in an endless loop if no context is current
CVF_ASSERT(oglContext);
CVF_ASSERT(oglContext->isCurrent());
Logger* logger = oglContext->group()->logger();
if (logger)
{
String errCodeStr = mapOpenGLErrorToString(err);
String msg = "OGL(" + errCodeStr + "): ";
logger->error(msg, fileName, line);
}
err = glGetError();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OpenGL::enableCheckOgl(bool enable)
{
m_enableCheckOgl = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGL::isCheckOglEnabled()
{
return m_enableCheckOgl;
}
} // namespace cvf
+130
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.
//
//##################################################################################################
#pragma once
// Currently we utilize GLEW everywhere except for OpenGLES
#ifndef CVF_OPENGL_ES
#define CVF_USE_GLEW
#endif
#ifdef CVF_USE_GLEW
// Define GLEW_MX for thread safe multi OpenGL context use in GLEW.
// On WIN32 the GLEW_MX define causes GLEW to store both the function pointers and the GLEW
// vars (such as __GLEW_VERSION_1_1 and __GLEW_ARB_draw_buffers) inside GLEWContextStruct.
// On other platforms GLEW stores the function pointers in global variables while the GLEW vars
// are stored inside the GLEWContextStruct.
// We also need to define the glewGetContext() macro - see definition of the CVF_CALLSITE_OPENGL macro above
#define GLEW_MX
#define glewGetContext() (cvfLocGLEWCtxPtr)
// Need to define GLEW_STATIC since we're not using GLEW as a DLL
#define GLEW_STATIC
#include "glew/GL/glew.h"
#endif // CVF_USE_GLEW
// Define macros that must be used wherever we're going to do OpenGL calls (via GLEW)
// Use CVF_CALLSITE_OPENGL when you're going to call OpenGL functions. If you're going
// to query GLEW variables (and possibly do OpenGL calls), use CVF_CALLSITE_GLEW instead
// The reason for having two macros is that most of the time we don't need the pointer
// to the GLEW structure on non-WIN32 platforms since the actual function pointers
// are stored in global variables and only the GLEW vars are stored in the struct.
#define CVF_CALLSITE_GLEW(CURR_OGL_CTX_PTR) \
GLEWContextStruct* cvfLocGLEWCtxPtr = CURR_OGL_CTX_PTR->group()->glewContextStruct()
#ifdef WIN32
#define CVF_CALLSITE_OPENGL(CURR_OGL_CTX_PTR) CVF_CALLSITE_GLEW(CURR_OGL_CTX_PTR)
#else
#define CVF_CALLSITE_OPENGL(CURR_OGL_CTX_PTR) CVF_UNUSED(CURR_OGL_CTX_PTR)
#endif
#if defined(WIN32) || defined(CVF_LINUX)
// Windows and Linux includes
#include <GL/gl.h>
#include <GL/glu.h>
#elif defined(CVF_IOS)
// iOS includes
#include "OpenGLES/ES2/gl.h"
#include "OpenGLES/ES2/glext.h"
#elif defined(CVF_OSX)
// Mac OSX includes
#include "OpenGL/gl.h"
#include "OpenGL/glu.h"
#endif
#include "cvfOpenGLTypes.h"
#include "cvfString.h"
// As long as we're using GLEW we will almost always need the context and context group when doing OpenGL calls
#include "cvfOpenGLContext.h"
#include "cvfOpenGLContextGroup.h"
namespace cvf {
//==================================================================================================
//
// Static class providing OpenGL wrappers and helpers
//
//==================================================================================================
class OpenGL
{
public:
static bool hasOpenGLError(OpenGLContext* oglContext);
static void clearOpenGLError(OpenGLContext* oglContext);
static String mapOpenGLErrorToString(cvfGLenum errorCode);
static bool testAndReportOpenGLError(OpenGLContext* oglContext, const char* operation, const char* fileName, int line);
static void cvf_check_ogl(OpenGLContext* oglContext, const char* fileName, int line);
static void enableCheckOgl(bool enable);
static bool isCheckOglEnabled();
private:
static bool m_enableCheckOgl;
};
}
// Define used for specifying buffer offset for glVertexAttribPointer
#define CVF_OGL_BUFFER_OFFSET(BYTE_OFFSET) ((char*)NULL + (BYTE_OFFSET))
// Define used to log error messages with file and line
#define CVF_CHECK_OGL(OGL_CTX_PTR) cvf::OpenGL::cvf_check_ogl(OGL_CTX_PTR, __FILE__, __LINE__)
#define CVF_CLEAR_OGL_ERROR(OGL_CTX_PTR) cvf::OpenGL::clearOpenGLError(OGL_CTX_PTR)
#define CVF_TEST_AND_REPORT_OPENGL_ERROR(OGL_CTX_PTR, OPERATION) cvf::OpenGL::testAndReportOpenGLError(OGL_CTX_PTR, OPERATION, __FILE__, __LINE__)
@@ -0,0 +1,147 @@
//##################################################################################################
//
// 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 "cvfOpenGLCapabilities.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::OpenGLCapabilities
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OpenGLCapabilities::OpenGLCapabilities()
: m_capabilityFlags(0),
m_openGLMajorVersion(1),
m_supportsFixedFunction(false)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OpenGLCapabilities::OpenGLCapabilities(const OpenGLCapabilities& other)
: Object()
{
*this = other;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OpenGLCapabilities::~OpenGLCapabilities()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OpenGLCapabilities& OpenGLCapabilities::operator=(const OpenGLCapabilities& rhs)
{
m_capabilityFlags = rhs.m_capabilityFlags;
m_openGLMajorVersion = rhs.m_openGLMajorVersion;
m_supportsFixedFunction = rhs.m_supportsFixedFunction;
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGLCapabilities::hasCapability(Capability capability) const
{
return (m_capabilityFlags & capability) ? true : false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OpenGLCapabilities::addCapablity(Capability capability)
{
m_capabilityFlags |= capability;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OpenGLCapabilities::removeCapablity(Capability capability)
{
m_capabilityFlags &= (~capability);
}
//--------------------------------------------------------------------------------------------------
/// Do we have baseline OpenGL support. Currently this is defined to OpenGL 2.0 support
//--------------------------------------------------------------------------------------------------
bool OpenGLCapabilities::supportsOpenGL2() const
{
return (m_openGLMajorVersion >= 2);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGLCapabilities::supportsOpenGLVer(uint majorVer) const
{
return (m_openGLMajorVersion >= majorVer);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGLCapabilities::supportsFixedFunction() const
{
return m_supportsFixedFunction;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OpenGLCapabilities::configureOpenGLSupport(uint openGLMajorVer)
{
m_openGLMajorVersion = openGLMajorVer;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OpenGLCapabilities::setSupportsFixedFunction(bool fixedFunction)
{
m_supportsFixedFunction = fixedFunction;
}
} // namespace cvf
@@ -0,0 +1,72 @@
//##################################################################################################
//
// 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 "cvfObject.h"
namespace cvf {
//==================================================================================================
//
//
//
//==================================================================================================
class OpenGLCapabilities : public Object
{
public:
enum Capability
{
FRAMEBUFFER_OBJECT = 0x00000001, // Supports framebuffer objects
GENERATE_MIPMAP_FUNC = 0x00000002, // Is the glGenerateMipmap() function supported. (req OGL 3.0 or ARB_framebuffer_object)
TEXTURE_FLOAT = 0x00000004, // Floating-point internal texture formats. (req OGL 3.0 or ARB_texture_float)
TEXTURE_RG = 0x00000008, // One- and two- component internal texture formats. (req. OGL 3.0 or ARB_texture_rg)
TEXTURE_RECTANGLE = 0x00000010 // Rectangular textures (req. OGL 3.1 or GL_ARB_texture_rectangle
};
public:
OpenGLCapabilities();
OpenGLCapabilities(const OpenGLCapabilities& other);
~OpenGLCapabilities();
OpenGLCapabilities& operator=(const OpenGLCapabilities& rhs);
bool hasCapability(Capability capability) const;
void addCapablity(Capability capability);
void removeCapablity(Capability capability);
bool supportsOpenGL2() const;
bool supportsOpenGLVer(uint majorVer) const;
bool supportsFixedFunction() const;
void configureOpenGLSupport(uint openGLMajorVer);
void setSupportsFixedFunction(bool fixedFunction);
private:
uint m_capabilityFlags; // Bitwise or combination of the capabilities
uint m_openGLMajorVersion; // The supported OpenGL version, default to 1.1. (Currently our baseline support requires OpenGL 2.0)
bool m_supportsFixedFunction; // Is fixed function supported?
};
}
@@ -0,0 +1,188 @@
//##################################################################################################
//
// 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 "cvfOpenGLContext.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfTrace.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::OpenGLContext
/// \ingroup Render
///
/// Encapsulates an OpenGL rendering context
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
///
/// The context will be added unconditionally to the \a contextGroup group
//--------------------------------------------------------------------------------------------------
OpenGLContext::OpenGLContext(OpenGLContextGroup* contextGroup)
: m_contextGroup(contextGroup),
m_isValid(false)
{
CVF_ASSERT(m_contextGroup);
m_contextGroup->addContext(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OpenGLContext::~OpenGLContext()
{
//Trace::show("OpenGLContext destructor");
m_isValid = false;
// Context group is holding references to contexts, so by the time we get to this
// destructor the link to the context group must already be broken
CVF_ASSERT(m_contextGroup == NULL);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGLContext::isContextValid() const
{
// Also check on context group, since it may have been set to NULL after valid flag was set
if (m_contextGroup && m_isValid)
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGLContext::initializeContext()
{
makeCurrent();
if (!m_contextGroup)
{
return false;
}
if (!m_contextGroup->isContextGroupInitialized())
{
if (!m_contextGroup->initializeContextGroup(this))
{
return false;
}
}
m_isValid = true;
return true;
}
//--------------------------------------------------------------------------------------------------
/// Prepare the context for deletion
///
/// Prepares the context for deletion by removing the context from its context group. If this is the
/// last context in the context group, this function will also try and delete the context group's
/// OpenGL resources.
///
/// \warning After calling this function the context is no longer usable and should be deleted.
/// \warning May try and make the context current in order to free resources if this context
/// is the last context in the context group.
//--------------------------------------------------------------------------------------------------
void OpenGLContext::shutdownContext()
{
if (m_contextGroup)
{
CVF_ASSERT(m_contextGroup->containsContext(this));
// If our ref count is down to 1, there is probably something strange going on.
// Since one reference to us is being held by the context group, this means that the
// caller ISN'T holding a reference which may give him a nast surprise when this function returns!
CVF_ASSERT(refCount() > 1);
// This call will remove the context from the group AND clean up resources in the
// group if we are the last context in the group
m_contextGroup->contextAboutToBeShutdown(this);
}
CVF_ASSERT(m_contextGroup == NULL);
m_isValid = false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OpenGLContextGroup* OpenGLContext::group()
{
return m_contextGroup;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const OpenGLContextGroup* OpenGLContext::group() const
{
return m_contextGroup;
}
//--------------------------------------------------------------------------------------------------
/// Get the resource manager to use with this context
///
/// This is a convenience function for getting the resource manager from the owner context group.
//--------------------------------------------------------------------------------------------------
OpenGLResourceManager* OpenGLContext::resourceManager()
{
CVF_ASSERT(m_contextGroup);
return m_contextGroup->resourceManager();
}
//--------------------------------------------------------------------------------------------------
/// Get the capabilities for this context
///
/// This is a convenience function for getting the capabilities from the owner context group.
//--------------------------------------------------------------------------------------------------
const OpenGLCapabilities* OpenGLContext::capabilities()
{
CVF_ASSERT(m_contextGroup);
return m_contextGroup->capabilities();
}
} // namespace cvf
@@ -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 "cvfObject.h"
#include "cvfOpenGLContextGroup.h"
namespace cvf {
class OpenGLResourceManager;
class OpenGLCapabilities;
//==================================================================================================
//
// Encapsulates an OpenGL rendering context
//
//==================================================================================================
class OpenGLContext : public Object
{
public:
OpenGLContext(OpenGLContextGroup* contextGroup);
virtual ~OpenGLContext();
bool isContextValid() const;
virtual bool initializeContext();
virtual void shutdownContext();
virtual void makeCurrent() = 0;
virtual bool isCurrent() const = 0;
OpenGLContextGroup* group();
const OpenGLContextGroup* group() const;
OpenGLResourceManager* resourceManager();
const OpenGLCapabilities* capabilities();
private:
OpenGLContextGroup* m_contextGroup; // Raw pointer (to avoid circular reference) to the context group that this context belongs to.
bool m_isValid; // Will be set to true after successful initialization
friend class OpenGLContextGroup;
};
#define CVF_LOG_RENDER_ERROR(OGL_CTX_PTR, THE_MESSAGE) OGL_CTX_PTR->group()->logger()->error((THE_MESSAGE), __FILE__, __LINE__ )
#define CVF_LOG_RENDER_DEBUG(OGL_CTX_PTR, THE_MESSAGE) OGL_CTX_PTR->group()->logger()->debug((THE_MESSAGE), __FILE__, __LINE__ )
#define CVF_SHOULD_LOG_RENDER_DEBUG(OGL_CTX_PTR) OGL_CTX_PTR->group()->logger()->isDebugEnabled()
}
@@ -0,0 +1,378 @@
//##################################################################################################
//
// 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 "cvfOpenGLContextGroup.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLContext.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfOpenGLCapabilities.h"
#include "cvfTrace.h"
#include <memory.h>
namespace cvf {
//==================================================================================================
///
/// \class cvf::OpenGLContextGroup
/// \ingroup Render
///
/// A context group associates OpenGLContext instances that share OpenGL resources such as
/// shader objects, textures and buffer objects. Contexts added to the group must be compatible from
/// OpenGL's perspective - that is they must use identical (pixel) formats.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OpenGLContextGroup::OpenGLContextGroup()
: m_isInitialized(false),
m_glewContextStruct(NULL)
{
m_resourceManager = new OpenGLResourceManager;
m_logger = new Logger;
m_capabilities = new OpenGLCapabilities;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OpenGLContextGroup::~OpenGLContextGroup()
{
//Trace::show("OpenGLContextGroup destructor");
// Our resource manager must already be clean
// There is no way of safely deleting the resources after all the contexts have been removed
CVF_ASSERT(m_resourceManager.notNull());
CVF_ASSERT(!m_resourceManager->hasAnyOpenGLResources());
// We're about to die, so make sure we disentangle from the contexts
// This is important since all the contexts have back raw pointers to the group
size_t numContexts = m_contexts.size();
size_t i;
for (i = 0; i < numContexts; i++)
{
OpenGLContext* ctx = m_contexts.at(i);
ctx->m_contextGroup = NULL;
}
m_contexts.clear();
uninitializeContextGroup();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGLContextGroup::isContextGroupInitialized() const
{
return m_isInitialized;
}
//--------------------------------------------------------------------------------------------------
/// Do initialization of this context group
///
/// It is safe to call this function multiple times, successive calls will do nothing if the
/// context group is already initialized.
///
/// \warning The context passed inn \a currentContext must be the current context and it must
/// be a member of this context group.
//--------------------------------------------------------------------------------------------------
bool OpenGLContextGroup::initializeContextGroup(OpenGLContext* currentContext)
{
CVF_ASSERT(currentContext);
CVF_ASSERT(currentContext->isCurrent());
CVF_ASSERT(containsContext(currentContext));
if (!m_isInitialized)
{
#ifdef CVF_USE_GLEW
if (!initializeGLEW(currentContext))
{
return false;
}
configureCapablititesFromGLEW(currentContext);
#endif
m_isInitialized = true;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OpenGLContextGroup::uninitializeContextGroup()
{
CVF_ASSERT(m_contexts.size() == 0);
CVF_ASSERT(!m_resourceManager->hasAnyOpenGLResources());
// Just replace capablities with a new object
m_capabilities = new OpenGLCapabilities;
#ifdef CVF_USE_GLEW
delete m_glewContextStruct;
#endif
m_glewContextStruct = NULL;
m_isInitialized = false;
}
//--------------------------------------------------------------------------------------------------
/// Called by OpenGLContext objects when they are being shut down
///
/// This function will remove the context \a contextToShutdown from the context group.
/// If \a contextToShutdown is the last context in the group, all resources in the group's
/// resource manager will be deleted and the context group will be reset to uninitialized.
///
/// \warning This function may try and make the context passed in \a contextToShutdown curreent!
//--------------------------------------------------------------------------------------------------
void OpenGLContextGroup::contextAboutToBeShutdown(OpenGLContext* contextToShutdown)
{
CVF_ASSERT(contextToShutdown);
CVF_ASSERT(containsContext(contextToShutdown));
// If this is the last context in the group, we'll delete all the OpenGL resources in the s resource manager before we go
bool shouldUninitializeGroup = false;
if (contextCount() == 1)
{
CVF_ASSERT(m_resourceManager.notNull());
if (m_resourceManager->hasAnyOpenGLResources() && contextToShutdown->isContextValid())
{
contextToShutdown->makeCurrent();
m_resourceManager->deleteAllOpenGLResources(contextToShutdown);
}
shouldUninitializeGroup = true;
}
// If the ref count on the context is down to 1, there is probably something strange going on.
// Since one reference to the context is being held by this context group, this means that the
// caller isn't holding a reference to the context. In this case the context object will evaporate
// during the call below, and the caller will most likely get a nasty surprise
CVF_ASSERT(contextToShutdown->refCount() > 1);
// Make sure we set the back pointer before removing it from our collection
// since the removal from the list may actually trigger destruction of the context (see comment above)
contextToShutdown->m_contextGroup = NULL;
m_contexts.erase(contextToShutdown);
if (shouldUninitializeGroup)
{
// Bring context group back to virgin state
uninitializeContextGroup();
}
}
//--------------------------------------------------------------------------------------------------
/// Initializes GLEW for this context group
///
/// \warning The context passed in \a currentContext must be current!
//--------------------------------------------------------------------------------------------------
bool OpenGLContextGroup::initializeGLEW(OpenGLContext* currentContext)
{
CVF_ASSERT(currentContext);
CVF_ASSERT(m_glewContextStruct == NULL);
#ifdef CVF_USE_GLEW
// Since we're sometimes (when using Core OpenGL) seeing some OGL errors from GLEW, check before and after call to help find them
CVF_CHECK_OGL(currentContext);
// Must allocate memory for struct first since glewInit() call below will try and retrieve it
GLEWContextStruct* theContextStruct = new GLEWContextStruct;
memset(theContextStruct, 0, sizeof(GLEWContextStruct));
GLenum err = glewContextInit(theContextStruct);
if (err != GLEW_OK)
{
delete theContextStruct;
return false;
}
m_glewContextStruct = theContextStruct;
CVF_CHECK_OGL(currentContext);
#else
CVF_FAIL_MSG("Not implemented");
#endif
return true;
}
//--------------------------------------------------------------------------------------------------
/// Configures the capabilities of this context group by querying GLEW
///
/// \warning The passed context must be current and GLEW must already be initialized!
//--------------------------------------------------------------------------------------------------
void OpenGLContextGroup::configureCapablititesFromGLEW(OpenGLContext* currentContext)
{
#ifdef CVF_USE_GLEW
CVF_CALLSITE_GLEW(currentContext);
CVF_ASSERT(m_glewContextStruct);
// Simplified config for now, we only differentiate between 1, 2, and 3
uint majorVer = 1;
if (GLEW_VERSION_2_0) majorVer = 2;
if (GLEW_VERSION_3_0) majorVer = 3;
m_capabilities->configureOpenGLSupport(majorVer);
m_capabilities->setSupportsFixedFunction(true);
if (GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object)
{
m_capabilities->addCapablity(OpenGLCapabilities::FRAMEBUFFER_OBJECT);
m_capabilities->addCapablity(OpenGLCapabilities::GENERATE_MIPMAP_FUNC);
}
if (GLEW_VERSION_3_0 || GLEW_ARB_texture_float)
{
m_capabilities->addCapablity(OpenGLCapabilities::TEXTURE_FLOAT);
}
if (GLEW_VERSION_3_0 || GLEW_ARB_texture_rg)
{
m_capabilities->addCapablity(OpenGLCapabilities::TEXTURE_RG);
}
if (GLEW_VERSION_3_1 || GLEW_ARB_texture_rectangle)
{
m_capabilities->addCapablity(OpenGLCapabilities::TEXTURE_RECTANGLE);
}
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t OpenGLContextGroup::contextCount() const
{
return m_contexts.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGLContextGroup::containsContext(const OpenGLContext* context) const
{
if (m_contexts.contains(context))
{
CVF_ASSERT(context->group() == this);
return true;
}
else
{
CVF_ASSERT(context->group() != this);
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Add an OpenGLContext to this group
///
/// \warning It is the caller's responsibility to ensure that the context being added is actually
/// capable of sharing OpenGL resources (display lists etc) with the contexts that are
/// already in the group. This function will not do any verifications to assert whether this is true.
//--------------------------------------------------------------------------------------------------
void OpenGLContextGroup::addContext(OpenGLContext* contextToAdd)
{
CVF_ASSERT(contextToAdd);
// Illegal to add a context that is already in our group
CVF_ASSERT(!m_contexts.contains(contextToAdd));
// Guard against adding a context that is already member of a another group
CVF_ASSERT(contextToAdd->group() == NULL || contextToAdd->group() == this);
// Add it to our group and set ourselves as the owning group using our friend powers
m_contexts.push_back(contextToAdd);
contextToAdd->m_contextGroup = this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OpenGLResourceManager* OpenGLContextGroup::resourceManager()
{
CVF_ASSERT(m_resourceManager.notNull());
return m_resourceManager.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Logger* OpenGLContextGroup::logger()
{
return m_logger.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OpenGLCapabilities* OpenGLContextGroup::capabilities()
{
CVF_ASSERT(m_capabilities.notNull());
return m_capabilities.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
GLEWContextStruct* OpenGLContextGroup::glewContextStruct()
{
#ifdef CVF_USE_GLEW
CVF_TIGHT_ASSERT(this);
CVF_TIGHT_ASSERT(m_glewContextStruct);
return m_glewContextStruct;
#else
CVF_FAIL_MSG("Not implemented");
return NULL;
#endif
}
} // namespace cvf
@@ -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 "cvfObject.h"
#include "cvfCollection.h"
#include "cvfLogger.h"
struct GLEWContextStruct;
namespace cvf {
class OpenGLContext;
class OpenGLResourceManager;
class OpenGLCapabilities;
//==================================================================================================
//
//
//
//==================================================================================================
class OpenGLContextGroup : public Object
{
public:
OpenGLContextGroup();
virtual ~OpenGLContextGroup();
bool isContextGroupInitialized() const;
size_t contextCount() const;
bool containsContext(const OpenGLContext* context) const;
OpenGLResourceManager* resourceManager();
Logger* logger();
OpenGLCapabilities* capabilities();
GLEWContextStruct* glewContextStruct();
private:
bool initializeContextGroup(OpenGLContext* currentContext);
void uninitializeContextGroup();
void contextAboutToBeShutdown(OpenGLContext* contextToShutdown);
bool initializeGLEW(OpenGLContext* currentContext);
void configureCapablititesFromGLEW(OpenGLContext* currentContext);
void addContext(OpenGLContext* contextToAdd);
private:
bool m_isInitialized;
Collection<OpenGLContext> m_contexts; // The OpenGL contexts that belong to this group
ref<OpenGLResourceManager> m_resourceManager; // Resource manager that is shared between all contexts in this group
ref<Logger> m_logger;
ref<OpenGLCapabilities> m_capabilities; // Capabilities of the contexts in this group context
GLEWContextStruct* m_glewContextStruct; // Pointer to the GLEW context struct
friend class OpenGLContext;
};
}
@@ -0,0 +1,590 @@
//##################################################################################################
//
// 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 "cvfTrace.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLContext.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfBufferObjectManaged.h"
#include "cvfShaderProgram.h"
#include "cvfShaderProgramGenerator.h"
#include "cvfShaderSourceProvider.h"
#include "cvfShaderSourceRepository.h"
#include "cvfOglRc.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::OpenGLResourceManager
/// \ingroup Render
///
/// OpenGL resource manager used to manage and partially track the usage of OpenGL resources
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Private constructor
//--------------------------------------------------------------------------------------------------
OpenGLResourceManager::OpenGLResourceManager()
: m_cachedVboMemoryUsage(0)
{
}
//--------------------------------------------------------------------------------------------------
/// Private destructor.
///
/// Asserts that there are no active resources left.
//--------------------------------------------------------------------------------------------------
OpenGLResourceManager::~OpenGLResourceManager()
{
// If you hit these asserts you're probably failing to clean up the OpenGL resources being used
// The resources being managed must be deleted before the OpenGL contexts get deleted.
// Currently, you'll have to call deleteAllOpenGLResources() before deleting the OpenGL contexts
CVF_ASSERT(bufferObjectMemoryUsage() == 0);
CVF_ASSERT(bufferObjectCount() == 0);
CVF_ASSERT(m_oglResources.size() == 0);
CVF_ASSERT(m_textShaderProgram.isNull());
CVF_ASSERT(m_nudgeShaderProgram.isNull());
CVF_ASSERT(m_unlitColorShaderProgram.isNull());
CVF_ASSERT(m_unlitTextureShaderProgram.isNull());
CVF_ASSERT(m_vectorDrawerShaderProgram.isNull());
}
//--------------------------------------------------------------------------------------------------
/// Get existing buffer object or create a new buffer object that is initialized with the passed data.
///
/// The passed \a data pointer is used as the lookup key when determining if an existing buffer object
/// can be returned or if a new buffer object must be created.
///
/// \return Returns NULL if memory for buffer object could not be allocated.
//--------------------------------------------------------------------------------------------------
ref<BufferObjectManaged> OpenGLResourceManager::getOrCreateManagedBufferObject(OpenGLContext* oglContext, cvfGLenum target, size_t sizeInBytes, const void* data)
{
// Will not work with NULL pointers since the key in the map is the pointer
CVF_ASSERT(data);
CVF_ASSERT(sizeInBytes > 0);
// Using the passed raw data pointer as the key, do a lookup to see if we already have a buffer object
DataPtrBufferObjectMapIterator it = m_dataPtrBufferObjectMap.find(data);
if (it != m_dataPtrBufferObjectMap.end())
{
// We're almost ready to return the object, but we need to check the ref count first
// If count is 1, this is an orphaned buffer that should be deleted
if (it->second->refCount() > 1)
{
return it->second;
}
}
// Must create a new buffer object
ref<BufferObjectManaged> bo = BufferObjectManaged::create(oglContext, target, sizeInBytes, data);
if (bo.isNull())
{
return NULL;
}
// Insert the newly created buffer object into our map from raw data pointer to buffer object
m_dataPtrBufferObjectMap[data] = bo;
m_cachedVboMemoryUsage += bo->byteCount();
return bo;
}
//--------------------------------------------------------------------------------------------------
/// Deletes any orphaned OpenGL buffer objects being managed by this class
///
/// An orphaned buffer object is an object where the resource manager is holding the only reference
/// to the object. This function acts as a garbage collector for buffer objects.
///
/// \warning The OpenGL context in which the resources were created or a context that is being
/// shared must be current in the calling thread.
//--------------------------------------------------------------------------------------------------
void OpenGLResourceManager::deleteOrphanedManagedBufferObjects(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
m_cachedVboMemoryUsage = 0;
DataPtrBufferObjectMapIterator it = m_dataPtrBufferObjectMap.begin();
while (it != m_dataPtrBufferObjectMap.end())
{
if (it->second->refCount() == 1)
{
// Explicitly delete the buffer object (the actual OpenGL object)
it->second->deleteBuffer(oglContext);
m_dataPtrBufferObjectMap.erase(it++);
}
else
{
m_cachedVboMemoryUsage += it->second->byteCount();
++it;
}
}
}
//--------------------------------------------------------------------------------------------------
/// Deletes all OpenGL buffer objects being managed by this class
//--------------------------------------------------------------------------------------------------
void OpenGLResourceManager::deleteAllManagedBufferObjects(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
DataPtrBufferObjectMapIterator it = m_dataPtrBufferObjectMap.begin();
while (it != m_dataPtrBufferObjectMap.end())
{
// Explicitly delete the buffer object (the actual OpenGL object)
it->second->deleteBuffer(oglContext);
++it;
}
m_cachedVboMemoryUsage = 0;
m_dataPtrBufferObjectMap.clear();
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of managed buffer objects
//--------------------------------------------------------------------------------------------------
int OpenGLResourceManager::bufferObjectCount() const
{
return static_cast<int>(m_dataPtrBufferObjectMap.size());
}
//--------------------------------------------------------------------------------------------------
/// Returns the total amount of memory currently used by the managed buffer objects (in bytes).
//--------------------------------------------------------------------------------------------------
size_t OpenGLResourceManager::bufferObjectMemoryUsage() const
{
return m_cachedVboMemoryUsage;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<OglRcShader> OpenGLResourceManager::createOglRcShader(OpenGLContext* oglContext, cvfGLenum shaderType)
{
ref<OglRcShader> rc = OglRcShader::create(oglContext, shaderType);
if (rc.notNull())
{
m_oglResources.push_back(rc.p());
return rc;
}
else
{
return NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<OglRcProgram> OpenGLResourceManager::createOglRcProgram(OpenGLContext* oglContext)
{
ref<OglRcProgram> rc = OglRcProgram::create(oglContext);
if (rc.notNull())
{
m_oglResources.push_back(rc.p());
return rc;
}
else
{
return NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<OglRcTexture> OpenGLResourceManager::createOglRcTexture(OpenGLContext* oglContext)
{
ref<OglRcTexture> rc = OglRcTexture::create(oglContext);
if (rc.notNull())
{
m_oglResources.push_back(rc.p());
return rc;
}
else
{
return NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<OglRcRenderbuffer> OpenGLResourceManager::createOglRcRenderbuffer(OpenGLContext* oglContext)
{
ref<OglRcRenderbuffer> rc = OglRcRenderbuffer::create(oglContext);
if (rc.notNull())
{
m_oglResources.push_back(rc.p());
return rc;
}
else
{
return NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<OglRcFramebuffer> OpenGLResourceManager::createOglRcFramebuffer(OpenGLContext* oglContext)
{
ref<OglRcFramebuffer> rc = OglRcFramebuffer::create(oglContext);
if (rc.notNull())
{
m_oglResources.push_back(rc.p());
return rc;
}
else
{
return NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OpenGLResourceManager::deleteAllOglRcObjects(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
OglResourcesListIterator it = m_oglResources.begin();
while (it != m_oglResources.end())
{
OglRc* oglRc = (*it).p();
oglRc->deleteResource(oglContext);
++it;
}
m_oglResources.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OpenGLResourceManager::deleteOrphanedOglRcObjects(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
//size_t originalCount = m_oglResources.size();
//size_t deletedCount = 0;
OglResourcesListIterator it = m_oglResources.begin();
while (it != m_oglResources.end())
{
OglRc* oglRc = (*it).p();
if (oglRc->refCount() == 1)
{
// Explicitly delete the actual OpenGL resource
oglRc->deleteResource(oglContext);
m_oglResources.erase(it++);
//deletedCount++;
}
else
{
++it;
}
}
//cvf::Trace::show("Deleted %ld (of %ld) OglRc instances", deletedCount, originalCount);
}
//--------------------------------------------------------------------------------------------------
/// Get ready linked shader program for text drawing
//--------------------------------------------------------------------------------------------------
ShaderProgram* OpenGLResourceManager::getLinkedTextShaderProgram(OpenGLContext* oglContext)
{
if (m_textShaderProgram.isNull())
{
ShaderProgramGenerator gen("TextShaderProgram", ShaderSourceProvider::instance());
gen.addVertexCode(ShaderSourceRepository::vs_MinimalTexture);
gen.addFragmentCode(ShaderSourceRepository::fs_Text);
m_textShaderProgram = gen.generate();
m_textShaderProgram->linkProgram(oglContext);
m_textShaderProgram->disableUniformTrackingForUniform("u_texture2D");
m_textShaderProgram->disableUniformTrackingForUniform("u_color");
}
return m_textShaderProgram.p();
}
//--------------------------------------------------------------------------------------------------
/// Get ready linked shader program for use with 'manual' occlusion query for points
///
/// Shader program drawing a point size 3 point with a very light gray color. Used with Add blending
/// to detect if the point was rendered or not. (hacky-occlusion query)
//--------------------------------------------------------------------------------------------------
ShaderProgram* OpenGLResourceManager::getLinkedNudgeShaderProgram(OpenGLContext* oglContext)
{
if (m_nudgeShaderProgram.isNull())
{
static char nudgeFragSource[] =
"void main () \n"
"{ \n"
" gl_FragColor = vec4(0.02, 0.02, 0.02, 0.02); \n"
"} \n";
static char nudgeVertSource[] =
" uniform mat4 cvfu_modelViewProjectionMatrix; \n"
" attribute vec4 cvfa_vertex; \n"
" \n"
" void main () \n"
" { \n"
" gl_PointSize = 3; \n"
" gl_Position = cvfu_modelViewProjectionMatrix*cvfa_vertex; \n"
" } \n";
ShaderProgramGenerator gen("Nudge Shader", ShaderSourceProvider::instance());
gen.addVertexCode(nudgeVertSource);
gen.addFragmentCode(nudgeFragSource);
m_nudgeShaderProgram = gen.generate();
m_nudgeShaderProgram->linkProgram(oglContext);
}
return m_nudgeShaderProgram.p();
}
//--------------------------------------------------------------------------------------------------
/// Get ready linked shader program for unlit color drawing
//--------------------------------------------------------------------------------------------------
ShaderProgram* OpenGLResourceManager::getLinkedUnlitColorShaderProgram(OpenGLContext* oglContext)
{
if (m_unlitColorShaderProgram.isNull())
{
ShaderProgramGenerator gen("UnlitColorShaderProgram", ShaderSourceProvider::instance());
gen.addVertexCode(ShaderSourceRepository::vs_Minimal);
gen.addFragmentCode(ShaderSourceRepository::src_Color);
gen.addFragmentCode(ShaderSourceRepository::fs_Unlit);
m_unlitColorShaderProgram = gen.generate();
m_unlitColorShaderProgram->linkProgram(oglContext);
}
return m_unlitColorShaderProgram.p();
}
//--------------------------------------------------------------------------------------------------
/// Get ready linked shader program for unlit textured drawing
//--------------------------------------------------------------------------------------------------
ShaderProgram* OpenGLResourceManager::getLinkedUnlitTextureShaderProgram(OpenGLContext* oglContext)
{
if (m_unlitTextureShaderProgram.isNull())
{
ShaderProgramGenerator gen("UnlitTextureShaderProgram", ShaderSourceProvider::instance());
gen.addVertexCode(ShaderSourceRepository::vs_MinimalTexture);
gen.addFragmentCode(ShaderSourceRepository::src_Texture);
gen.addFragmentCode(ShaderSourceRepository::fs_Unlit);
m_unlitTextureShaderProgram = gen.generate();
m_unlitTextureShaderProgram->linkProgram(oglContext);
}
return m_unlitTextureShaderProgram.p();
}
//--------------------------------------------------------------------------------------------------
/// Get ready linked shader program for vector drawing
//--------------------------------------------------------------------------------------------------
ShaderProgram* OpenGLResourceManager::getLinkedVectorDrawerShaderProgram(OpenGLContext* oglContext)
{
if (m_vectorDrawerShaderProgram.isNull())
{
ShaderProgramGenerator gen("VectorDrawerShaderProgram", ShaderSourceProvider::instance());
gen.addVertexCode(ShaderSourceRepository::vs_VectorDrawer);
gen.addFragmentCode(ShaderSourceRepository::fs_VectorDrawer);
m_vectorDrawerShaderProgram = gen.generate();
m_vectorDrawerShaderProgram->linkProgram(oglContext);
m_vectorDrawerShaderProgram->disableUniformTrackingForUniform("u_transformationMatrix");
m_vectorDrawerShaderProgram->disableUniformTrackingForUniform("u_color");
}
return m_vectorDrawerShaderProgram.p();
}
//--------------------------------------------------------------------------------------------------
/// Deletes all OpenGL shader programs being managed by this class
//--------------------------------------------------------------------------------------------------
void OpenGLResourceManager::deleteAllShaderPrograms(OpenGLContext* oglContext)
{
if (m_textShaderProgram.notNull())
{
ref<ShaderProgram> progToDelete = m_textShaderProgram;
m_textShaderProgram = NULL;
if (progToDelete->isProgramUsed(oglContext))
{
ShaderProgram::useNoProgram(oglContext);
}
progToDelete->deleteProgram(oglContext);
}
if (m_nudgeShaderProgram.notNull())
{
ref<ShaderProgram> progToDelete = m_nudgeShaderProgram;
m_nudgeShaderProgram = NULL;
if (progToDelete->isProgramUsed(oglContext))
{
ShaderProgram::useNoProgram(oglContext);
}
progToDelete->deleteProgram(oglContext);
}
if (m_unlitColorShaderProgram.notNull())
{
ref<ShaderProgram> progToDelete = m_unlitColorShaderProgram;
m_unlitColorShaderProgram = NULL;
if (progToDelete->isProgramUsed(oglContext))
{
ShaderProgram::useNoProgram(oglContext);
}
progToDelete->deleteProgram(oglContext);
}
if (m_unlitTextureShaderProgram.notNull())
{
ref<ShaderProgram> progToDelete = m_unlitTextureShaderProgram;
m_unlitTextureShaderProgram = NULL;
if (progToDelete->isProgramUsed(oglContext))
{
ShaderProgram::useNoProgram(oglContext);
}
progToDelete->deleteProgram(oglContext);
}
if (m_vectorDrawerShaderProgram.notNull())
{
ref<ShaderProgram> progToDelete = m_vectorDrawerShaderProgram;
m_vectorDrawerShaderProgram = NULL;
if (progToDelete->isProgramUsed(oglContext))
{
ShaderProgram::useNoProgram(oglContext);
}
progToDelete->deleteProgram(oglContext);
}
}
//--------------------------------------------------------------------------------------------------
/// Evicts (deletes) any orphaned OpenGL resources being managed by this class
///
/// An orphaned OpenGL resource is an object where the resource manager is holding the only reference
/// to the object. This function acts as a garbage collector for buffer objects.
///
/// \warning The OpenGL context passed in \a oglContext must be the same one (or shared with) used
/// when creating the resources.
//--------------------------------------------------------------------------------------------------
void OpenGLResourceManager::evictOrphanedOpenGLResources(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
CVF_ASSERT(oglContext->isCurrent());
deleteOrphanedManagedBufferObjects(oglContext);
deleteOrphanedOglRcObjects(oglContext);
}
//--------------------------------------------------------------------------------------------------
/// Deletes all OpenGL resources known to this class
///
/// \warning The OpenGL context passed in \a oglContext must be the same one (or shared with) used
/// when creating the resources.
//--------------------------------------------------------------------------------------------------
void OpenGLResourceManager::deleteAllOpenGLResources(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
CVF_ASSERT(oglContext->isCurrent());
deleteAllManagedBufferObjects(oglContext);
deleteAllOglRcObjects(oglContext);
deleteAllShaderPrograms(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool OpenGLResourceManager::hasAnyOpenGLResources() const
{
if (!m_dataPtrBufferObjectMap.empty())
{
return true;
}
if (!m_oglResources.empty())
{
return true;
}
if (m_textShaderProgram.notNull() ||
m_nudgeShaderProgram.notNull() ||
m_unlitColorShaderProgram.notNull() ||
m_unlitTextureShaderProgram.notNull() ||
m_vectorDrawerShaderProgram.notNull())
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
/// Dump (using trace) resource info
//--------------------------------------------------------------------------------------------------
void OpenGLResourceManager::dumpCurrentResourceUsage() const
{
Trace::show("OpenGL resource tracking:");
Trace::show("Num. VBOs active: %6d Memory usage: %8d", bufferObjectCount(), bufferObjectMemoryUsage());
}
} // namespace cvf
@@ -0,0 +1,100 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfOpenGLTypes.h"
#include "cvfCollection.h"
#include <map>
#include <list>
namespace cvf {
class BufferObjectManaged;
class ShaderProgram;
class OpenGLContext;
class OglRc;
class OglRcShader;
class OglRcProgram;
class OglRcTexture;
class OglRcRenderbuffer;
class OglRcFramebuffer;
//==================================================================================================
//
// OpenGL resource manager
//
//==================================================================================================
class OpenGLResourceManager : public Object
{
public:
OpenGLResourceManager();
virtual ~OpenGLResourceManager();
ref<BufferObjectManaged> getOrCreateManagedBufferObject(OpenGLContext* oglContext, cvfGLenum target, size_t sizeInBytes, const void* data);
int bufferObjectCount() const;
size_t bufferObjectMemoryUsage() const;
ref<OglRcShader> createOglRcShader(OpenGLContext* oglContext, cvfGLenum shaderType);
ref<OglRcProgram> createOglRcProgram(OpenGLContext* oglContext);
ref<OglRcTexture> createOglRcTexture(OpenGLContext* oglContext);
ref<OglRcRenderbuffer> createOglRcRenderbuffer(OpenGLContext* oglContext);
ref<OglRcFramebuffer> createOglRcFramebuffer(OpenGLContext* oglContext);
ShaderProgram* getLinkedTextShaderProgram(OpenGLContext* oglContext);
ShaderProgram* getLinkedNudgeShaderProgram(OpenGLContext* oglContext);
ShaderProgram* getLinkedUnlitColorShaderProgram(OpenGLContext* oglContext);
ShaderProgram* getLinkedUnlitTextureShaderProgram(OpenGLContext* oglContext);
ShaderProgram* getLinkedVectorDrawerShaderProgram(OpenGLContext* oglContext);
void evictOrphanedOpenGLResources(OpenGLContext* oglContext);
void deleteAllOpenGLResources(OpenGLContext* oglContext);
bool hasAnyOpenGLResources() const;
void dumpCurrentResourceUsage() const;
private:
void deleteAllManagedBufferObjects(OpenGLContext* oglContext);
void deleteOrphanedManagedBufferObjects(OpenGLContext* oglContext);
void deleteAllOglRcObjects(OpenGLContext* oglContext);
void deleteOrphanedOglRcObjects(OpenGLContext* oglContext);
void deleteAllShaderPrograms(OpenGLContext* oglContext);
private:
typedef std::map<const void*, ref<BufferObjectManaged> > DataPtrBufferObjectMap;
typedef std::map<const void*, ref<BufferObjectManaged> >::iterator DataPtrBufferObjectMapIterator;
typedef std::list<ref<OglRc> > OglResourcesList;
typedef std::list<ref<OglRc> >::iterator OglResourcesListIterator;
DataPtrBufferObjectMap m_dataPtrBufferObjectMap; // Mapping from data pointer to BufferObject
mutable size_t m_cachedVboMemoryUsage; //
OglResourcesList m_oglResources;
ref<ShaderProgram> m_textShaderProgram;
ref<ShaderProgram> m_nudgeShaderProgram;
ref<ShaderProgram> m_unlitColorShaderProgram;
ref<ShaderProgram> m_unlitTextureShaderProgram;
ref<ShaderProgram> m_vectorDrawerShaderProgram;
};
}
@@ -0,0 +1,50 @@
//##################################################################################################
//
// 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
namespace cvf {
// Define aliases for the OpenGL types so we can utilize them without including
// the actual OpenGL headers all over the place.
typedef unsigned int cvfGLenum;
typedef unsigned char cvfGLboolean;
typedef unsigned int cvfGLbitfield;
typedef signed char cvfGLbyte; // 1-byte signed
typedef short cvfGLshort; // 2-byte signed
typedef int cvfGLint; // 4-byte signed
typedef int cvfGLsizei; // 4-byte signed
typedef unsigned char cvfGLubyte; // 1-byte unsigned
typedef unsigned short cvfGLushort; // 2-byte unsigned
typedef unsigned int cvfGLuint; // 4-byte unsigned
typedef float cvfGLfloat; // single precision float
typedef float cvfGLclampf; // single precision float in [0,1]
typedef double cvfGLdouble; // double precision float
typedef double cvfGLclampd; // double precision float in [0,1]
typedef void cvfGLvoid;
// Type used to hold OpenGL identificators (object names)
// Typically the return values from glCreateShader() etc
// May eventually wrap this up in a class
typedef unsigned int OglId;
}
@@ -0,0 +1,381 @@
//##################################################################################################
//
// 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 "cvfOverlayAxisCross.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"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#endif
namespace cvf {
//==================================================================================================
///
/// \class cvf::OverlayAxisCross
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
OverlayAxisCross::OverlayAxisCross(Camera* camera, Font* font)
: m_camera(camera),
m_xLabel("x"),
m_yLabel("y"),
m_zLabel("z"),
m_textColor(Color3::BLACK),
m_font(font),
m_size(120, 120)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OverlayAxisCross::~OverlayAxisCross()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayAxisCross::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 OverlayAxisCross::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 OverlayAxisCross::setAxisLabelsColor(const Color3f& color)
{
m_textColor = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayAxisCross::sizeHint()
{
return m_size;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayAxisCross::maximumSize()
{
return sizeHint();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayAxisCross::minimumSize()
{
return sizeHint();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayAxisCross::setSize(const Vec2ui& size)
{
m_size = size;
}
//--------------------------------------------------------------------------------------------------
/// Hardware rendering using shader programs
//--------------------------------------------------------------------------------------------------
void OverlayAxisCross::render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
Mat4d viewMatrix = m_camera->viewMatrix();
render(oglContext, position, size, false, viewMatrix);
}
//--------------------------------------------------------------------------------------------------
/// Software rendering
//--------------------------------------------------------------------------------------------------
void OverlayAxisCross::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 OverlayAxisCross::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);
}
// 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, -4.4));
// 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);
}
renderAxisLabels(oglContext, software, matrixState);
}
//--------------------------------------------------------------------------------------------------
/// Draw the axis
//--------------------------------------------------------------------------------------------------
void OverlayAxisCross::renderAxis(OpenGLContext* oglContext, const MatrixState& matrixState)
{
CVF_ASSERT(m_axis.notNull());
CVF_ASSERT(m_xAxisTriangle.notNull());
CVF_ASSERT(m_yAxisTriangle.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 X axis triangle
ref<ShaderProgram> triangleProgram = resourceManager->getLinkedUnlitColorShaderProgram(oglContext);
if (triangleProgram->useProgram(oglContext))
{
triangleProgram->clearUniformApplyTracking();
triangleProgram->applyFixedUniforms(oglContext, matrixState);
}
UniformFloat xUniformColor("u_color", Color4f(Color3::RED));
triangleProgram->applyUniform(oglContext, xUniformColor);
m_xAxisTriangle->render(oglContext, triangleProgram.p(), matrixState);
// Draw Y axis triangle
UniformFloat yUniformColor("u_color", Color4f(Color3::GREEN));
triangleProgram->applyUniform(oglContext, yUniformColor);
m_yAxisTriangle->render(oglContext, triangleProgram.p(), matrixState);
}
//--------------------------------------------------------------------------------------------------
/// Draw the axis using immediate mode OpenGL
//--------------------------------------------------------------------------------------------------
void OverlayAxisCross::renderAxisImmediateMode(OpenGLContext* oglContext, const MatrixState& matrixState)
{
#ifdef CVF_OPENGL_ES
CVF_FAIL_MSG("Not supported on OpenGL ES");
#else
m_axis->renderImmediateMode(oglContext, matrixState);
// Draw X axis triangle
Material_FF xMaterial(Material_FF::PURE_RED);
xMaterial.applyOpenGL(oglContext);
m_xAxisTriangle->renderImmediateMode(oglContext, matrixState);
// Draw Y axis triangle
Material_FF yMaterial(Material_FF::PURE_GREEN);
yMaterial.applyOpenGL(oglContext);
m_yAxisTriangle->renderImmediateMode(oglContext, matrixState);
#endif // CVF_OPENGL_ES
}
//--------------------------------------------------------------------------------------------------
/// Create the geometry used to draw the axis (vector arrows) and the two triangles
//--------------------------------------------------------------------------------------------------
void OverlayAxisCross::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
ref<cvf::Vec3fArray> vertexArray = new Vec3fArray;
vertexArray->resize(3);
vertexArray->set(0, Vec3f(0.0f, 0.0f, 0.0f)); // X axis
vertexArray->set(1, Vec3f(0.0f, 0.0f, 0.0f)); // Y axis
vertexArray->set(2, Vec3f(0.0f, 0.0f, 0.0f)); // 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());
// X axis triangle
GeometryBuilderDrawableGeo xAxisTriBuilder;
xAxisTriBuilder.addTriangle(0, 1, 2);
Vec3fArray xAxisTriVerts;
xAxisTriVerts.resize(3);
xAxisTriVerts[0] = Vec3f(0, 0, 0);
xAxisTriVerts[1] = Vec3f(0.5f, 0, 0);
xAxisTriVerts[2] = Vec3f(0.2f, 0.2f, 0);
xAxisTriBuilder.addVertices(xAxisTriVerts);
m_xAxisTriangle = xAxisTriBuilder.drawableGeo();
// Y axis triangle
GeometryBuilderDrawableGeo yAxisTriBuilder;
yAxisTriBuilder.addTriangle(0, 1, 2);
Vec3fArray yAxisTriVerts;
yAxisTriVerts.resize(3);
yAxisTriVerts[0] = Vec3f(0, 0, 0);
yAxisTriVerts[1] = Vec3f(0.2f, 0.2f, 0);
yAxisTriVerts[2] = Vec3f(0, 0.4f, 0);
yAxisTriBuilder.addVertices(yAxisTriVerts);
m_yAxisTriangle = yAxisTriBuilder.drawableGeo();
}
//--------------------------------------------------------------------------------------------------
/// Draw the axis labels
//--------------------------------------------------------------------------------------------------
void OverlayAxisCross::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);
}
}
} // namespace cvf
@@ -0,0 +1,82 @@
//##################################################################################################
//
// 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"
namespace cvf {
class Camera;
class DrawableGeo;
class DrawableVectors;
class Font;
class ShaderProgram;
class MatrixState;
//==================================================================================================
//
// Overlay axis cross
//
//==================================================================================================
class OverlayAxisCross : public OverlayItem
{
public:
OverlayAxisCross(Camera* camera, Font* font);
~OverlayAxisCross();
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 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);
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
ref<DrawableVectors> m_axis;
ref<DrawableGeo> m_xAxisTriangle;
ref<DrawableGeo> m_yAxisTriangle;
};
}
@@ -0,0 +1,662 @@
//##################################################################################################
//
// 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 "cvfOverlayColorLegend.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"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#else
#include "cvfRenderState.h"
#endif
#include "cvfLegendScalarMapper.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::OverlayColorLegend
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
OverlayColorLegend::OverlayColorLegend(Font* font)
: m_sizeHint(200, 200),
m_color(Color3::BLACK),
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);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OverlayColorLegend::~OverlayColorLegend()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayColorLegend::sizeHint()
{
return m_sizeHint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayColorLegend::maximumSize()
{
return m_sizeHint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayColorLegend::minimumSize()
{
return Vec2ui(100,100);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::setScalarMapper(const LegendScalarMapper* scalarMapper)
{
m_scalarMapper = scalarMapper;
if (m_scalarMapper.notNull())
{
std::vector<double> levelValues;
m_scalarMapper->majorLevels(&levelValues);
m_tickValues.assign(levelValues);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::setSizeHint(const Vec2ui& size)
{
m_sizeHint = size;
}
//--------------------------------------------------------------------------------------------------
/// Set color of the text and lines to be rendered
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::setColor(const Color3f& color)
{
m_color = color;
}
//--------------------------------------------------------------------------------------------------
/// Returns the color of the text and lines
//--------------------------------------------------------------------------------------------------
const Color3f& OverlayColorLegend::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 OverlayColorLegend::setTitle(const String& title)
{
// Title
if (title.isEmpty())
{
m_titleStrings.clear();
}
else
{
m_titleStrings = title.split("\n");
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String OverlayColorLegend::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 OverlayColorLegend::render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
render(oglContext, position, size, false);
}
//--------------------------------------------------------------------------------------------------
/// Software rendering using software
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
render(oglContext, position, size, true);
}
//--------------------------------------------------------------------------------------------------
/// Set up camera/viewport and render
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software)
{
if (size.x() <= 0 || size.y() <= 0)
{
return;
}
Camera camera;
camera.setViewport(position.x(), position.y(), size.x(), size.y());
camera.setProjectionAsPixelExact2D();
camera.setViewMatrix(Mat4d::IDENTITY);
camera.applyOpenGL();
camera.viewport()->applyOpenGL(oglContext, Viewport::CLEAR_DEPTH);
// Get layout information
// Todo: Cache this between renderings. Update only when needed.
OverlayColorLegendLayoutInfo layout(position, size);
layoutInfo(&layout);
// Set up text drawer
TextDrawer textDrawer(m_font.p());
setupTextDrawer(&textDrawer, &layout);
// Do the actual rendering
if (software)
{
renderLegendImmediateMode(oglContext, &layout);
textDrawer.renderSoftware(oglContext, camera);
}
else
{
const MatrixState matrixState(camera);
renderLegend(oglContext, &layout, matrixState);
textDrawer.render(oglContext, camera);
}
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::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 OverlayColorLegend::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);
Depth depth(false);
depth.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_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++)
{
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;
}
#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
Depth resetDepth;
resetDepth.applyOpenGL(oglContext);
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
/// Draw the legend using immediate mode OpenGL
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::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);
Depth depth(false);
depth.applyOpenGL(oglContext);
Lighting_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
Lighting_FF resetLighting;
resetLighting.applyOpenGL(oglContext);
Depth resetDepth;
resetDepth.applyOpenGL(oglContext);
CVF_CHECK_OGL(oglContext);
#endif // CVF_OPENGL_ES
}
//--------------------------------------------------------------------------------------------------
/// Get layout information
//--------------------------------------------------------------------------------------------------
void OverlayColorLegend::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->normalizedLevelPosition(m_tickValues[i]);
t = Math::clamp(t, 0.0, 1.1);
layout->tickPixelPos->set(i, t*layout->legendRect.height());
}
}
} // namespace cvf
@@ -0,0 +1,114 @@
//##################################################################################################
//
// 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 LegendScalarMapper;
//==================================================================================================
//
// 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;
};
//==================================================================================================
//
// Overlay color legend
//
//==================================================================================================
class OverlayColorLegend : public OverlayItem
{
public:
OverlayColorLegend(Font* font);
virtual ~OverlayColorLegend();
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);
void setSizeHint(const Vec2ui& size);
void setColor(const Color3f& color);
const Color3f& color() const;
void setTitle(const String& title);
String title() const;
protected:
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;
std::vector<String> m_titleStrings;
ref<Font> m_font;
cref<LegendScalarMapper> m_scalarMapper;
};
}
@@ -0,0 +1,63 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfVector2.h"
namespace cvf {
class OpenGLContext;
//==================================================================================================
//
// Interface for overlay items
//
//==================================================================================================
class OverlayItem : public Object
{
public:
enum LayoutCorner
{
TOP_LEFT,
TOP_RIGHT,
BOTTOM_LEFT,
BOTTOM_RIGHT
};
enum LayoutDirection
{
HORIZONTAL,
VERTICAL
};
public:
virtual Vec2ui sizeHint() = 0; // In Pixels
virtual Vec2ui maximumSize() = 0; // In Pixels
virtual Vec2ui minimumSize() = 0; // In Pixels
virtual void render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size) = 0;
virtual void renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size) = 0;
};
}
@@ -0,0 +1,382 @@
//##################################################################################################
//
// 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 "cvfRenderState.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::OverlayTextBox
/// \ingroup Render
///
/// An view overlay item capable of showing a text with optionally a border and a background
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor. The specified font is used to draw all the text
//--------------------------------------------------------------------------------------------------
OverlayTextBox::OverlayTextBox(Font* font)
: m_size(200, 50),
m_drawBackground(true),
m_drawBorder(true),
m_textColor(Color3::WHITE),
m_backgroundColor(0.2f, 0.2f, 1.0f),
m_borderColor(0.6f, 0.6f, 1.0f)
{
m_textDrawer = new TextDrawer(font);
m_textDrawer->setVerticalAlignment(TextDrawer::CENTER);
m_textDrawer->setDrawBackground(false);
m_textDrawer->setDrawBorder(false);
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
OverlayTextBox::~OverlayTextBox()
{
}
//--------------------------------------------------------------------------------------------------
/// Returns the wanted size in pixels
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayTextBox::sizeHint()
{
return m_size;
}
//--------------------------------------------------------------------------------------------------
/// Returns the maximum size of the text box in pixels
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayTextBox::maximumSize()
{
return sizeHint();
}
//--------------------------------------------------------------------------------------------------
/// Returns the minimum size of the text box in pixels
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui OverlayTextBox::minimumSize()
{
return sizeHint();
}
//--------------------------------------------------------------------------------------------------
/// Render using Shaders
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
render(oglContext, position, size, false);
}
//--------------------------------------------------------------------------------------------------
/// Render using Fixed Function
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::renderSoftware(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size)
{
render(oglContext, position, size, true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software)
{
Mat4d ident;
MatrixState matrixState(position, size, ident, ident);
Vec2f textPos(0.0f, static_cast<float>(size.y())/2.0f);
if (m_drawBorder || m_drawBackground)
{
renderBackgroundAndBorder(oglContext, position, size, software);
textPos.x() = 4; // Allow for margin
}
// Set the text
m_textDrawer->removeAllTexts();
m_textDrawer->addText(m_text, textPos);
m_textDrawer->setTextColor(m_textColor);
// Draw the text
if (software)
{
m_textDrawer->renderSoftware(oglContext, matrixState);
}
else
{
m_textDrawer->render(oglContext, matrixState);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::renderBackgroundAndBorder(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software)
{
CVF_CALLSITE_OPENGL(oglContext);
// Prepare 2D pixel exact projection to draw texts
Camera projCam;
projCam.setViewport(position.x(), position.y(), size.x(), size.y());
projCam.setProjectionAsPixelExact2D();
projCam.setViewMatrix(Mat4d::IDENTITY);
// Turn off depth test
Depth depth(false, Depth::LESS, false);
depth.applyOpenGL(oglContext);
ref<ShaderProgram> backgroundShader;
float vertexArray[12];
projCam.viewport()->applyOpenGL(oglContext, Viewport::DO_NOT_CLEAR);
if (software)
{
if (ShaderProgram::supportedOpenGL(oglContext))
{
ShaderProgram::useNoProgram(oglContext);
}
#ifndef CVF_OPENGL_ES
Material_FF mat;
mat.enableColorMaterial(true);
mat.applyOpenGL(oglContext);
Lighting_FF light(false);
light.applyOpenGL(oglContext);
#endif
projCam.applyOpenGL();
}
else
{
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(ShaderProgram::VERTEX);
glVertexAttribPointer(ShaderProgram::VERTEX, 3, GL_FLOAT, GL_FALSE, 0, vertexArray);
backgroundShader = oglContext->resourceManager()->getLinkedUnlitColorShaderProgram(oglContext);
if (backgroundShader->useProgram(oglContext))
{
MatrixState projMatrixState(projCam);
backgroundShader->clearUniformApplyTracking();
backgroundShader->applyFixedUniforms(oglContext, projMatrixState);
}
}
Vec3f min(1.0f, 1.0f, 0.0f);
Vec3f max(static_cast<float>(size.x() - 1), static_cast<float>(size.y() - 1), 0.0f);
// Setup the vertex array
float* v1 = &vertexArray[0];
float* v2 = &vertexArray[3];
float* v3 = &vertexArray[6];
float* v4 = &vertexArray[9];
v1[0] = min.x(); v1[1] = min.y(); v1[2] = 0.0f;
v2[0] = max.x(); v2[1] = min.y(); v2[2] = 0.0f;
v3[0] = max.x(); v3[1] = max.y(); v3[2] = 0.0f;
v4[0] = min.x(); v4[1] = max.y(); v4[2] = 0.0f;
if (m_drawBackground)
{
if (software)
{
#ifndef CVF_OPENGL_ES
glColor4fv(m_backgroundColor.ptr());
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(v1);
glVertex3fv(v2);
glVertex3fv(v3);
glVertex3fv(v4);
glEnd();
#endif
}
else
{
// Draw background
UniformFloat backgroundColor("u_color", Color4f(m_backgroundColor));
backgroundShader->applyUniform(oglContext, backgroundColor);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
}
if (m_drawBorder)
{
if (software)
{
#ifndef CVF_OPENGL_ES
glColor3fv(m_borderColor.ptr());
glBegin(GL_LINE_LOOP);
glVertex3fv(v1);
glVertex3fv(v2);
glVertex3fv(v3);
glVertex3fv(v4);
glEnd();
#endif
}
else
{
UniformFloat borderColor("u_color", Color4f(m_borderColor));
backgroundShader->applyUniform(oglContext, borderColor);
// Draw border
glDrawArrays(GL_LINE_LOOP, 0, 4);
}
}
}
//--------------------------------------------------------------------------------------------------
/// Set the text to draw in the box
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::setText(const String& text)
{
m_text = text;
}
//--------------------------------------------------------------------------------------------------
/// Set the size (in pixels) of the text box
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::setSize( const Vec2ui& size )
{
m_size = size;
}
//--------------------------------------------------------------------------------------------------
/// Set the text color
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::setTextColor(const Color3f& color)
{
m_textColor = color;
}
//--------------------------------------------------------------------------------------------------
/// Set the background color of the text box
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::setBackgroundColor(const Color3f& color)
{
m_backgroundColor = color;
}
//--------------------------------------------------------------------------------------------------
/// Set the border color of the text box
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::setBorderColor(const Color3f& color)
{
m_borderColor = color;
}
//--------------------------------------------------------------------------------------------------
/// Set if a filled background of the text box should be drawn or not
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::setDrawBackground(bool drawBackground)
{
m_drawBackground = drawBackground;
}
//--------------------------------------------------------------------------------------------------
/// Set if the border of the text box should be drawn or not
//--------------------------------------------------------------------------------------------------
void OverlayTextBox::setDrawBorder(bool drawBorder)
{
m_drawBorder = drawBorder;
}
//--------------------------------------------------------------------------------------------------
/// Returns the text shown in the text box
//--------------------------------------------------------------------------------------------------
String OverlayTextBox::text() const
{
return m_text;
}
//--------------------------------------------------------------------------------------------------
/// Returns the color used to draw the text
//--------------------------------------------------------------------------------------------------
Color3f OverlayTextBox::textColor() const
{
return m_textColor;
}
//--------------------------------------------------------------------------------------------------
/// Returns the color of the background
//--------------------------------------------------------------------------------------------------
Color3f OverlayTextBox::backgroundColor() const
{
return m_backgroundColor;
}
//--------------------------------------------------------------------------------------------------
/// Returns the color of the border.
//--------------------------------------------------------------------------------------------------
Color3f OverlayTextBox::borderColor() const
{
return m_borderColor;
}
//--------------------------------------------------------------------------------------------------
/// Returns true if the background will be drawn
//--------------------------------------------------------------------------------------------------
bool OverlayTextBox::drawBackground() const
{
return m_drawBackground;
}
//--------------------------------------------------------------------------------------------------
/// Returns true if the border will be drawn
//--------------------------------------------------------------------------------------------------
bool OverlayTextBox::drawBorder() const
{
return m_drawBorder;
}
} // namespace cvf
@@ -0,0 +1,82 @@
//##################################################################################################
//
// 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"
namespace cvf {
class Font;
class TextDrawer;
//==================================================================================================
//
// Overlay text box
//
//==================================================================================================
class OverlayTextBox : public OverlayItem
{
public:
OverlayTextBox(Font* font);
~OverlayTextBox();
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 setText(const String& text);
void setSize(const Vec2ui& size);
void setTextColor(const Color3f& color);
void setBackgroundColor(const Color3f& color);
void setBorderColor(const Color3f& color);
void setDrawBackground(bool drawBackground);
void setDrawBorder(bool drawBorder);
String text() const;
Color3f textColor() const;
Color3f backgroundColor() const;
Color3f borderColor() const;
bool drawBackground() const;
bool drawBorder() const;
private:
void render(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software);
void renderBackgroundAndBorder(OpenGLContext* oglContext, const Vec2ui& position, const Vec2ui& size, bool software);
private:
Vec2ui m_size;
String m_text;
ref<TextDrawer> m_textDrawer;
bool m_drawBackground;
bool m_drawBorder;
Color3f m_textColor;
Color3f m_backgroundColor;
Color3f m_borderColor;
};
}
@@ -0,0 +1,204 @@
//##################################################################################################
//
// 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 "cvfMath.h"
#include "cvfPrimitiveSet.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::PrimitiveSet
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PrimitiveSet::PrimitiveSet(PrimitiveType primitiveType)
: m_primitiveType(primitiveType)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PrimitiveType PrimitiveSet::primitiveType() const
{
return m_primitiveType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvfGLenum PrimitiveSet::primitiveTypeOpenGL() const
{
switch (m_primitiveType)
{
case PT_POINTS: return GL_POINTS;
case PT_LINES: return GL_LINES;
case PT_LINE_LOOP: return GL_LINE_LOOP;
case PT_LINE_STRIP: return GL_LINE_STRIP;
case PT_TRIANGLES: return GL_TRIANGLES;
case PT_TRIANGLE_STRIP: return GL_TRIANGLE_STRIP;
case PT_TRIANGLE_FAN: return GL_TRIANGLE_FAN;
default: CVF_FAIL_MSG("Unhandled primitive type");
}
return UNDEFINED_UINT;
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of triangles in this primitive group
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSet::triangleCount() const
{
if (m_primitiveType != PT_TRIANGLES)
{
return 0;
}
CVF_ASSERT(indexCount()%3 == 0);
return indexCount()/3;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSet::faceCount() const
{
switch (m_primitiveType)
{
case PT_POINTS: return indexCount();
case PT_LINES: return indexCount()/2;
case PT_LINE_LOOP: return indexCount();
case PT_LINE_STRIP: return indexCount() - 1;
case PT_TRIANGLES: return triangleCount();
case PT_TRIANGLE_STRIP: return indexCount() - 2;
case PT_TRIANGLE_FAN: return indexCount() - 2;
default: CVF_FAIL_MSG("Unhandled primitive type");
}
return 0;
}
//--------------------------------------------------------------------------------------------------
/// Gets connectivity for one face in this primitive set
///
/// The indices array will be populated with the connectivities for the specified face.
/// The connectivity table will have 1, 2, 3 or 4 entries. If this primitive set consists
/// of a triangle fan, triangles will be returned. In a similar fashion, if the primitive set
/// consist of a quad strip, quads will be returned.
//--------------------------------------------------------------------------------------------------
void PrimitiveSet::getFaceIndices(size_t indexOfFace, UIntArray* indices) const
{
CVF_TIGHT_ASSERT(indexOfFace < faceCount());
CVF_TIGHT_ASSERT(indices);
indices->setSizeZero();
if (m_primitiveType == PT_POINTS)
{
indices->reserve(1);
indices->add(index(indexOfFace));
}
else if (m_primitiveType == PT_LINES)
{
indices->reserve(2);
indices->add(index(2*indexOfFace));
indices->add(index(2*indexOfFace + 1));
}
else if (m_primitiveType == PT_LINE_LOOP)
{
indices->reserve(2);
if (indexOfFace == faceCount() - 1)
{
indices->add(index(indexOfFace));
indices->add(index(0));
}
else
{
indices->add(index(indexOfFace));
indices->add(index(indexOfFace + 1));
}
}
else if (m_primitiveType == PT_LINE_STRIP)
{
indices->reserve(2);
indices->add(index(indexOfFace));
indices->add(index(indexOfFace + 1));
}
else if (m_primitiveType == PT_TRIANGLES)
{
indices->reserve(3);
const size_t baseIdx = 3*indexOfFace;
indices->add(index(baseIdx));
indices->add(index(baseIdx + 1));
indices->add(index(baseIdx + 2));
}
else if (m_primitiveType == PT_TRIANGLE_FAN)
{
indices->reserve(3);
indices->add(index(0));
indices->add(index(indexOfFace + 1));
indices->add(index(indexOfFace + 2));
}
else if (m_primitiveType == PT_TRIANGLE_STRIP)
{
indices->reserve(3);
if (indexOfFace % 2 == 0)
{
indices->add(index(indexOfFace));
indices->add(index(indexOfFace + 1));
indices->add(index(indexOfFace + 2));
}
else
{
indices->add(index(indexOfFace + 1));
indices->add(index(indexOfFace));
indices->add(index(indexOfFace + 2));
}
}
else
{
CVF_FAIL_MSG("Not implemented");
}
}
} // namespace cvf
@@ -0,0 +1,75 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfArray.h"
#include "cvfOpenGLTypes.h"
namespace cvf {
class OpenGLContext;
enum PrimitiveType
{
PT_POINTS = 100,
PT_LINES,
PT_LINE_LOOP,
PT_LINE_STRIP,
PT_TRIANGLES,
PT_TRIANGLE_STRIP,
PT_TRIANGLE_FAN
};
//==================================================================================================
//
//
//
//==================================================================================================
class PrimitiveSet : public Object
{
public:
PrimitiveSet(PrimitiveType primitiveType);
PrimitiveType primitiveType() const;
cvfGLenum primitiveTypeOpenGL() const;
size_t triangleCount() const;
size_t faceCount() const;
void getFaceIndices(size_t indexOfFace, UIntArray* indices) const;
virtual void render(OpenGLContext* oglContext) const = 0;
virtual void createUploadBufferObjectsGPU(OpenGLContext* oglContext) = 0;
virtual void releaseBufferObjectsGPU() = 0;
virtual size_t indexCount() const = 0;
virtual uint index(size_t i) const = 0;
private:
PrimitiveType m_primitiveType;
};
}
@@ -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.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfAssert.h"
#include "cvfMath.h"
#include "cvfPrimitiveSetDirect.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::PrimitiveSetDirect
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PrimitiveSetDirect::PrimitiveSetDirect(PrimitiveType primitiveType)
: PrimitiveSet(primitiveType),
m_startIndex(0),
m_indexCount(0)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetDirect::render(OpenGLContext* oglContext) const
{
if (m_indexCount == 0)
{
return;
}
GLint first = static_cast<GLint>(m_startIndex);
GLsizei count = static_cast<GLsizei>(m_indexCount);
glDrawArrays(primitiveTypeOpenGL(), first, count);
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetDirect::createUploadBufferObjectsGPU(OpenGLContext* /*oglContext*/)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetDirect::releaseBufferObjectsGPU()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetDirect::setStartIndex(size_t startIndex)
{
m_startIndex = startIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetDirect::setIndexCount(size_t indexCount)
{
m_indexCount = indexCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSetDirect::indexCount() const
{
return m_indexCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint PrimitiveSetDirect::index(size_t i) const
{
CVF_TIGHT_ASSERT(i < m_indexCount);
return static_cast<uint>(m_startIndex + i);
}
} // namespace cvf
@@ -0,0 +1,53 @@
//##################################################################################################
//
// 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 "cvfPrimitiveSet.h"
namespace cvf {
//==================================================================================================
//
//
//
//==================================================================================================
class PrimitiveSetDirect : public PrimitiveSet
{
public:
PrimitiveSetDirect(PrimitiveType primitiveType);
virtual void render(OpenGLContext* oglContext) const;
virtual void createUploadBufferObjectsGPU(OpenGLContext* oglContext);
virtual void releaseBufferObjectsGPU();
void setStartIndex(size_t startIndex);
void setIndexCount(size_t indexCount);
virtual size_t indexCount() const;
virtual uint index(size_t i) const;
private:
size_t m_startIndex; // Starting index in the enabled (vertex attribute) arrays
size_t m_indexCount; // Number of indices to be rendered.
};
}
@@ -0,0 +1,243 @@
//##################################################################################################
//
// 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 "cvfMath.h"
#include "cvfPrimitiveSetIndexedUInt.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfBufferObjectManaged.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::PrimitiveSetIndexedUInt
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PrimitiveSetIndexedUInt::PrimitiveSetIndexedUInt(PrimitiveType primitiveType)
: PrimitiveSet(primitiveType),
m_minIndex(0),
m_maxIndex(0)
{
}
//--------------------------------------------------------------------------------------------------
/// Deletes OpenGL resources created by this primitive set
//--------------------------------------------------------------------------------------------------
PrimitiveSetIndexedUInt::~PrimitiveSetIndexedUInt()
{
releaseBufferObjectsGPU();
}
//--------------------------------------------------------------------------------------------------
/// Render primitives in this primitive set using vertex arrays
///
/// \warning Requires at least OpenGL 1.5
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUInt::render(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_TIGHT_ASSERT(oglContext);
CVF_TIGHT_ASSERT(BufferObjectManaged::supportedOpenGL(oglContext));
if (m_indices.isNull())
{
return;
}
GLsizei numIndices = static_cast<GLsizei>(m_indices->size());
if (numIndices <= 0)
{
return;
}
const GLvoid* ptrOrOffset = 0;
if (m_indicesBO.notNull() && m_indicesBO->isUploaded())
{
m_indicesBO->bindBuffer(oglContext);
}
else
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
ptrOrOffset = m_indices->ptr();
}
#ifdef CVF_OPENGL_ES
glDrawElements(primitiveTypeOpenGL(), numIndices, GL_UNSIGNED_INT, ptrOrOffset);
#else
glDrawRangeElements(primitiveTypeOpenGL(), m_minIndex, m_maxIndex, numIndices, GL_UNSIGNED_INT, ptrOrOffset);
#endif
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
/// Create buffer object and upload data to the GPU
///
/// \warning The current render context must support buffer objects (OGL version >= 1.5)
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUInt::createUploadBufferObjectsGPU(OpenGLContext* oglContext)
{
CVF_TIGHT_ASSERT(oglContext);
CVF_TIGHT_ASSERT(BufferObjectManaged::supportedOpenGL(oglContext));
// Buffer object already in place?
if (m_indicesBO.notNull() && m_indicesBO->isUploaded())
{
return;
}
if (m_indices.notNull())
{
size_t numIndices = m_indices->size();
if (numIndices > 0)
{
GLuint uiSizeInBytes = static_cast<GLuint>(numIndices*sizeof(GLuint));
m_indicesBO = oglContext->resourceManager()->getOrCreateManagedBufferObject(oglContext, GL_ELEMENT_ARRAY_BUFFER, uiSizeInBytes, m_indices->ptr());
CVF_CHECK_OGL(oglContext);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUInt::releaseBufferObjectsGPU()
{
m_indicesBO = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUInt::setIndices(UIntArray* indices)
{
m_minIndex = 0;
m_maxIndex = 0;
m_indices = indices;
// Find min/max index present in array
size_t numIndices = m_indices.notNull() ? m_indices->size() : 0;
if (numIndices > 0)
{
uint thisIndex = m_indices->get(0);
m_minIndex = thisIndex;
m_maxIndex = thisIndex;
size_t i;
for (i = 1; i < numIndices; i++)
{
thisIndex = indices->get(i);
if (thisIndex < m_minIndex)
{
m_minIndex = thisIndex;
}
if (thisIndex > m_maxIndex)
{
m_maxIndex = thisIndex;
}
}
}
m_indicesBO = NULL;
}
//--------------------------------------------------------------------------------------------------
/// Get a const ptr to the indices (connectivities) stored in this primitive set
//--------------------------------------------------------------------------------------------------
const UIntArray* PrimitiveSetIndexedUInt::indices() const
{
return m_indices.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSetIndexedUInt::indexCount() const
{
return m_indices.notNull() ? m_indices->size() : 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint PrimitiveSetIndexedUInt::index(size_t i) const
{
CVF_TIGHT_ASSERT(m_indices.notNull());
return m_indices->get(i);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint PrimitiveSetIndexedUInt::minIndex() const
{
if (indexCount() > 0)
{
return m_minIndex;
}
else
{
return UNDEFINED_UINT;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint PrimitiveSetIndexedUInt::maxIndex() const
{
if (indexCount() > 0)
{
return m_maxIndex;
}
else
{
return UNDEFINED_UINT;
}
}
} // namespace cvf
@@ -0,0 +1,59 @@
//##################################################################################################
//
// 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 "cvfPrimitiveSet.h"
namespace cvf {
class BufferObjectManaged;
//==================================================================================================
//
//
//
//==================================================================================================
class PrimitiveSetIndexedUInt : public PrimitiveSet
{
public:
PrimitiveSetIndexedUInt(PrimitiveType primitiveType);
virtual ~PrimitiveSetIndexedUInt();
virtual void render(OpenGLContext* oglContext) const;
virtual void createUploadBufferObjectsGPU(OpenGLContext* oglContext);
virtual void releaseBufferObjectsGPU();
void setIndices(UIntArray* indices);
const UIntArray* indices() const;
virtual size_t indexCount() const;
virtual uint index(size_t i) const;
uint minIndex() const;
uint maxIndex() const;
private:
ref<UIntArray> m_indices;
uint m_minIndex;
uint m_maxIndex;
ref<BufferObjectManaged> m_indicesBO;
};
}
@@ -0,0 +1,231 @@
//##################################################################################################
//
// 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 "cvfMath.h"
#include "cvfPrimitiveSetIndexedUIntScoped.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfBufferObjectManaged.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::PrimitiveSetIndexedUIntScoped
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PrimitiveSetIndexedUIntScoped::PrimitiveSetIndexedUIntScoped(PrimitiveType primitiveType)
: PrimitiveSet(primitiveType),
m_firstElement(0),
m_elementCount(0)
{
}
//--------------------------------------------------------------------------------------------------
/// Deletes OpenGL resources created by this primitive set
//--------------------------------------------------------------------------------------------------
PrimitiveSetIndexedUIntScoped::~PrimitiveSetIndexedUIntScoped()
{
releaseBufferObjectsGPU();
}
//--------------------------------------------------------------------------------------------------
/// Render primitives in this primitive set using vertex arrays
///
/// \warning Requires at least OpenGL 1.5
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUIntScoped::render(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_TIGHT_ASSERT(BufferObjectManaged::supportedOpenGL(oglContext));
if (m_indices.isNull())
{
return;
}
GLsizei numIndices = static_cast<GLsizei>(m_elementCount);
if (numIndices <= 0)
{
return;
}
const GLvoid* ptrOrOffset = 0;
if (m_indicesBO.notNull() && m_indicesBO->isUploaded())
{
m_indicesBO->bindBuffer(oglContext);
ptrOrOffset = reinterpret_cast<GLvoid*>(m_firstElement*sizeof(uint));
}
else
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
ptrOrOffset = m_indices->ptr() + m_firstElement;
}
glDrawElements(primitiveTypeOpenGL(), numIndices, GL_UNSIGNED_INT, ptrOrOffset);
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
/// Create buffer object and upload data to the GPU
///
/// \warning The current render context must support buffer objects (OGL version >= 1.5)
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUIntScoped::createUploadBufferObjectsGPU(OpenGLContext* oglContext)
{
CVF_TIGHT_ASSERT(oglContext);
CVF_TIGHT_ASSERT(BufferObjectManaged::supportedOpenGL(oglContext));
// Buffer object already in place?
if (m_indicesBO.notNull() && m_indicesBO->isUploaded())
{
return;
}
if (m_indices.notNull())
{
size_t numIndices = m_indices->size();
if (numIndices > 0)
{
GLuint uiSizeInBytes = static_cast<GLuint>(numIndices*sizeof(GLuint));
m_indicesBO = oglContext->resourceManager()->getOrCreateManagedBufferObject(oglContext, GL_ELEMENT_ARRAY_BUFFER, uiSizeInBytes, m_indices->ptr());
CVF_CHECK_OGL(oglContext);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUIntScoped::releaseBufferObjectsGPU()
{
m_indicesBO = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUIntScoped::setIndices(UIntArray* indices, size_t firstElement, size_t elementCount)
{
if (indices)
{
CVF_ASSERT(firstElement < indices->size());
CVF_ASSERT(firstElement + elementCount <= indices->size());
m_indices = indices;
m_firstElement = firstElement;
m_elementCount = elementCount;
}
else
{
CVF_ASSERT(firstElement == 0);
CVF_ASSERT(elementCount == 0);
m_indices = NULL;
m_firstElement = 0;
m_elementCount = 0;
}
m_indicesBO = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUIntScoped::setScope(size_t firstElement, size_t elementCount)
{
if (m_indices.notNull())
{
CVF_ASSERT(firstElement < m_indices->size());
CVF_ASSERT(firstElement + elementCount <= m_indices->size());
m_firstElement = firstElement;
m_elementCount = elementCount;
}
else
{
CVF_ASSERT(firstElement == 0);
CVF_ASSERT(elementCount == 0);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const UIntArray* PrimitiveSetIndexedUIntScoped::indices() const
{
return m_indices.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSetIndexedUIntScoped::scopeFirstElement() const
{
return m_firstElement;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSetIndexedUIntScoped::scopeElementCount() const
{
return m_elementCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSetIndexedUIntScoped::indexCount() const
{
return m_elementCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint PrimitiveSetIndexedUIntScoped::index(size_t i) const
{
CVF_TIGHT_ASSERT(m_indices.notNull());
return m_indices->get(m_firstElement + i);
}
} // namespace cvf
@@ -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 "cvfPrimitiveSet.h"
namespace cvf {
class BufferObjectManaged;
//==================================================================================================
//
//
//
//==================================================================================================
class PrimitiveSetIndexedUIntScoped : public PrimitiveSet
{
public:
PrimitiveSetIndexedUIntScoped(PrimitiveType primitiveType);
virtual ~PrimitiveSetIndexedUIntScoped();
virtual void render(OpenGLContext* oglContext) const;
virtual void createUploadBufferObjectsGPU(OpenGLContext* oglContext);
virtual void releaseBufferObjectsGPU();
void setIndices(UIntArray* indices, size_t firstElement, size_t elementCount);
void setScope(size_t firstElement, size_t elementCount);
const UIntArray* indices() const;
size_t scopeFirstElement() const;
size_t scopeElementCount() const;
virtual size_t indexCount() const;
virtual uint index(size_t i) const;
private:
ref<UIntArray> m_indices;
size_t m_firstElement;
size_t m_elementCount;
ref<BufferObjectManaged> m_indicesBO;
};
}
@@ -0,0 +1,239 @@
//##################################################################################################
//
// 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 "cvfMath.h"
#include "cvfPrimitiveSetIndexedUShort.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfBufferObjectManaged.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::PrimitiveSetIndexedUShort
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PrimitiveSetIndexedUShort::PrimitiveSetIndexedUShort(PrimitiveType primitiveType)
: PrimitiveSet(primitiveType),
m_minIndex(0),
m_maxIndex(0)
{
}
//--------------------------------------------------------------------------------------------------
/// Deletes OpenGL resources created by this primitive set
//--------------------------------------------------------------------------------------------------
PrimitiveSetIndexedUShort::~PrimitiveSetIndexedUShort()
{
releaseBufferObjectsGPU();
}
//--------------------------------------------------------------------------------------------------
/// Render primitives in this primitive set using vertex arrays
///
/// \warning Requires at least OpenGL 1.5
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUShort::render(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_TIGHT_ASSERT(BufferObjectManaged::supportedOpenGL(oglContext));
if (m_indices.isNull())
{
return;
}
GLsizei numIndices = static_cast<GLsizei>(m_indices->size());
if (numIndices <= 0)
{
return;
}
const GLvoid* ptrOrOffset = 0;
if (m_indicesBO.notNull() && m_indicesBO->isUploaded())
{
m_indicesBO->bindBuffer(oglContext);
}
else
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
ptrOrOffset = m_indices->ptr();
}
#ifdef CVF_OPENGL_ES
glDrawElements(primitiveTypeOpenGL(), numIndices, GL_UNSIGNED_SHORT, ptrOrOffset);
#else
glDrawRangeElements(primitiveTypeOpenGL(), m_minIndex, m_maxIndex, numIndices, GL_UNSIGNED_SHORT, ptrOrOffset);
#endif
}
//--------------------------------------------------------------------------------------------------
/// Create buffer object and upload data to the GPU
///
/// \warning The current render context must support buffer objects (OGL version >= 1.5)
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUShort::createUploadBufferObjectsGPU(OpenGLContext* oglContext)
{
CVF_TIGHT_ASSERT(oglContext);
CVF_TIGHT_ASSERT(BufferObjectManaged::supportedOpenGL(oglContext));
// Buffer object already in place?
if (m_indicesBO.notNull() && m_indicesBO->isUploaded())
{
return;
}
if (m_indices.notNull())
{
size_t numIndices = m_indices->size();
if (numIndices > 0)
{
GLuint uiSizeInBytes = static_cast<GLuint>(numIndices*sizeof(GLushort));
m_indicesBO = oglContext->resourceManager()->getOrCreateManagedBufferObject(oglContext, GL_ELEMENT_ARRAY_BUFFER, uiSizeInBytes, m_indices->ptr());
CVF_CHECK_OGL(oglContext);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUShort::releaseBufferObjectsGPU()
{
m_indicesBO = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUShort::setIndices(UShortArray* indices)
{
m_minIndex = 0;
m_maxIndex = 0;
m_indices = indices;
// Find min/max index present in array
size_t numIndices = m_indices.notNull() ? m_indices->size() : 0;
if (numIndices > 0)
{
ushort thisIndex = m_indices->get(0);
m_minIndex = thisIndex;
m_maxIndex = thisIndex;
size_t i;
for (i = 1; i < numIndices; i++)
{
thisIndex = indices->get(i);
if (thisIndex < m_minIndex)
{
m_minIndex = thisIndex;
}
if (thisIndex > m_maxIndex)
{
m_maxIndex = thisIndex;
}
}
}
m_indicesBO = NULL;
}
//--------------------------------------------------------------------------------------------------
/// Get a const ptr to the indices (connectivities) stored in this primitive set
//--------------------------------------------------------------------------------------------------
const UShortArray* PrimitiveSetIndexedUShort::indices() const
{
return m_indices.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSetIndexedUShort::indexCount() const
{
return m_indices.notNull() ? m_indices->size() : 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint PrimitiveSetIndexedUShort::index(size_t i) const
{
CVF_TIGHT_ASSERT(m_indices.notNull());
return m_indices->get(i);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint PrimitiveSetIndexedUShort::minIndex() const
{
if (indexCount() > 0)
{
return m_minIndex;
}
else
{
return UNDEFINED_UINT;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint PrimitiveSetIndexedUShort::maxIndex() const
{
if (indexCount() > 0)
{
return m_maxIndex;
}
else
{
return UNDEFINED_UINT;
}
}
} // namespace cvf
@@ -0,0 +1,59 @@
//##################################################################################################
//
// 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 "cvfPrimitiveSet.h"
namespace cvf {
class BufferObjectManaged;
//==================================================================================================
//
//
//
//==================================================================================================
class PrimitiveSetIndexedUShort : public PrimitiveSet
{
public:
PrimitiveSetIndexedUShort(PrimitiveType primitiveType);
virtual ~PrimitiveSetIndexedUShort();
virtual void render(OpenGLContext* oglContext) const;
virtual void createUploadBufferObjectsGPU(OpenGLContext* oglContext);
virtual void releaseBufferObjectsGPU();
void setIndices(UShortArray* indices);
const UShortArray* indices() const;
virtual size_t indexCount() const;
virtual uint index(size_t i) const;
uint minIndex() const;
uint maxIndex() const;
private:
ref<UShortArray> m_indices;
ushort m_minIndex;
ushort m_maxIndex;
ref<BufferObjectManaged> m_indicesBO;
};
}
@@ -0,0 +1,231 @@
//##################################################################################################
//
// 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 "cvfMath.h"
#include "cvfPrimitiveSetIndexedUShortScoped.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfBufferObjectManaged.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::PrimitiveSetIndexedUShortScoped
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PrimitiveSetIndexedUShortScoped::PrimitiveSetIndexedUShortScoped(PrimitiveType primitiveType)
: PrimitiveSet(primitiveType),
m_firstElement(0),
m_elementCount(0)
{
}
//--------------------------------------------------------------------------------------------------
/// Deletes OpenGL resources created by this primitive set
//--------------------------------------------------------------------------------------------------
PrimitiveSetIndexedUShortScoped::~PrimitiveSetIndexedUShortScoped()
{
releaseBufferObjectsGPU();
}
//--------------------------------------------------------------------------------------------------
/// Render primitives in this primitive set using vertex arrays
///
/// \warning Requires at least OpenGL 1.5
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUShortScoped::render(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_ASSERT(BufferObjectManaged::supportedOpenGL(oglContext));
if (m_indices.isNull())
{
return;
}
GLsizei numIndices = static_cast<GLsizei>(m_elementCount);
if (numIndices <= 0)
{
return;
}
const GLvoid* ptrOrOffset = 0;
if (m_indicesBO.notNull() && m_indicesBO->isUploaded())
{
m_indicesBO->bindBuffer(oglContext);
ptrOrOffset = reinterpret_cast<GLvoid*>(m_firstElement*sizeof(GLushort));
}
else
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
ptrOrOffset = m_indices->ptr() + m_firstElement;
}
glDrawElements(primitiveTypeOpenGL(), numIndices, GL_UNSIGNED_SHORT, ptrOrOffset);
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
/// Create buffer object and upload data to the GPU
///
/// \warning The current render context must support buffer objects (OGL version >= 1.5)
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUShortScoped::createUploadBufferObjectsGPU(OpenGLContext* oglContext)
{
CVF_TIGHT_ASSERT(oglContext);
CVF_TIGHT_ASSERT(BufferObjectManaged::supportedOpenGL(oglContext));
// Buffer object already in place?
if (m_indicesBO.notNull() && m_indicesBO->isUploaded())
{
return;
}
if (m_indices.notNull())
{
size_t numIndices = m_indices->size();
if (numIndices > 0)
{
GLuint uiSizeInBytes = static_cast<GLuint>(numIndices*sizeof(GLushort));
m_indicesBO = oglContext->resourceManager()->getOrCreateManagedBufferObject(oglContext, GL_ELEMENT_ARRAY_BUFFER, uiSizeInBytes, m_indices->ptr());
CVF_CHECK_OGL(oglContext);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUShortScoped::releaseBufferObjectsGPU()
{
m_indicesBO = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUShortScoped::setIndices(UShortArray* indices, size_t firstElement, size_t elementCount)
{
if (indices)
{
CVF_ASSERT(firstElement < indices->size());
CVF_ASSERT(firstElement + elementCount <= indices->size());
m_indices = indices;
m_firstElement = firstElement;
m_elementCount = elementCount;
}
else
{
CVF_ASSERT(firstElement == 0);
CVF_ASSERT(elementCount == 0);
m_indices = NULL;
m_firstElement = 0;
m_elementCount = 0;
}
m_indicesBO = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PrimitiveSetIndexedUShortScoped::setScope(size_t firstElement, size_t elementCount)
{
if (m_indices.notNull())
{
CVF_ASSERT(firstElement < m_indices->size());
CVF_ASSERT(firstElement + elementCount <= m_indices->size());
m_firstElement = firstElement;
m_elementCount = elementCount;
}
else
{
CVF_ASSERT(firstElement == 0);
CVF_ASSERT(elementCount == 0);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSetIndexedUShortScoped::scopeFirstElement() const
{
return m_firstElement;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSetIndexedUShortScoped::scopeElementCount() const
{
return m_elementCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const UShortArray* PrimitiveSetIndexedUShortScoped::indices() const
{
return m_indices.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t PrimitiveSetIndexedUShortScoped::indexCount() const
{
return m_elementCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint PrimitiveSetIndexedUShortScoped::index(size_t i) const
{
CVF_TIGHT_ASSERT(m_indices.notNull());
return m_indices->get(m_firstElement + i);
}
} // namespace cvf
@@ -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 "cvfPrimitiveSet.h"
namespace cvf {
class BufferObjectManaged;
//==================================================================================================
//
//
//
//==================================================================================================
class PrimitiveSetIndexedUShortScoped : public PrimitiveSet
{
public:
PrimitiveSetIndexedUShortScoped(PrimitiveType primitiveType);
virtual ~PrimitiveSetIndexedUShortScoped();
virtual void render(OpenGLContext* oglContext) const;
virtual void createUploadBufferObjectsGPU(OpenGLContext* oglContext);
virtual void releaseBufferObjectsGPU();
void setIndices(UShortArray* indices, size_t firstElement, size_t elementCount);
void setScope(size_t firstElement, size_t elementCount);
const UShortArray* indices() const;
size_t scopeFirstElement() const;
size_t scopeElementCount() const;
virtual size_t indexCount() const;
virtual uint index(size_t i) const;
private:
ref<UShortArray> m_indices;
size_t m_firstElement;
size_t m_elementCount;
ref<BufferObjectManaged> m_indicesBO;
};
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,425 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfOpenGLTypes.h"
#include "cvfColor4.h"
#include "cvfString.h"
namespace cvf {
class OpenGLContext;
class ShaderProgram;
class Sampler;
class Texture;
//==================================================================================================
//
// Base class for storing and changing OpenGL state attributes
//
//==================================================================================================
class RenderState : public Object
{
public:
enum Type
{
BLENDING, // Must start at 0, used for indexing in RenderStateTracker
COLOR_MASK,
CULL_FACE,
FRONT_FACE,
DEPTH,
POINT,
POLYGON_MODE,
POLYGON_OFFSET,
TEXTURE_BINDINGS,
#ifndef CVF_OPENGL_ES
LIGHTING_FF, //Fixed function
MATERIAL_FF, //Fixed function
NORMALIZE_FF, //Fixed function
TEXTURE_MAPPING_FF, //Fixed function
#endif
COUNT // Must be the last entry
};
public:
virtual ~RenderState();
Type type() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const = 0;
virtual bool isFixedFunction() const;
protected:
RenderState(Type type);
private:
Type m_stateType;
};
//==================================================================================================
//
// 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
@@ -0,0 +1,149 @@
//##################################################################################################
//
// 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 "cvfRenderStateSet.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStateSet
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateSet::RenderStateSet()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint RenderStateSet::count() const
{
return static_cast<uint>(m_renderStates.size());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderState* RenderStateSet::renderState(uint index)
{
CVF_ASSERT(index < count());
return m_renderStates[index].p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RenderState* RenderStateSet::renderState(uint index) const
{
CVF_ASSERT(index < count());
return m_renderStates[index].p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateSet::setRenderState(RenderState* renderState)
{
CVF_ASSERT(renderState);
RenderState::Type incomingType = renderState->type();
size_t numStates = m_renderStates.size();
size_t i;
for (i = 0; i < numStates; i++)
{
if (m_renderStates[i]->type() == incomingType)
{
m_renderStates[i] = renderState;
return;
}
}
m_renderStates.push_back(renderState);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderState* RenderStateSet::renderStateOfType(RenderState::Type type)
{
size_t numStates = m_renderStates.size();
size_t i;
for (i = 0; i < numStates; i++)
{
if (m_renderStates[i]->type() == type)
{
return m_renderStates[i].p();
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RenderState* RenderStateSet::renderStateOfType(RenderState::Type type) const
{
size_t numStates = m_renderStates.size();
size_t i;
for (i = 0; i < numStates; i++)
{
if (m_renderStates[i]->type() == type)
{
return m_renderStates[i].p();
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateSet::removeRenderState(const RenderState* renderState)
{
m_renderStates.erase(renderState);
}
} // namespace cvf
@@ -0,0 +1,53 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfRenderState.h"
#include "cvfCollection.h"
namespace cvf {
//==================================================================================================
//
//
//
//==================================================================================================
class RenderStateSet : public Object
{
public:
RenderStateSet();
uint count() const;
RenderState* renderState(uint index);
const RenderState* renderState(uint index) const;
void setRenderState(RenderState* renderState);
RenderState* renderStateOfType(RenderState::Type type);
const RenderState* renderStateOfType(RenderState::Type type) const;
void removeRenderState(const RenderState* renderState);
private:
Collection<RenderState> m_renderStates;
};
}
@@ -0,0 +1,189 @@
//##################################################################################################
//
// 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 "cvfRenderStateTracker.h"
#include "cvfRenderStateSet.h"
#include "cvfOpenGLContext.h"
#include "cvfOpenGLCapabilities.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#endif
#include <memory.h>
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderStateTracker
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateTracker::RenderStateTracker()
{
memset(m_renderStateUsageTable, 0, sizeof(m_renderStateUsageTable));
memset(m_currentRenderStates, 0, sizeof(m_currentRenderStates));
setupDefaultRenderStates();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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;
#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;
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderStateTracker::resetAndApplyDefaultRenderStates(OpenGLContext* oglContext)
{
memset(m_renderStateUsageTable, 0, sizeof(m_renderStateUsageTable));
memset(m_currentRenderStates, 0, sizeof(m_currentRenderStates));
bool contextSupportsFixedFunction = oglContext->capabilities()->supportsFixedFunction();
int numRenderStates = RenderState::COUNT;
int i;
for (i = 0; i < numRenderStates; i++)
{
RenderState* rs = m_defaultRenderStates[i].p();
CVF_ASSERT(rs);
if (rs->isFixedFunction())
{
// Apply fixed function render states ONLY if the OpenGL context supports it
if (contextSupportsFixedFunction)
{
rs->applyOpenGL(oglContext);
}
}
else
{
rs->applyOpenGL(oglContext);
}
}
}
//--------------------------------------------------------------------------------------------------
/// Apply states in RenderStateSet
///
/// \param oglContext The current OpenGLContext
/// \param newRSS The new RenderStateSet that is to be applied
/// \param prevRSS The previous RenderStateSet
//--------------------------------------------------------------------------------------------------
void RenderStateTracker::applyRenderStates(OpenGLContext* oglContext, const RenderStateSet* newRSS, const RenderStateSet* prevRSS)
{
const int IS_DEFAULT = 0;
const int IN_USE = 1;
const int WILL_BE_SET = 2;
// If there is no previous state set, assume all render states are at defaults
if (!prevRSS)
{
memset(m_renderStateUsageTable, IS_DEFAULT, sizeof(m_renderStateUsageTable));
memset(m_currentRenderStates, 0, sizeof(m_currentRenderStates));
}
uint numNewStates = newRSS ? newRSS->count() : 0;
// Modify the usage flag for all the states that are present in the new state set.
// These will be set later so there is no need to set them back to the defaults
uint i;
for (i = 0; i < numNewStates; i++)
{
m_renderStateUsageTable[newRSS->renderState(i)->type()] = WILL_BE_SET;
}
// Iterate over the previous state set
// Apply the corresponding default state only if it won't be overwritten when we apply the new states later
if (prevRSS)
{
uint numPrevStates = prevRSS->count();
for (i = 0; i < numPrevStates; i++)
{
RenderState::Type stateType = prevRSS->renderState(i)->type();
// Only need to apply the corresponding default if it is flagged as IN_USE
// States with the WILL_BE_SET usage are handled in the final loop below
if (m_renderStateUsageTable[stateType] == IN_USE)
{
const RenderState* defaultState = m_defaultRenderStates[stateType].p();
defaultState->applyOpenGL(oglContext);
m_currentRenderStates[stateType] = defaultState;
m_renderStateUsageTable[stateType] = IS_DEFAULT;
}
}
}
// Iterate over the incoming new render states
// Call apply function only if the new state is different from the current one
for (i = 0; i < numNewStates; i++)
{
const RenderState* newState = newRSS->renderState(i);
CVF_ASSERT(newState);
RenderState::Type stateType = newState->type();
if (m_currentRenderStates[stateType] != newState)
{
newState->applyOpenGL(oglContext);
m_currentRenderStates[stateType] = newState;
}
m_renderStateUsageTable[stateType] = IN_USE;
}
}
} // namespace cvf
@@ -0,0 +1,52 @@
//##################################################################################################
//
// 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 {
class RenderStateSet;
class OpenGLContext;
//==================================================================================================
//
// RenderStateTracker
//
//==================================================================================================
class RenderStateTracker
{
public:
RenderStateTracker();
void resetAndApplyDefaultRenderStates(OpenGLContext* oglContext);
void applyRenderStates(OpenGLContext* oglContext, const RenderStateSet* newRSS, const RenderStateSet* prevRSS);
private:
void setupDefaultRenderStates();
private:
int m_renderStateUsageTable[RenderState::COUNT];
const RenderState* m_currentRenderStates[RenderState::COUNT]; // Pointers to the render states that are current
ref<RenderState> m_defaultRenderStates[RenderState::COUNT]; // Default render states, contains all known render states initialized to their defaults
};
}
@@ -0,0 +1,665 @@
//##################################################################################################
//
// 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 "cvfOpenGL.h"
#include "cvfColor4.h"
#include "cvfMath.h"
#include "cvfRenderState_FF.h"
#include "cvfTexture2D_FF.h"
#include "cvfOpenGLCapabilities.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Lighting_FF
/// \ingroup Render
///
/// Encapsulate OpenGL glLightModel() and glEnable()/glDisable() with GL_LIGHTING
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Lighting_FF::Lighting_FF(bool enableLighting)
: RenderState(LIGHTING_FF),
m_enableLighting(enableLighting),
m_twoSided(false),
m_localViewer(false),
m_ambientIntensity(0.2f, 0.2f, 0.2f, 1.0f)
{
}
//--------------------------------------------------------------------------------------------------
/// Enables or disables fixed function lighting calculations
///
/// \sa http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml with GL_LIGHTING
//--------------------------------------------------------------------------------------------------
void Lighting_FF::enable(bool enableLighting)
{
m_enableLighting = enableLighting;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Lighting_FF::enableTwoSided(bool enableTwoSided)
{
m_twoSided = enableTwoSided;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Lighting_FF::enableLocalViewer(bool enableLocalViewer)
{
m_localViewer = enableLocalViewer;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Lighting_FF::setAmbientIntensity(const Color3f& ambientIntensity)
{
m_ambientIntensity.set(ambientIntensity, 1.0f);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Lighting_FF::isEnabled() const
{
return m_enableLighting;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Lighting_FF::isTwoSidedEnabled() const
{
return m_twoSided;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Lighting_FF::isLocalViewerEnabled() const
{
return m_localViewer;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f Lighting_FF::ambientIntensity() const
{
return m_ambientIntensity.toColor3f();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Lighting_FF::applyOpenGL(OpenGLContext* oglContext) const
{
if (m_enableLighting)
{
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, m_twoSided ? 1 : 0);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, m_localViewer ? 1 : 0);
CVF_ASSERT(m_ambientIntensity.isValid());
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, m_ambientIntensity.ptr());
glEnable(GL_LIGHTING);
}
else
{
glDisable(GL_LIGHTING);
}
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Lighting_FF::isFixedFunction() const
{
return true;
}
//==================================================================================================
///
/// \class cvf::Material_FF
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Default constructor, initializes all values to OpenGL defaults
//--------------------------------------------------------------------------------------------------
Material_FF::Material_FF()
: RenderState(MATERIAL_FF),
m_ambient(0.2f, 0.2f, 0.2f),
m_diffuse(0.8f, 0.8f, 0.8f),
m_specular(0, 0, 0),
m_emission(0, 0, 0),
m_alpha(1.0f),
m_shininess(0),
m_enableColorMaterial(false)
{
}
//--------------------------------------------------------------------------------------------------
/// Constructor taking ambient and diffuse color
//--------------------------------------------------------------------------------------------------
Material_FF::Material_FF(const Color3f& ambientAndDiffuseColor)
: RenderState(MATERIAL_FF),
m_ambient(ambientAndDiffuseColor),
m_diffuse(ambientAndDiffuseColor),
m_specular(0, 0, 0),
m_emission(0, 0, 0),
m_alpha(1.0f),
m_shininess(0),
m_enableColorMaterial(false)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Material_FF::Material_FF(MaterialIdent materialIdent)
: RenderState(MATERIAL_FF),
m_specular(0, 0, 0),
m_emission(0, 0, 0),
m_alpha(1.0f),
m_shininess(0),
m_enableColorMaterial(false)
{
switch (materialIdent)
{
case PURE_WHITE: m_ambient.set(1.0f, 1.0f, 1.0f); m_diffuse.set(1.0f, 1.0f, 1.0f); break;
case PURE_BLACK: m_ambient.set(0.0f, 0.0f, 0.0f); m_diffuse.set(0.0f, 0.0f, 0.0f); break;
case PURE_RED: m_ambient.set(1.0f, 0.0f, 0.0f); m_diffuse.set(1.0f, 0.0f, 0.0f); break;
case PURE_GREEN: m_ambient.set(0.0f, 1.0f, 0.0f); m_diffuse.set(0.0f, 1.0f, 0.0f); break;
case PURE_BLUE: m_ambient.set(0.0f, 0.0f, 1.0f); m_diffuse.set(0.0f, 0.0f, 1.0f); break;
case PURE_YELLOW: m_ambient.set(1.0f, 1.0f, 0.0f); m_diffuse.set(1.0f, 1.0f, 0.0f); break;
case PURE_MAGENTA: m_ambient.set(1.0f, 0.0f, 1.0f); m_diffuse.set(1.0f, 0.0f, 1.0f); break;
case PURE_CYAN: m_ambient.set(0.0f, 1.0f, 1.0f); m_diffuse.set(0.0f, 1.0f, 1.0f); break;
case BRASS: m_ambient.set(0.329412f, 0.223529f, 0.027451f); m_diffuse.set(0.780392f, 0.568627f, 0.113725f); m_specular.set(0.992157f, 0.941176f, 0.807843f); m_alpha = 1.00f; m_shininess = 27.8974f; break;
case BRONZE: m_ambient.set(0.212500f, 0.127500f, 0.054000f); m_diffuse.set(0.714000f, 0.428400f, 0.181440f); m_specular.set(0.393548f, 0.271906f, 0.166721f); m_alpha = 1.00f; m_shininess = 25.6000f; break;
case POLISHED_BRONZE: m_ambient.set(0.250000f, 0.148000f, 0.064750f); m_diffuse.set(0.400000f, 0.236800f, 0.103600f); m_specular.set(0.774597f, 0.458561f, 0.200621f); m_alpha = 1.00f; m_shininess = 76.8000f; break;
case CHROME: m_ambient.set(0.250000f, 0.250000f, 0.250000f); m_diffuse.set(0.400000f, 0.400000f, 0.400000f); m_specular.set(0.774597f, 0.774597f, 0.774597f); m_alpha = 1.00f; m_shininess = 76.8000f; break;
case COPPER: m_ambient.set(0.191250f, 0.073500f, 0.022500f); m_diffuse.set(0.703800f, 0.270480f, 0.082800f); m_specular.set(0.256777f, 0.137622f, 0.086014f); m_alpha = 1.00f; m_shininess = 12.8000f; break;
case POLISHED_COPPER: m_ambient.set(0.229500f, 0.088250f, 0.027500f); m_diffuse.set(0.550800f, 0.211800f, 0.066000f); m_specular.set(0.580594f, 0.223257f, 0.069570f); m_alpha = 1.00f; m_shininess = 51.2000f; break;
case GOLD: m_ambient.set(0.247250f, 0.199500f, 0.074500f); m_diffuse.set(0.751640f, 0.606480f, 0.226480f); m_specular.set(0.628281f, 0.555802f, 0.366065f); m_alpha = 1.00f; m_shininess = 51.2000f; break;
case POLISHED_GOLD: m_ambient.set(0.247250f, 0.224500f, 0.064500f); m_diffuse.set(0.346150f, 0.314300f, 0.090300f); m_specular.set(0.797357f, 0.723991f, 0.208006f); m_alpha = 1.00f; m_shininess = 83.2000f; break;
case PEWTER: m_ambient.set(0.105882f, 0.058824f, 0.113725f); m_diffuse.set(0.427451f, 0.470588f, 0.541176f); m_specular.set(0.333333f, 0.333333f, 0.521569f); m_alpha = 1.00f; m_shininess = 9.8462f; break;
case SILVER: m_ambient.set(0.192250f, 0.192250f, 0.192250f); m_diffuse.set(0.507540f, 0.507540f, 0.507540f); m_specular.set(0.508273f, 0.508273f, 0.508273f); m_alpha = 1.00f; m_shininess = 51.2000f; break;
case POLISHED_SILVER: m_ambient.set(0.231250f, 0.231250f, 0.231250f); m_diffuse.set(0.277500f, 0.277500f, 0.277500f); m_specular.set(0.773911f, 0.773911f, 0.773911f); m_alpha = 1.00f; m_shininess = 89.6000f; break;
case EMERALD: m_ambient.set(0.021500f, 0.174500f, 0.021500f); m_diffuse.set(0.075680f, 0.614240f, 0.075680f); m_specular.set(0.633000f, 0.727811f, 0.633000f); m_alpha = 0.55f; m_shininess = 76.8000f; break;
case JADE: m_ambient.set(0.135000f, 0.222500f, 0.157500f); m_diffuse.set(0.540000f, 0.890000f, 0.630000f); m_specular.set(0.316228f, 0.316228f, 0.316228f); m_alpha = 0.95f; m_shininess = 12.8000f; break;
case OBSIDIAN: m_ambient.set(0.053750f, 0.050000f, 0.066250f); m_diffuse.set(0.182750f, 0.170000f, 0.225250f); m_specular.set(0.332741f, 0.328634f, 0.346435f); m_alpha = 0.82f; m_shininess = 38.4000f; break;
case PEARL: m_ambient.set(0.250000f, 0.207250f, 0.207250f); m_diffuse.set(1.000000f, 0.829000f, 0.829000f); m_specular.set(0.296648f, 0.296648f, 0.296648f); m_alpha = 0.92f; m_shininess = 11.2640f; break;
case RUBY: m_ambient.set(0.174500f, 0.011750f, 0.011750f); m_diffuse.set(0.614240f, 0.041360f, 0.041360f); m_specular.set(0.727811f, 0.626959f, 0.626959f); m_alpha = 0.55f; m_shininess = 76.8000f; break;
case TURQUOISE: m_ambient.set(0.100000f, 0.187250f, 0.174500f); m_diffuse.set(0.396000f, 0.741510f, 0.691020f); m_specular.set(0.297254f, 0.308290f, 0.306678f); m_alpha = 0.80f; m_shininess = 12.8000f; break;
case BLACK_PLASTIC: m_ambient.set(0.000000f, 0.000000f, 0.000000f); m_diffuse.set(0.010000f, 0.010000f, 0.010000f); m_specular.set(0.500000f, 0.500000f, 0.500000f); m_alpha = 1.00f; m_shininess = 32.0000f; break;
case CYAN_PLASTIC: m_ambient.set(0.000000f, 0.100000f, 0.060000f); m_diffuse.set(0.000000f, 0.509804f, 0.509804f); m_specular.set(0.501961f, 0.501961f, 0.501961f); m_alpha = 1.00f; m_shininess = 32.0000f; break;
case GREEN_PLASTIC: m_ambient.set(0.000000f, 0.000000f, 0.000000f); m_diffuse.set(0.100000f, 0.350000f, 0.100000f); m_specular.set(0.450000f, 0.550000f, 0.450000f); m_alpha = 1.00f; m_shininess = 32.0000f; break;
case RED_PLASTIC: m_ambient.set(0.000000f, 0.000000f, 0.000000f); m_diffuse.set(0.500000f, 0.000000f, 0.000000f); m_specular.set(0.700000f, 0.600000f, 0.600000f); m_alpha = 1.00f; m_shininess = 32.0000f; break;
case WHITE_PLASTIC: m_ambient.set(0.000000f, 0.000000f, 0.000000f); m_diffuse.set(0.550000f, 0.550000f, 0.550000f); m_specular.set(0.700000f, 0.700000f, 0.700000f); m_alpha = 1.00f; m_shininess = 32.0000f; break;
case YELLOW_PLASTIC: m_ambient.set(0.000000f, 0.000000f, 0.000000f); m_diffuse.set(0.500000f, 0.500000f, 0.000000f); m_specular.set(0.600000f, 0.600000f, 0.500000f); m_alpha = 1.00f; m_shininess = 32.0000f; break;
case BLACK_RUBBER: m_ambient.set(0.020000f, 0.020000f, 0.020000f); m_diffuse.set(0.010000f, 0.010000f, 0.010000f); m_specular.set(0.400000f, 0.400000f, 0.400000f); m_alpha = 1.00f; m_shininess = 10.0000f; break;
case CYAN_RUBBER: m_ambient.set(0.000000f, 0.050000f, 0.050000f); m_diffuse.set(0.400000f, 0.500000f, 0.500000f); m_specular.set(0.040000f, 0.700000f, 0.700000f); m_alpha = 1.00f; m_shininess = 10.0000f; break;
case GREEN_RUBBER: m_ambient.set(0.000000f, 0.050000f, 0.000000f); m_diffuse.set(0.400000f, 0.500000f, 0.400000f); m_specular.set(0.040000f, 0.700000f, 0.040000f); m_alpha = 1.00f; m_shininess = 10.0000f; break;
case RED_RUBBER: m_ambient.set(0.050000f, 0.000000f, 0.000000f); m_diffuse.set(0.500000f, 0.400000f, 0.400000f); m_specular.set(0.700000f, 0.040000f, 0.040000f); m_alpha = 1.00f; m_shininess = 10.0000f; break;
case WHITE_RUBBER: m_ambient.set(0.050000f, 0.050000f, 0.050000f); m_diffuse.set(0.500000f, 0.500000f, 0.500000f); m_specular.set(0.700000f, 0.700000f, 0.700000f); m_alpha = 1.00f; m_shininess = 10.0000f; break;
case YELLOW_RUBBER: m_ambient.set(0.050000f, 0.050000f, 0.000000f); m_diffuse.set(0.500000f, 0.500000f, 0.400000f); m_specular.set(0.700000f, 0.700000f, 0.040000f); m_alpha = 1.00f; m_shininess = 10.0000f; break;
default: CVF_FAIL_MSG("Unhandled MaterialIdent");
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::setAmbientAndDiffuse(const Color3f& color)
{
CVF_ASSERT(color.isValid());
m_ambient = color;
m_diffuse = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::setDiffuse(const Color3f& color)
{
CVF_ASSERT(color.isValid());
m_diffuse = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::setSpecular(const Color3f& color)
{
CVF_ASSERT(color.isValid());
m_specular = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::setAlpha(float alpha)
{
m_alpha = alpha;
}
//--------------------------------------------------------------------------------------------------
/// Value that specifies the RGBA specular exponent of the material.
/// 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)
{
m_shininess = shininess;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f Material_FF::frontAmbient() const
{
return m_ambient;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f Material_FF::frontDiffuse() const
{
return m_diffuse;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f Material_FF::frontSpecular() const
{
return m_specular;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f Material_FF::frontEmission() const
{
return m_emission;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Material_FF::frontAlpha() const
{
return m_alpha;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Material_FF::frontShininess() const
{
return m_shininess;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::enableColorMaterial(bool enableColorMaterial)
{
m_enableColorMaterial = enableColorMaterial;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Material_FF::isColorMaterialEnabled() const
{
return m_enableColorMaterial;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Material_FF::applyOpenGL(OpenGLContext* oglContext) const
{
Color4f ambient(m_ambient, m_alpha);
Color4f diffuse(m_diffuse, m_alpha);
Color4f emission(m_emission, m_alpha);
Color4f specular(m_specular, m_alpha);
CVF_ASSERT(ambient.isValid());
CVF_ASSERT(diffuse.isValid());
CVF_ASSERT(emission.isValid());
CVF_ASSERT(specular.isValid());
CVF_ASSERT(Math::valueInRange(m_shininess, 0.0f, 128.0f));
if (m_enableColorMaterial)
{
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
}
else
{
glDisable(GL_COLOR_MATERIAL);
}
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient.ptr());
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.ptr());
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular.ptr());
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emission.ptr());
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, m_shininess);
// Try this to be nice if lighting is off
glColor3fv(diffuse.ptr());
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Material_FF::isFixedFunction() const
{
return true;
}
//==================================================================================================
///
/// \class cvf::Normalize_FF
/// \ingroup Render
///
/// Controls normalization of normals in fixed function
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Normalize_FF::Normalize_FF(bool enableNormalization)
: RenderState(NORMALIZE_FF),
m_enable(enableNormalization)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Normalize_FF::enable(bool enableNormalization)
{
m_enable = enableNormalization;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Normalize_FF::isEnabled() const
{
return m_enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Normalize_FF::applyOpenGL(OpenGLContext* oglContext) const
{
if (m_enable)
{
glEnable(GL_NORMALIZE);
}
else
{
glEnable(GL_NORMALIZE);
}
CVF_CHECK_OGL(oglContext);
}
//==================================================================================================
///
/// \class cvf::TextureMapping_FF
/// \ingroup Render
///
/// Enable 2D texturing for texture unit 0 and fixed function
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TextureMapping_FF::TextureMapping_FF(Texture2D_FF* texture)
: RenderState(TEXTURE_MAPPING_FF),
m_texture(texture),
m_textureFunction(MODULATE),
m_environmentMapping(false)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TextureMapping_FF::~TextureMapping_FF()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureMapping_FF::setTexture(Texture2D_FF* texture)
{
m_texture = texture;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Texture2D_FF* TextureMapping_FF::texture()
{
return m_texture.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureMapping_FF::setTextureFunction(TextureFunction texFunc)
{
m_textureFunction = texFunc;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TextureMapping_FF::TextureFunction TextureMapping_FF::textureFunction() const
{
return m_textureFunction;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureMapping_FF::setEnvironmentMapping(bool environmentMapping)
{
m_environmentMapping = environmentMapping;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool TextureMapping_FF::environmentMapping() const
{
return m_environmentMapping;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureMapping_FF::setupTexture(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
if (m_texture.notNull())
{
if (m_texture->textureOglId() == 0)
{
if (oglContext->capabilities()->supportsOpenGL2())
{
glActiveTexture(GL_TEXTURE0);
}
m_texture->setupTexture(oglContext);
CVF_CHECK_OGL(oglContext);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TextureMapping_FF::applyOpenGL(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
if (oglContext->capabilities()->supportsOpenGL2())
{
glActiveTexture(GL_TEXTURE0);
}
if (m_texture.notNull() && m_texture->textureOglId() != 0)
{
m_texture->bind(oglContext);
m_texture->setupTextureParams(oglContext);
cvfGLint oglTexFunc = GL_MODULATE;
switch (m_textureFunction)
{
case MODULATE: oglTexFunc = GL_MODULATE; break;
case DECAL: oglTexFunc = GL_DECAL; break;
}
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, oglTexFunc);
glEnable(GL_TEXTURE_2D);
if (m_environmentMapping)
{
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
GLint piSphereMap[1];
piSphereMap[0] = GL_SPHERE_MAP;
glTexGeniv(GL_S, GL_TEXTURE_GEN_MODE, piSphereMap);
glTexGeniv(GL_T, GL_TEXTURE_GEN_MODE, piSphereMap);
}
else
{
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
}
}
else
{
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
}
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool TextureMapping_FF::isFixedFunction() const
{
return true;
}
} // namespace cvf
@@ -0,0 +1,209 @@
//##################################################################################################
//
// 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 "cvfColor4.h"
namespace cvf {
class Texture2D_FF;
//==================================================================================================
//
// Encapsulates OpenGL's glLightModel() and glEnable()/glDisable() with GL_LIGHTING
//
//==================================================================================================
class Lighting_FF : public RenderState
{
public:
Lighting_FF(bool enableLighting = true);
void enable(bool enableLighting);
bool isEnabled() const;
void enableTwoSided(bool enableTwoSided);
void enableLocalViewer(bool enableLocalViewer);
void setAmbientIntensity(const Color3f& ambientIntensity);
bool isTwoSidedEnabled() const;
bool isLocalViewerEnabled() const;
Color3f ambientIntensity() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
virtual bool isFixedFunction() const;
private:
bool m_enableLighting; // Master enable/disable switch for fixed function OpenGL lighting
bool m_twoSided; // Two sided lighting
bool m_localViewer; // Determines how specular reflection angles are computed
Color4f m_ambientIntensity; // The global ambient light intensity
};
//==================================================================================================
//
// Encapsulates OpenGL glMaterial() state
//
//==================================================================================================
class Material_FF : public RenderState
{
public:
enum MaterialIdent
{
// Simple materials with just ambient and diffuse set. All other parameters are left at defaults
PURE_WHITE, ///< White material
PURE_BLACK, ///< Black material
PURE_RED, ///< Red material
PURE_GREEN, ///< Green material
PURE_BLUE, ///< Blue material
PURE_YELLOW, ///< Yellow material
PURE_MAGENTA, ///< Magenta material
PURE_CYAN, ///< Cyan material
// Parameters for common materials, based on table presented in SIGGRAPH 99, Lighting and Shading Techniques for Interactive Applications.
// Sets specular and shininess in addition to ambient and diffuse, and may also include transparency (alpha value)
BRASS, ///< Brass
BRONZE, ///< Bronze
POLISHED_BRONZE, ///< Polished Bronze
CHROME, ///< Chrome
COPPER, ///< Copper
POLISHED_COPPER, ///< Polished Copper
GOLD, ///< Gold
POLISHED_GOLD, ///< Polished Gold
PEWTER, ///< Pewter
SILVER, ///< Silver
POLISHED_SILVER, ///< Polished Silver
EMERALD, ///< Emerald
JADE, ///< Jade
OBSIDIAN, ///< Obsidian
PEARL, ///< Pearl
RUBY, ///< Ruby
TURQUOISE, ///< Turquoise
BLACK_PLASTIC, ///< Black Plastic
CYAN_PLASTIC, ///< Cyan Plastic
GREEN_PLASTIC, ///< Green Plastic
RED_PLASTIC, ///< Red Plastic
WHITE_PLASTIC, ///< White Plastic
YELLOW_PLASTIC, ///< Yellow Plastic
BLACK_RUBBER, ///< Black Rubber
CYAN_RUBBER, ///< Cyan Rubber
GREEN_RUBBER, ///< Green Rubber
RED_RUBBER, ///< Red Rubber
WHITE_RUBBER, ///< White Rubber
YELLOW_RUBBER ///< Yellow Rubber
};
public:
Material_FF();
explicit Material_FF(const Color3f& ambientAndDiffuseColor);
explicit Material_FF(MaterialIdent materialIdent);
void setAmbientAndDiffuse(const Color3f& color);
void setDiffuse(const Color3f& color);
void setSpecular(const Color3f& color);
void setAlpha(float alpha);
void setShininess(float shininess);
Color3f frontAmbient() const;
Color3f frontDiffuse() const;
Color3f frontSpecular() const;
Color3f frontEmission() const;
float frontAlpha() const;
float frontShininess() const;
void enableColorMaterial(bool enableColorMaterial);
bool isColorMaterialEnabled() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
virtual bool isFixedFunction() const;
private:
Color3f m_ambient;
Color3f m_diffuse;
Color3f m_specular;
Color3f m_emission;
float m_alpha; // Alpha, 1.0 is no transparency, 0.0 completely transparent
float m_shininess; // Range 0.0 to 128.0
bool m_enableColorMaterial;
};
//==================================================================================================
//
// Controls normalization of normals in fixed function
//
//==================================================================================================
class Normalize_FF : public RenderState
{
public:
Normalize_FF(bool enableNormalization = true);
void enable(bool enableNormalization);
bool isEnabled() const;
virtual void applyOpenGL(OpenGLContext* oglContext) const;
private:
bool m_enable;
};
//==================================================================================================
//
//
//
//==================================================================================================
class TextureMapping_FF : public RenderState
{
public:
enum TextureFunction
{
MODULATE,
DECAL
};
public:
TextureMapping_FF(Texture2D_FF* texture = NULL);
~TextureMapping_FF();
void setTexture(Texture2D_FF* texture);
Texture2D_FF* texture();
void setTextureFunction(TextureFunction texFunc);
TextureFunction textureFunction() const;
void setEnvironmentMapping(bool environmentMapping);
bool environmentMapping() const;
void setupTexture(OpenGLContext* oglContext);
virtual void applyOpenGL(OpenGLContext* oglContext) const;
virtual bool isFixedFunction() const;
private:
ref<Texture2D_FF> m_texture;
TextureFunction m_textureFunction;
bool m_environmentMapping;
};
} // namespace cvf
@@ -0,0 +1,161 @@
//##################################################################################################
//
// 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 "cvfRenderbufferObject.h"
#include "cvfOpenGL.h"
#include "cvfOglRc.h"
#include "cvfOpenGLResourceManager.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderbufferObject
/// \ingroup Render
///
/// Encapsulates an OpenGL renderbuffer object
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderbufferObject::RenderbufferObject(InternalFormat format, uint width, uint height)
: Object(),
m_interalFormat(format),
m_width(width),
m_height(height),
m_versionTick(1)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderbufferObject::~RenderbufferObject()
{
// Just release our reference
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcBuffer.p()));
m_oglRcBuffer = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OglId RenderbufferObject::renderbufferOglId() const
{
return OglRc::safeOglId(m_oglRcBuffer.p());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint RenderbufferObject::versionTick() const
{
return m_versionTick;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderbufferObject::setSize(uint width, uint height)
{
// Forget existing buffer
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcBuffer.p()));
m_oglRcBuffer = NULL;
m_width = width;
m_height = height;
m_versionTick++;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderbufferObject::create(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_CLEAR_OGL_ERROR(oglContext);
m_oglRcBuffer = oglContext->resourceManager()->createOglRcRenderbuffer(oglContext);
OglId myOglId = OglRc::safeOglId(m_oglRcBuffer.p());
glBindRenderbuffer(GL_RENDERBUFFER, myOglId);
glRenderbufferStorage(GL_RENDERBUFFER, intenalFormatOpenGL(), static_cast<GLsizei>(m_width), static_cast<GLsizei>(m_height));
if (CVF_TEST_AND_REPORT_OPENGL_ERROR(oglContext, "Allocate render buffer storage"))
{
deleteRenderbuffer(oglContext);
return false;
}
m_versionTick++;
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderbufferObject::deleteRenderbuffer(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
if (m_oglRcBuffer.notNull())
{
m_oglRcBuffer->deleteResource(oglContext);
CVF_CHECK_OGL(oglContext);
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcBuffer.p()));
m_oglRcBuffer = NULL;
}
m_versionTick++;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvfGLenum RenderbufferObject::intenalFormatOpenGL() const
{
switch(m_interalFormat)
{
case RGBA: return GL_RGBA;
case DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT16;
#ifndef CVF_OPENGL_ES
case DEPTH_COMPONENT24: return GL_DEPTH_COMPONENT24;
case DEPTH_COMPONENT32: return GL_DEPTH_COMPONENT32;
case DEPTH24_STENCIL8: return GL_DEPTH24_STENCIL8;
#endif
}
CVF_FAIL_MSG("Illegal renderbuffer format");
return GL_RGBA;
}
} // namespace cvf
@@ -0,0 +1,71 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfOpenGLTypes.h"
namespace cvf {
class OpenGLContext;
class OglRcRenderbuffer;
//==================================================================================================
//
// Wrapper for OpenGL Renderbuffer Object
//
//==================================================================================================
class RenderbufferObject : public Object
{
public:
enum InternalFormat
{
RGBA,
DEPTH_COMPONENT16,
DEPTH_COMPONENT24,
DEPTH_COMPONENT32,
DEPTH24_STENCIL8
};
public:
RenderbufferObject(InternalFormat format, uint width, uint height);
~RenderbufferObject();
void setSize(uint width, uint height);
bool create(OpenGLContext* oglContext);
void deleteRenderbuffer(OpenGLContext* oglContext);
OglId renderbufferOglId() const;
uint versionTick() const;
private:
cvfGLenum intenalFormatOpenGL() const;
private:
InternalFormat m_interalFormat;
uint m_width;
uint m_height;
uint m_versionTick; // Versioning to be able to detect changes
ref<OglRcRenderbuffer> m_oglRcBuffer; //
};
}
@@ -0,0 +1,134 @@
//##################################################################################################
//
// 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 "cvfSampler.h"
#include "cvfOpenGL.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Sampler
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Sampler::Sampler()
: m_wrapModeS(REPEAT),
m_wrapModeT(REPEAT),
m_minFilter(NEAREST_MIPMAP_LINEAR),
m_magFilter(LINEAR)
{
// // Old defaults
// m_wrapModeS(CLAMP_TO_EDGE),
// m_wrapModeT(CLAMP_TO_EDGE),
// m_minFilter(NEAREST),
// m_magFilter(NEAREST)
}
//--------------------------------------------------------------------------------------------------
/// Sets wrap mode for both S and T
//--------------------------------------------------------------------------------------------------
void Sampler::setWrapMode(WrapMode wrapMode)
{
setWrapModeS(wrapMode);
setWrapModeT(wrapMode);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Sampler::setWrapModeS(WrapMode wrapMode)
{
m_wrapModeS = wrapMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Sampler::setWrapModeT(WrapMode wrapMode)
{
m_wrapModeT = wrapMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Sampler::setMinFilter(Filter minFilter)
{
m_minFilter = minFilter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Sampler::setMagFilter(Filter magFilter)
{
CVF_ASSERT(magFilter == NEAREST || magFilter == LINEAR);
m_magFilter = magFilter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Sampler::WrapMode Sampler::wrapModeS() const
{
return m_wrapModeS;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Sampler::WrapMode Sampler::wrapModeT() const
{
return m_wrapModeT;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Sampler::Filter Sampler::minFilter() const
{
return m_minFilter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Sampler::Filter Sampler::magFilter() const
{
return m_magFilter;
}
} // namespace cvf
@@ -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 "cvfObject.h"
namespace cvf {
//==================================================================================================
//
// OpenGL 3.3/4.1 settings:
//
// Currently handled:
// TEXTURE_WRAP_S
// TEXTURE_WRAP_T
// TEXTURE_MIN_FILTER
// TEXTURE_MAG_FILTER
//
// TBI:
// TEXTURE_WRAP_R, TEXTURE_BORDER_COLOR, TEXTURE_MIN_LOD, TEXTURE_MAX_LOD, TEXTURE_LOD_BIAS,
// TEXTURE_COMPARE_MODE, TEXTURE_COMPARE_FUNC
//
//==================================================================================================
class Sampler : public Object
{
public:
enum WrapMode
{
REPEAT, // OpenGL default
CLAMP_TO_EDGE,
CLAMP_TO_BORDER,
MIRRORED_REPEAT
};
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
};
public:
Sampler();
void setWrapMode(WrapMode wrapMode);
void setWrapModeS(WrapMode wrapMode);
void setWrapModeT(WrapMode wrapMode);
void setMinFilter(Filter minFilter);
void setMagFilter(Filter magFilter);
WrapMode wrapModeS() const;
WrapMode wrapModeT() const;
Filter minFilter() const;
Filter magFilter() const;
private:
WrapMode m_wrapModeS;
WrapMode m_wrapModeT;
Filter m_minFilter;
Filter m_magFilter;
};
} // namespace cvf
@@ -0,0 +1,393 @@
//##################################################################################################
//
// 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 "cvfScalarMapper.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::ScalarMapper
/// \ingroup Render
///
/// Abstract base class for mapping scalar values to texture coordinates/colors
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<Color3ubArray> ScalarMapper::colorTableArray(ColorTable colorTable)
{
ref<Color3ubArray> colors = new Color3ubArray;
switch (colorTable)
{
case BLACK_WHITE:
{
colors->reserve(2);
colors->add(Color3ub( 0, 0, 0));
colors->add(Color3ub(255, 255, 255));
break;
}
case BLUE_RED:
{
colors->reserve(2);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub(255, 0, 0));
break;
}
case BLUE_GREEN:
{
colors->reserve(2);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 255, 0));
break;
}
case YELLOW_RED:
{
colors->reserve(2);
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case GREEN_YELLOW_RED:
{
colors->reserve(3);
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case RED_YELLOW:
{
colors->reserve(2);
colors->add(Color3ub(255, 0, 0));
colors->add(Color3ub(255, 255, 0));
break;
}
case THERMAL_1:
{
colors->reserve(11);
colors->add(Color3ub( 0, 0, 0));
colors->add(Color3ub( 16, 80, 79));
colors->add(Color3ub( 27, 159, 155));
colors->add(Color3ub( 96, 213, 87));
colors->add(Color3ub(170, 234, 37));
colors->add(Color3ub(240, 215, 16));
colors->add(Color3ub(255, 167, 0));
colors->add(Color3ub(255, 64, 17));
colors->add(Color3ub(252, 137, 125));
colors->add(Color3ub(255, 200, 200));
colors->add(Color3ub(255, 255, 255));
break;
}
case THERMAL_2:
{
colors->reserve(12);
colors->add(Color3ub( 0, 0, 0));
colors->add(Color3ub( 18, 0, 130));
colors->add(Color3ub( 95, 0, 142));
colors->add(Color3ub(159, 0, 146));
colors->add(Color3ub(193, 6, 135));
colors->add(Color3ub(225, 48, 65));
colors->add(Color3ub(240, 86, 0));
colors->add(Color3ub(240, 126, 0));
colors->add(Color3ub(255, 166, 0));
colors->add(Color3ub(255, 205, 0));
colors->add(Color3ub(255, 237, 94));
colors->add(Color3ub(255, 255, 255));
break;
}
case THERMAL_3:
{
colors->reserve(4);
colors->add(Color3ub( 0, 0, 0));
colors->add(Color3ub(218, 20, 5));
colors->add(Color3ub(210, 210, 30));
colors->add(Color3ub(218, 218, 218));
break;
}
case METAL_CASTING:
{
colors->reserve(5);
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub(255, 0, 0));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 255, 255));
break;
}
case NORMAL:
{
// Choses the primary colors only variant
colors = normalColorTableArray(5);
break;
}
}
CVF_ASSERT(colors->size() > 0);
return colors;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<Color3ubArray> ScalarMapper::normalColorTableArray(uint colorCount)
{
CVF_ASSERT(colorCount > 0 && colorCount <= 13);
ref<Color3ubArray> colors = new Color3ubArray;
switch (colorCount)
{
case 1:
{
colors->reserve(1);
colors->add(Color3ub( 0, 0, 255));
break;
}
case 2:
{
colors->reserve(2);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub(255, 0, 255));
break;
}
case 3:
{
colors->reserve(3);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case 4:
{
colors->reserve(4);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case 5:
{
colors->reserve(5);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case 6:
{
colors->reserve(6);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 185, 255));
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 186, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case 7:
{
colors->reserve(7);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 185, 255));
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 186, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case 8:
{
colors->reserve(8);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 120, 255));
colors->add(Color3ub( 0, 200, 255));
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 185, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case 9:
{
colors->reserve(9);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 120, 255));
colors->add(Color3ub( 0, 200, 255));
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 200, 0));
colors->add(Color3ub(255, 120, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case 10:
{
colors->reserve(10);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 100, 255));
colors->add(Color3ub( 0, 160, 255));
colors->add(Color3ub( 0, 210, 255));
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 200, 0));
colors->add(Color3ub(255, 120, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case 11:
{
colors->reserve(11);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 100, 255));
colors->add(Color3ub( 0, 160, 255));
colors->add(Color3ub( 0, 210, 255));
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 210, 0));
colors->add(Color3ub(255, 160, 0));
colors->add(Color3ub(255, 100, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case 12:
{
colors->reserve(12);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 90, 255));
colors->add(Color3ub( 0, 140, 255));
colors->add(Color3ub( 0, 180, 255));
colors->add(Color3ub( 0, 220, 255));
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 210, 0));
colors->add(Color3ub(255, 160, 0));
colors->add(Color3ub(255, 100, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
case 13:
{
colors->reserve(13);
colors->add(Color3ub( 0, 0, 255));
colors->add(Color3ub( 0, 90, 255));
colors->add(Color3ub( 0, 140, 255));
colors->add(Color3ub( 0, 180, 255));
colors->add(Color3ub( 0, 220, 255));
colors->add(Color3ub( 0, 255, 255));
colors->add(Color3ub( 0, 255, 0));
colors->add(Color3ub(255, 255, 0));
colors->add(Color3ub(255, 220, 0));
colors->add(Color3ub(255, 180, 0));
colors->add(Color3ub(255, 140, 0));
colors->add(Color3ub(255, 90, 0));
colors->add(Color3ub(255, 0, 0));
break;
}
default:
{
CVF_FAIL_MSG("Invalid input color count");
break;
}
}
CVF_ASSERT(colors->size() >= 1);
return colors;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<Color3ubArray> ScalarMapper::interpolateColorArray(const Color3ubArray& colorArray, uint targetColorCount)
{
uint inputColorCount = static_cast<uint>(colorArray.size());
CVF_ASSERT(inputColorCount > 1);
CVF_ASSERT(targetColorCount > 1);
ref<Color3ubArray> colors = new Color3ubArray;
colors->reserve(targetColorCount);
const uint inputLevelCount = inputColorCount - 1;
const uint outputLevelCount = targetColorCount - 1;
uint outputLevelIdx;
for (outputLevelIdx = 0; outputLevelIdx < outputLevelCount; outputLevelIdx++)
{
double dblInputLevelIndex = inputLevelCount * (outputLevelIdx / static_cast<double>(outputLevelCount));
const uint inputLevelIndex = static_cast<uint>(dblInputLevelIndex);
CVF_ASSERT(inputLevelIndex < inputLevelCount);
double t = dblInputLevelIndex - inputLevelIndex;
CVF_ASSERT(t >= 0 && t <= 1.0);
Color3ub c1 = colorArray[inputLevelIndex];
Color3ub c2 = colorArray[inputLevelIndex + 1];
int r = static_cast<int>(c1.r() + t*(c2.r() - c1.r()) + 0.5);
int g = static_cast<int>(c1.g() + t*(c2.g() - c1.g()) + 0.5);
int b = static_cast<int>(c1.b() + t*(c2.b() - c1.b()) + 0.5);
r = Math::clamp(r, 0, 255);
g = Math::clamp(g, 0, 255);
b = Math::clamp(b, 0, 255);
Color3ub col((ubyte)r, (ubyte)g, (ubyte)b);
colors->add(col);
}
colors->add(colorArray[colorArray.size() - 1]);
return colors;
}
} // namespace cvf
@@ -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 "cvfObject.h"
#include "cvfArray.h"
namespace cvf {
class TextureImage;
//==================================================================================================
//
// Abstract base class for mapping scalar values to texture coordinates/colors
//
//==================================================================================================
class ScalarMapper : public Object
{
public:
enum ColorTable
{
NORMAL,
BLACK_WHITE,
BLUE_RED,
BLUE_GREEN,
YELLOW_RED,
GREEN_YELLOW_RED,
RED_YELLOW,
THERMAL_1,
THERMAL_2,
THERMAL_3,
METAL_CASTING
};
public:
virtual Vec2f mapToTextureCoord(double scalarValue) const = 0;
virtual Color3ub mapToColor(double scalarValue) const = 0;
virtual bool updateTexture(TextureImage* image) const = 0;
protected:
static ref<Color3ubArray> colorTableArray(ColorTable colorTable);
static ref<Color3ubArray> normalColorTableArray(uint colorCount);
static ref<Color3ubArray> interpolateColorArray(const Color3ubArray& colorArray, uint targetColorCount);
};
}
@@ -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.
//
//##################################################################################################
#include "cvfScalarMapperContinuousLinear.h"
#include "cvfMath.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::ScalarMapperContinuousLinear
/// \ingroup Render
///
/// Maps scalar values to texture coordinates/colors using continuous linear mapping
/// Configured by specifying a number of level colors and a min/max range.
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperContinuousLinear::normalizedLevelPosition(double domainValue) const
{
double range = m_rangeMax - m_rangeMin;
if (range != 0) return cvf::Math::clamp((domainValue - m_rangeMin)/range, 0.0, 1.0);
else return 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperContinuousLinear::domainValue(double normalizedPosition) const
{
double range = m_rangeMax - m_rangeMin;
return (normalizedPosition * range + m_rangeMin);
}
} // namespace cvf
@@ -0,0 +1,43 @@
//##################################################################################################
//
// 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 "cvfScalarMapperContinuousLog.h"
namespace cvf
{
//==================================================================================================
//
// Maps scalar values to texture coordinates/colors
//
//==================================================================================================
class ScalarMapperContinuousLinear : public ScalarMapperContinuousLog
{
public:
ScalarMapperContinuousLinear() {m_decadeLevelCount = 2; }
protected:
virtual double normalizedLevelPosition( double domainValue ) const;
virtual double domainValue( double normalizedPosition ) const;
};
}
@@ -0,0 +1,246 @@
//##################################################################################################
//
// 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 "cvfScalarMapperContinuousLog.h"
#include "cvfMath.h"
#include "cvfTextureImage.h"
#include <cmath>
namespace cvf {
//==================================================================================================
///
/// \class cvf::ScalarMapperContinuousLog
/// \ingroup Render
///
/// Maps scalar values to texture coordinates/colors using continuous logarithmic mapping
/// 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 logRangeMax = log10(m_rangeMax);
double logRangeMin = log10(m_rangeMin);
double logRange = logRangeMax - logRangeMin;
double logValue;
if (scalarValue <= 0) logValue = logRangeMin;
else logValue = log10(scalarValue);
if (logRange != 0)
{
return cvf::Math::clamp((logValue - logRangeMin)/logRange, 0.0, 1.0);
}
else
{
return 0;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperContinuousLog::domainValue(double normalizedPosition) const
{
double logRangeMax = log10(m_rangeMax);
double logRangeMin = log10(m_rangeMin);
double logRange = logRangeMax - logRangeMin;
double logValue = normalizedPosition*logRange + logRangeMin;
return pow(10, logValue);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperContinuousLog::setMajorLevelCount(size_t levelCount, bool adjustLevels)
{
m_majorLevelCount = levelCount;
m_adjustLevels = adjustLevels;
}
} // namespace cvf
@@ -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 "cvfBase.h"
#include "cvfObject.h"
#include "cvfLegendScalarMapper.h"
namespace cvf {
//==================================================================================================
//
// Maps scalar values to texture coordinates/colors
//
//==================================================================================================
class ScalarMapperContinuousLog : public LegendScalarMapper
{
public:
ScalarMapperContinuousLog();
void setRange(double min, double max);
void setMajorLevelCount(size_t levelCount, bool adjustLevels = true);
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 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.
};
}
@@ -0,0 +1,300 @@
//##################################################################################################
//
// 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 "cvfScalarMapperDiscreteLinear.h"
#include "cvfMath.h"
#include "cvfTextureImage.h"
#include <cmath>
namespace cvf {
//==================================================================================================
///
/// \class cvf::ScalarMapperDiscreteLinear
/// \ingroup Render
///
/// Maps scalar values to texture coordinates/colors using discrete linear mapping
//==================================================================================================
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);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperDiscreteLinear::discretize(double scalarValue) const
{
std::set<double>::iterator it;
it = m_sortedLevels.upper_bound(scalarValue);
if (it == m_sortedLevels.begin()) return (*it);
if (it == m_sortedLevels.end()) return (*m_sortedLevels.rbegin());
double upperValue = *it;
it--;
double lowerValue = *it;
return 0.5 * (upperValue + lowerValue);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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 range = m_rangeMax - m_rangeMin;
if (range != 0) return cvf::Math::clamp((domainScalarValue - m_rangeMin)/range, 0.0, 1.0);
else return 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperDiscreteLinear::domainValue(double normalizedPosition) const
{
double range = m_rangeMax - m_rangeMin;
return (normalizedPosition * range + m_rangeMin);
}
//--------------------------------------------------------------------------------------------------
/// 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
@@ -0,0 +1,75 @@
//##################################################################################################
//
// 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 "cvfLegendScalarMapper.h"
namespace cvf {
//==================================================================================================
//
// Maps scalar values to texture coordinates/colors
//
//==================================================================================================
class ScalarMapperDiscreteLinear : public LegendScalarMapper
{
public:
ScalarMapperDiscreteLinear();
void setRange(double min, double max);
void setLevelsFromColorCount(size_t colorCount, bool adjustLevels = true);
void setLevelsFromValues(const std::set<double>& levelValues);
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 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.
};
}
@@ -0,0 +1,72 @@
//##################################################################################################
//
// 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 "cvfScalarMapperDiscreteLog.h"
#include <cmath>
#include "cvfMath.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::ScalarMapperDiscreteLog
/// \ingroup Render
///
/// Maps scalar values to texture coordinates/colors using discrete logarithmic mapping
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperDiscreteLog::normalizedLevelPosition(double domainScalarValue) const
{
double logRangeMax = log10(m_rangeMax);
double logRangeMin = log10(m_rangeMin);
double logRange = logRangeMax - logRangeMin;
double logValue;
if (domainScalarValue <= 0) logValue = logRangeMin;
else logValue = log10(domainScalarValue);
if (logRange != 0)
{
return cvf::Math::clamp((logValue - logRangeMin)/logRange, 0.0, 1.0);
}
else
{
return 0;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperDiscreteLog::domainValue(double normalizedPosition) const
{
double logRangeMax = log10(m_rangeMax);
double logRangeMin = log10(m_rangeMin);
double logRange = logRangeMax - logRangeMin;
double logValue = normalizedPosition*logRange + logRangeMin;
return pow(10, logValue);
}
} // namespace cvf
@@ -0,0 +1,40 @@
//##################################################################################################
//
// 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 "cvfScalarMapperDiscreteLinear.h"
namespace cvf {
//==================================================================================================
//
// Maps scalar values to texture coordinates/colors
//
//==================================================================================================
class ScalarMapperDiscreteLog : public ScalarMapperDiscreteLinear
{
public:
ScalarMapperDiscreteLog() {m_decadeLevelCount = 2; }
protected:
virtual double normalizedLevelPosition( double domainValue ) const;
virtual double domainValue( double normalizedPosition ) const;
};
}
@@ -0,0 +1,373 @@
//##################################################################################################
//
// 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 "cvfMath.h"
#include "cvfScalarMapperUniformLevels.h"
#include "cvfOverlayColorLegend.h"
#include "cvfTextureImage.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::ScalarMapperUniformLevels
/// \ingroup Render
///
/// Maps scalar values to texture coordinates/colors using levels of uniform size.
/// Configured by specifying a number of level colors and a min/max range.
//==================================================================================================
ScalarMapperUniformLevels::ScalarMapperUniformLevels()
: m_rangeMin(0),
m_rangeMax(0),
m_textureSize(64),
m_maxTexCoord(1.0)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperUniformLevels::setRange(double min, double max)
{
m_rangeMin = min;
m_rangeMax = max;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperUniformLevels::rangeMin() const
{
return m_rangeMin;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ScalarMapperUniformLevels::rangeMax() const
{
return m_rangeMax;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperUniformLevels::setColors(const Color3ubArray& colorArray)
{
CVF_ASSERT(colorArray.size() > 0);
m_colors = colorArray;
recomputeMaxTexCoord();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperUniformLevels::setColors(ColorTable colorTable, uint levelCount)
{
// The normal color table has 13 hand coded levels, so handle these level counts separately
if (colorTable == NORMAL && levelCount <= 13)
{
m_colors = *normalColorTableArray(levelCount);
}
else
{
ref<Color3ubArray> baseColors = colorTableArray(colorTable);
if (baseColors->size() == levelCount)
{
m_colors = *baseColors;
}
else
{
m_colors = *interpolateColorArray(*baseColors, levelCount);
}
}
CVF_ASSERT(m_colors.size() == levelCount);
recomputeMaxTexCoord();
}
//--------------------------------------------------------------------------------------------------
/// Set the size of the texture produces by updateTexture()
///
/// For compatibility with OpenGL versions older than 2.0, the specified size should be a power of 2
/// Note that changing this size affects the texture coordinate generation.
///
/// \warning The texture size must be at least the the same as the number of colors specified.
/// If this is not the case, updateTexture() will fail.
//--------------------------------------------------------------------------------------------------
void ScalarMapperUniformLevels::setTextureSize(uint textureSize)
{
CVF_ASSERT(m_textureSize > 0);
m_textureSize = textureSize;
recomputeMaxTexCoord();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint ScalarMapperUniformLevels::textureSize() const
{
return m_textureSize;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ScalarMapperUniformLevels::recomputeMaxTexCoord()
{
const uint numColors = static_cast<uint>(m_colors.size());
if (numColors == 0)
{
m_maxTexCoord = 1.0;
return;
}
const uint numPixelsPerColor = m_textureSize/numColors;
if (numPixelsPerColor == 0)
{
m_maxTexCoord = 1.0;
return;
}
uint texturePixelsInUse = numColors*numPixelsPerColor;
CVF_ASSERT(texturePixelsInUse <= m_textureSize);
m_maxTexCoord = static_cast<double>(texturePixelsInUse)/static_cast<double>(m_textureSize);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Vec2f ScalarMapperUniformLevels::mapToTextureCoord(double scalarValue) const
{
const double range = m_rangeMax - m_rangeMin;
if (range >= 0)
{
if (scalarValue > m_rangeMin && scalarValue < m_rangeMax)
{
// Truly inside the range, implies a range > 0
CVF_ASSERT(range > 0);
double s = static_cast<float>(((scalarValue - m_rangeMin)/range)*m_maxTexCoord);
// Clamp to the currently legal texture coord range
// Might need to add code to correct for float precision, but that is probably not the main enemy.
// Our real problem is the fact that in most cases the texture coords get treated with even less precision
// on the graphics hardware. What we would really like is to guess at the HW precision and then correct for that.
// Currently the workaround is done in updateTexture() which pads the upper end of the texture when we're not filling
// all the texture pixels.
s = Math::clamp(s, 0.0, m_maxTexCoord);
return Vec2f(static_cast<float>(s), 0.5f);
}
else if (scalarValue <= m_rangeMin)
{
return Vec2f(0.0f, 0.5f);
}
else if (scalarValue >= m_rangeMax)
{
return Vec2f(static_cast<float>(m_maxTexCoord), 0.5f);
}
else
{
// If we get here we have som NaN, Use lowest legal texture coord
return Vec2f(0.0f, 0.0f);
}
}
else
{
// Range is invalid (min > max)
return Vec2f(0.0f, 0.5f);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3ub ScalarMapperUniformLevels::mapToColor(double scalarValue) const
{
uint colorCount = static_cast<uint>(m_colors.size());
CVF_ASSERT(colorCount > 0);
if (colorCount < 1)
{
return Color3::BLACK;
}
const double range = m_rangeMax - m_rangeMin;
if (range >= 0)
{
if (scalarValue > m_rangeMin && scalarValue < m_rangeMax)
{
// Truly inside the range, implies a range > 0
CVF_ASSERT(range > 0);
const double levelRange = range/colorCount;
const double dblIndex = (scalarValue - m_rangeMin)/levelRange;
uint index = 0;
if (dblIndex > 0 && dblIndex < colorCount)
{
index = static_cast<uint>(dblIndex);
}
else if (dblIndex >= colorCount)
{
index = colorCount - 1;
}
CVF_ASSERT(index < colorCount);
return m_colors[index];
}
else if (scalarValue <= m_rangeMin)
{
return m_colors[0];
}
else if (scalarValue >= m_rangeMax)
{
return m_colors[colorCount - 1];
}
else
{
// If we get here we have some NaN
return Color3::BLACK;
}
}
else
{
// Range is invalid
return m_colors[0];
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ScalarMapperUniformLevels::updateTexture(TextureImage* image) const
{
CVF_ASSERT(image);
const uint numColors = static_cast<uint>(m_colors.size());
if (numColors < 1)
{
return false;
}
CVF_ASSERT(m_textureSize >= numColors);
if (m_textureSize < numColors)
{
return false;
}
image->allocate(m_textureSize, 1);
// For now fill with white so we can see any errors more easily
image->fill(Color4ub(Color3::WHITE));
const uint numPixelsPerColor = m_textureSize/numColors;
CVF_ASSERT(numPixelsPerColor >= 1);
uint ic;
for (ic = 0; ic < numColors; ic++)
{
const Color4ub clr(m_colors[ic], 255);
uint ip;
for (ip = 0; ip < numPixelsPerColor; ip++)
{
image->setPixel(ic*numPixelsPerColor + ip, 0, clr);
}
}
// In cases where we're not using the entire texture we might get into problems with texture coordinate precision on the graphics hardware.
// Therefore we set one extra pixel with the 'highest' color in the color table
if (numColors*numPixelsPerColor < m_textureSize)
{
const Color4ub topClr(m_colors[numColors - 1], 255);
image->setPixel(numColors*numPixelsPerColor, 0, topClr);
}
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
@@ -0,0 +1,77 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfLegendScalarMapper.h"
namespace cvf {
class OverlayColorLegend;
//==================================================================================================
//
// Maps scalar values to texture coordinates/colors
//
//==================================================================================================
class ScalarMapperUniformLevels : public LegendScalarMapper
{
public:
ScalarMapperUniformLevels();
void setRange(double min, double max);
double rangeMin() const;
double rangeMax() const;
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;
private:
void recomputeMaxTexCoord();
private:
double m_rangeMin;
double m_rangeMax;
Color3ubArray m_colors;
uint m_textureSize; // The size of texture that updateTexture() is will produce.
double m_maxTexCoord; // The largest allowable s texture coordinate, scalar values >= m_rangeMax will get mapped to this coordinate
};
}
@@ -0,0 +1,266 @@
//##################################################################################################
//
// 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 "cvfShaderProgram.h"
#include "cvfLogger.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfOglRc.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Shader
/// \ingroup Render
///
/// Encapsulates a GLSL shader.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Shader::Shader(ShaderType shaderType, const String& shaderName)
: m_shaderType(shaderType),
m_shaderName(shaderName),
m_lastCompileSucceeded(false),
m_compiledVersionTick(-1)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Shader::Shader(ShaderType shaderType, const String& shaderName, const String& source)
: m_shaderType(shaderType),
m_shaderName(shaderName),
m_source(source),
m_lastCompileSucceeded(false),
m_compiledVersionTick(-1)
{
}
//--------------------------------------------------------------------------------------------------
/// OpenGL resources must already be deleted. \sa deleteShader()
//--------------------------------------------------------------------------------------------------
Shader::~Shader()
{
// Just release our reference
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcShader.p()));
m_oglRcShader = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Shader::ShaderType Shader::shaderType() const
{
return m_shaderType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String Shader::shaderName() const
{
return m_shaderName;
}
//--------------------------------------------------------------------------------------------------
/// Compiles the shader if needed
///
/// \return Returns true if the shader is/was compiled. Otherwise false.
//--------------------------------------------------------------------------------------------------
bool Shader::compile(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_ASSERT(ShaderProgram::supportedOpenGL(oglContext));
if (OglRc::safeOglId(m_oglRcShader.p()) != 0 && m_lastCompileSucceeded)
{
#ifdef _DEBUG
uint myOglId = OglRc::safeOglId(m_oglRcShader.p());
GLint status;
glGetShaderiv(myOglId, GL_COMPILE_STATUS, &status);
CVF_ASSERT(status == GL_TRUE);
#endif
return true;
}
// Start by flagging compile as failure
m_lastCompileSucceeded = false;
if (OglRc::safeOglId(m_oglRcShader.p()) == 0)
{
cvfGLenum glShaderType = GL_VERTEX_SHADER;
switch (m_shaderType)
{
case VERTEX_SHADER: glShaderType = GL_VERTEX_SHADER; break;
case FRAGMENT_SHADER: glShaderType = GL_FRAGMENT_SHADER; break;
#ifndef CVF_OPENGL_ES
case GEOMETRY_SHADER: glShaderType = GL_GEOMETRY_SHADER; break;
#endif
default: CVF_FAIL_MSG("Unhandled shader type"); break;
}
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcShader.p()));
m_oglRcShader = oglContext->resourceManager()->createOglRcShader(oglContext, glShaderType);
if (m_oglRcShader.isNull())
{
return false;
}
}
uint myOglId = m_oglRcShader->oglId();
CVF_ASSERT(myOglId != 0);
if (m_source.isEmpty())
{
String errStr = String("Error compiling shader: '%1'\n").arg(m_shaderName);
errStr += "Shader source is empty";
CVF_LOG_RENDER_ERROR(oglContext, errStr);
return false;
}
CharArray charArr = m_source.toAscii();
const char* stringArray[1];
stringArray[0] = charArr.ptr();
glShaderSource(myOglId, 1, stringArray, NULL);
CVF_CHECK_OGL(oglContext);
glCompileShader(myOglId);
GLint iCompileStatus = 0;
glGetShaderiv(myOglId, GL_COMPILE_STATUS, &iCompileStatus);
if (iCompileStatus != GL_TRUE)
{
String errStr = String("Error compiling shader: '%1'\n").arg(m_shaderName);
errStr += "GLSL details:\n";
errStr += shaderInfoLog(oglContext);
CVF_LOG_RENDER_ERROR(oglContext, errStr);
return false;
}
m_compiledVersionTick++;
m_lastCompileSucceeded = true;
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int Shader::compiledVersionTick() const
{
if (m_lastCompileSucceeded && OglRc::safeOglId(m_oglRcShader.p()) != 0)
{
return m_compiledVersionTick;
}
else
{
return -1;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvfGLuint Shader::shaderOglId() const
{
return OglRc::safeOglId(m_oglRcShader.p());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Shader::deleteShader(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
if (m_oglRcShader.notNull())
{
m_oglRcShader->deleteResource(oglContext);
CVF_CHECK_OGL(oglContext);
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcShader.p()));
m_oglRcShader = NULL;
m_lastCompileSucceeded = false;
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the information log for this shader
///
/// See: http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderInfoLog.xml
//--------------------------------------------------------------------------------------------------
String Shader::shaderInfoLog(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
uint myOglId = OglRc::safeOglId(m_oglRcShader.p());
if (myOglId == 0)
{
return "Shader object not created.";
}
if (!glIsShader(myOglId))
{
return "Shader object identifier does not correspond to a shader object.";
}
GLint reqBufferSize = 0;
glGetShaderiv(myOglId, GL_INFO_LOG_LENGTH, &reqBufferSize);
if (reqBufferSize > 0)
{
// TODO
// This is a good place for using CharArray
std::vector<GLchar> charBuffer;
charBuffer.resize(static_cast<size_t>(reqBufferSize + 1));
glGetShaderInfoLog(myOglId, reqBufferSize, NULL, &charBuffer[0]);
String logString(&charBuffer[0]);
return logString;
}
else
{
return "";
}
}
} // namespace cvf
@@ -0,0 +1,72 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfString.h"
#include "cvfOpenGLTypes.h"
namespace cvf {
class OpenGLContext;
class OglRcShader;
//==================================================================================================
//
// Encapsulates a GLSL shader (vertex, fragment or geometry shader)
//
//==================================================================================================
class Shader : public Object
{
public:
enum ShaderType
{
VERTEX_SHADER,
FRAGMENT_SHADER,
GEOMETRY_SHADER
};
public:
Shader(ShaderType shaderType, const String& shaderName);
Shader(ShaderType shaderType, const String& shaderName, const String& source);
~Shader();
ShaderType shaderType() const;
String shaderName() const;
bool compile(OpenGLContext* oglContext);
int compiledVersionTick() const;
OglId shaderOglId() const;
void deleteShader(OpenGLContext* oglContext);
String shaderInfoLog(OpenGLContext* oglContext) const;
private:
const ShaderType m_shaderType; // Type is vertex, fragment or geometry shader
String m_shaderName; // Name of this shader. Primarily used when reporting errors
String m_source;
bool m_lastCompileSucceeded; // Flag to indicate if the last attempt at compiling this shader succeeded. May be true even after shader is deleted wrt OpenGL
int m_compiledVersionTick; // Versioning of this shader
ref<OglRcShader> m_oglRcShader; //
};
}
@@ -0,0 +1,849 @@
//##################################################################################################
//
// 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 "cvfShaderProgram.h"
#include "cvfOpenGL.h"
#include "cvfUniform.h"
#include "cvfUniformSet.h"
#include "cvfMatrixState.h"
#include "cvfTrace.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfOglRc.h"
#include "cvfOpenGLCapabilities.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::ShaderProgram
/// \ingroup Render
///
/// Encapsulates a GLSL shader program.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ShaderProgram::ShaderProgram(const String& programName)
: m_programName(programName),
m_needsLinking(true)
{
}
//--------------------------------------------------------------------------------------------------
/// Get name of this shader program
///
/// If no name has been set, one will be constructed by concatenating the name of the attached shaders.
//--------------------------------------------------------------------------------------------------
String ShaderProgram::programName() const
{
if (m_programName.isEmpty())
{
String progName;
uint numShaders = shaderCount();
uint i;
for (i = 0; i < numShaders; i++)
{
const Shader* shader = m_shaders.at(i);
if (i > 0) progName += " # ";
progName += shader->shaderName();
}
return progName;
}
else
{
return m_programName;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgram::setProgramName(const String& programName)
{
m_programName = programName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ShaderProgram::~ShaderProgram()
{
// Just release our reference
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcProgram.p()));
m_oglRcProgram = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgram::addShader(Shader* shader)
{
CVF_ASSERT(shader);
m_shaders.push_back(shader);
m_linkedShaderVersionTicks.push_back(-1);
m_needsLinking = true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint ShaderProgram::shaderCount() const
{
return static_cast<uint>(m_shaders.size());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Shader* ShaderProgram::shader(uint index)
{
CVF_ASSERT(index < shaderCount());
return m_shaders.at(index);
}
//--------------------------------------------------------------------------------------------------
/// Links the program if needed
///
/// Will create the shader program if needed. Will compile the program's shaders if needed.
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::linkProgram(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_ASSERT(ShaderProgram::supportedOpenGL(oglContext));
if (OglRc::safeOglId(m_oglRcProgram.p()) != 0)
{
if (!needsLinking())
{
return true;
}
}
// Do a delete/create cycle to avoid keeping tabs of which shaders
// that need to be detached. Assumption is that relinking happens seldom
deleteProgram(oglContext);
if (!createProgram(oglContext))
{
CVF_LOG_RENDER_ERROR(oglContext, String("Unable to create program '%1'").arg(programName()));
return false;
}
// For now, always call compile on all the shaders
// The compile should be a no-op if everything is in sync
uint numShaders = shaderCount();
CVF_ASSERT(numShaders == static_cast<uint>(m_linkedShaderVersionTicks.size()));
uint i;
for (i = 0; i < numShaders; i++)
{
Shader* shader = m_shaders.at(i);
if (!shader->compile(oglContext))
{
CVF_LOG_RENDER_ERROR(oglContext, String("Error compiling shader '%1' attached to program '%2'").arg(shader->shaderName()).arg(programName()));
return false;
}
CVF_ASSERT(shader->shaderOglId() != 0);
glAttachShader(m_oglRcProgram->oglId(), shader->shaderOglId());
CVF_CHECK_OGL(oglContext);
m_linkedShaderVersionTicks[i] = shader->compiledVersionTick();
}
bindFixedAttributes(oglContext);
glLinkProgram(m_oglRcProgram->oglId());
//Trace::show("%d", glGetAttribLocation(m_programObjID, "cvfa_vertex"));
//Trace::show("%d", glGetAttribLocation(m_programObjID, "cvfa_normal"));
//Trace::show("%d", glGetAttribLocation(m_programObjID, "cvfa_color"));
//Trace::show(programInfoLog().toAscii().ptr());
GLint iLinkStatus = 0;
glGetProgramiv(m_oglRcProgram->oglId(), GL_LINK_STATUS, &iLinkStatus);
if (iLinkStatus != GL_TRUE)
{
CVF_LOG_RENDER_ERROR(oglContext, String("Error linking shader program '%1', GLSL details:\n%2").arg(programName()).arg(programInfoLog(oglContext)));
return false;
}
m_needsLinking = false;
discoverActiveUniforms(oglContext);
return true;
}
//--------------------------------------------------------------------------------------------------
/// Creates the program. Does nothing shader program is already created
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::createProgram(OpenGLContext* oglContext)
{
CVF_ASSERT(ShaderProgram::supportedOpenGL(oglContext));
if (OglRc::safeOglId(m_oglRcProgram.p()) == 0)
{
OpenGLResourceManager* resourceManager = oglContext->resourceManager();
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcProgram.p()));
m_oglRcProgram = resourceManager->createOglRcProgram(oglContext);
if (m_oglRcProgram.isNull())
{
CVF_CHECK_OGL(oglContext);
return false;
}
m_needsLinking = true;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::needsLinking() const
{
if (m_needsLinking) return true;
uint numShaders = shaderCount();
CVF_ASSERT(numShaders == static_cast<uint>(m_linkedShaderVersionTicks.size()));
uint i;
for (i = 0; i < numShaders; i++)
{
const Shader* shader = m_shaders.at(i);
int compiledVersionTick = shader->compiledVersionTick();
if (compiledVersionTick != m_linkedShaderVersionTicks[i] || compiledVersionTick == -1)
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::useProgram(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_TIGHT_ASSERT(ShaderProgram::supportedOpenGL(oglContext));
if (m_needsLinking)
{
return false;
}
CVF_ASSERT(OglRc::safeOglId(m_oglRcProgram.p()) != 0);
CVF_ASSERT(validateProgram(oglContext));
// Need this check to clear any "hanging" errors that is not produced by glUseProgram below, but still
// will make this method return false.
CVF_CLEAR_OGL_ERROR(oglContext);
glUseProgram(m_oglRcProgram->oglId());
// TODO
// Is there any lightweight way to check if the glUseCall was successful
if (CVF_TEST_AND_REPORT_OPENGL_ERROR(oglContext, "Use shader program"))
{
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgram::useNoProgram(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_TIGHT_ASSERT(ShaderProgram::supportedOpenGL(oglContext));
glUseProgram(0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::isProgramUsed(OpenGLContext* /*oglContext*/) const
{
GLint currentProgram = 0;
glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram); // Note: GL_CURRENT_PROGRAM is renamed to GL_ACTIVE_PROGRAM in 4.1
if (currentProgram != 0)
{
if (static_cast<OglId>(currentProgram) == OglRc::safeOglId(m_oglRcProgram.p()))
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
OglId ShaderProgram::programOglId() const
{
return OglRc::safeOglId(m_oglRcProgram.p());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgram::deleteProgram(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
if (m_oglRcProgram.notNull())
{
m_oglRcProgram->deleteResource(oglContext);
CVF_CHECK_OGL(oglContext);
CVF_ASSERT(OglRc::isSafeToRelease(m_oglRcProgram.p()));
m_oglRcProgram = NULL;
uint numShaders = static_cast<uint>(m_linkedShaderVersionTicks.size());
uint i;
for (i = 0; i < numShaders; i++)
{
m_linkedShaderVersionTicks[i] = -1;
}
m_needsLinking = true;
}
CVF_ASSERT(m_needsLinking);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::validateProgram(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
if (OglRc::safeOglId(m_oglRcProgram.p()) == 0)
{
return false;
}
glValidateProgram(m_oglRcProgram->oglId());
GLint validateStatus = GL_FALSE;
glGetProgramiv(m_oglRcProgram->oglId(), GL_VALIDATE_STATUS, &validateStatus);
if (validateStatus == GL_TRUE)
{
return true;
}
else
{
// Any textual result of the vaidation is presented in the log
CVF_LOG_RENDER_ERROR(oglContext, programInfoLog(oglContext));
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the information log for this shader
///
/// See: http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramInfoLog.xml
//--------------------------------------------------------------------------------------------------
String ShaderProgram::programInfoLog(OpenGLContext* oglContext) const
{
CVF_CALLSITE_OPENGL(oglContext);
uint myOglId = OglRc::safeOglId(m_oglRcProgram.p());
if (myOglId == 0)
{
return "Program object not created.";
}
if (!glIsProgram(myOglId))
{
return "Program object identifier does not correspond to a shader program object.";
}
GLint reqBufferSize = 0;
glGetProgramiv(myOglId, GL_INFO_LOG_LENGTH, &reqBufferSize);
if (reqBufferSize > 0)
{
// TODO
// This is a good place for using CharArray
std::vector<GLchar> charBuffer;
charBuffer.resize(static_cast<size_t>(reqBufferSize + 1));
glGetProgramInfoLog(myOglId, reqBufferSize, NULL, &charBuffer[0]);
String logString(&charBuffer[0]);
return logString;
}
else
{
return "";
}
}
//--------------------------------------------------------------------------------------------------
/// Set a default uniform for this shader program
///
/// Default uniforms are stored with the shader program and may be used to bundle 'default' values
/// for some of the uniforms that the shader program exposes.and The default uniforms should be
/// applied using the applyDefaultUniforms() function.
//--------------------------------------------------------------------------------------------------
void ShaderProgram::setDefaultUniform(Uniform* uniform)
{
CVF_ASSERT(uniform);
if (m_defaultUniformSet.isNull())
{
m_defaultUniformSet = new UniformSet;
}
m_defaultUniformSet->setUniform(uniform);
}
//--------------------------------------------------------------------------------------------------
/// Apply the shader program's default uniforms
///
/// Will apply the shader program's default uniforms, if any. To get the intended behavior, the
/// default uniforms should typically be applied before applying any other uniforms. Otherwise, the
/// default values will overwrite any user specified uniforms.
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::applyDefaultUniforms(OpenGLContext* oglContext)
{
bool allUniformsSuccess = true;
if (m_defaultUniformSet.notNull())
{
size_t numUniforms = m_defaultUniformSet->count();
size_t i;
for (i = 0; i < numUniforms; i++)
{
const Uniform* uniform = m_defaultUniformSet->uniform(i);
allUniformsSuccess &= applyUniform(oglContext, *uniform);
}
}
return allUniformsSuccess;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgram::applyUniformAtLocation(OpenGLContext* oglContext, int location, const Uniform& uniform)
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_TIGHT_ASSERT(location >= 0);
const int valCount = uniform.valueCount();
CVF_ASSERT_MSG(valCount > 0, "No data set for uniform");
switch (uniform.type())
{
case Uniform::INT: glUniform1iv(location, valCount, uniform.intPtr()); break;
case Uniform::FLOAT: glUniform1fv(location, valCount, uniform.floatPtr()); break;
case Uniform::FLOAT_VEC2: glUniform2fv(location, valCount, uniform.floatPtr()); break;
case Uniform::FLOAT_VEC3: glUniform3fv(location, valCount, uniform.floatPtr()); break;
case Uniform::FLOAT_VEC4: glUniform4fv(location, valCount, uniform.floatPtr()); break;
case Uniform::FLOAT_MAT4: glUniformMatrix4fv(location, valCount, GL_FALSE, uniform.floatPtr()); break;
case Uniform::UNDEFINED: CVF_FAIL_MSG("Unhandled type");
}
}
//--------------------------------------------------------------------------------------------------
/// Specify value of a uniform variable in this shader program
///
/// \return Returns false if the uniform doesn't exist in this shader program.
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::applyUniform(OpenGLContext* oglContext, const Uniform& uniform)
{
int location = uniformLocation(uniform.name());
if (location == -1)
{
// If you end up here one of the following might have happened
// - the shader program is not properly linked
// - the uniform name is wrong
// - the specified uniform name is declared but not actually used in the program
// It is actually necessary to make the texture have influence on the resulting color, not just touch
// the texture.
CVF_LOG_RENDER_ERROR(oglContext, String("In program '%1', error applying uniform: %2").arg(programName()).arg(uniform.name()));
return false;
}
applyUniformAtLocation(oglContext, location, uniform);
m_appliedUniformLocations.insert(location);
CVF_CHECK_OGL(oglContext);
return true;
}
//--------------------------------------------------------------------------------------------------
/// Specify values of uniform variables in this shader program
///
/// \return Returns true if all uniforms in the uniform set were applied successfully. Returns false
/// if any of the uniforms didn't exist in the shader program.
///
/// \sa applyUniform(), applyActiveUniformsOnly()
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::applyUniforms(OpenGLContext* oglContext, const UniformSet& uniformSet)
{
bool allUniformsSuccess = true;
size_t numUniforms = uniformSet.count();
size_t i;
for (i = 0; i < numUniforms; i++)
{
const Uniform* uniform = uniformSet.uniform(i);
allUniformsSuccess &= applyUniform(oglContext, *uniform);
}
return allUniformsSuccess;
}
//--------------------------------------------------------------------------------------------------
/// Apply only uniforms that are active in this shader program
///
/// As opposed to applyUniforms() this function will allow uniform sets consisting of uniforms that are
/// not active in the shader program.
//--------------------------------------------------------------------------------------------------
void ShaderProgram::applyActiveUniformsOnly(OpenGLContext* oglContext, const UniformSet& uniformSet)
{
size_t numUniforms = uniformSet.count();
size_t i;
for (i = 0; i < numUniforms; i++)
{
const Uniform* uniform = uniformSet.uniform(i);
int location = uniformLocation(uniform->name());
if (location != -1)
{
applyUniformAtLocation(oglContext, location, *uniform);
m_appliedUniformLocations.insert(location);
}
}
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgram::applyFixedUniforms(OpenGLContext* oglContext, const MatrixState& matrixState)
{
CVF_CALLSITE_OPENGL(oglContext);
std::map<FixedUniform, int>::const_iterator it;
for (it = m_fixedUniformsMap.begin(); it != m_fixedUniformsMap.end(); ++it)
{
int location = it->second;
CVF_ASSERT(location >= 0);
FixedUniform fixedUniform = it->first;
switch (fixedUniform)
{
case PROJECTION_MATRIX: glUniformMatrix4fv(location, 1, GL_FALSE, matrixState.projectionMatrix().ptr()); break;
case VIEW_MATRIX: glUniformMatrix4fv(location, 1, GL_FALSE, matrixState.viewMatrix().ptr()); break;
case VIEW_MATRIX_INVERSE: glUniformMatrix4fv(location, 1, GL_FALSE, matrixState.viewMatrixInverse().ptr()); break;
case MODEL_MATRIX: glUniformMatrix4fv(location, 1, GL_FALSE, matrixState.modelMatrix().ptr()); break;
case MODEL_MATRIX_INVERSE: glUniformMatrix4fv(location, 1, GL_FALSE, matrixState.modelMatrixInverse().ptr()); break;
case MODEL_MATRIX_INVERSE_TRANSPOSE: glUniformMatrix4fv(location, 1, GL_FALSE, matrixState.modelMatrixInverseTranspose().ptr()); break;
case MODEL_VIEW_MATRIX: glUniformMatrix4fv(location, 1, GL_FALSE, matrixState.modelViewMatrix().ptr()); break;
case MODEL_VIEW_MATRIX_INVERSE: glUniformMatrix4fv(location, 1, GL_FALSE, matrixState.modelViewMatrixInverse().ptr()); break;
case MODEL_VIEW_PROJECTION_MATRIX: glUniformMatrix4fv(location, 1, GL_FALSE, matrixState.modelViewProjectionMatrix().ptr()); break;
case NORMAL_MATRIX: glUniformMatrix3fv(location, 1, GL_FALSE, matrixState.normalMatrix().ptr()); break;
case PIXEL_HEIGHT_AT_UNIT_DISTANCE: glUniform1f(location, matrixState.pixelHeightAtUnitDistance()); break;
default:
CVF_FAIL_MSG("Unhandled fixed uniform");
break;
}
// Assume that the uniform got set
// Hitting default clause implies programming error
m_appliedUniformLocations.insert(location);
CVF_CHECK_OGL(oglContext);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgram::clearUniformApplyTracking()
{
m_appliedUniformLocations.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgram::checkReportAllUniformsApplied(OpenGLContext* oglContext) const
{
const size_t numUniformsApplied = m_appliedUniformLocations.size();
const size_t numUniforms = m_fixedUniformsNameLocationMap.size() + m_uniformsNameLocationMap.size();
if (numUniforms != numUniformsApplied)
{
std::map<std::string, int>::const_iterator it;
for (it = m_uniformsNameLocationMap.begin(); it != m_uniformsNameLocationMap.end(); ++it)
{
int uniformLocation = it->second;
if (m_appliedUniformLocations.find(uniformLocation) == m_appliedUniformLocations.end())
{
std::string uniformName(it->first);
if (m_uniformsDisabledFromTracking.find(uniformName) == m_uniformsDisabledFromTracking.end())
{
CVF_LOG_RENDER_ERROR(oglContext, String("In program '%1', uniform not set: %2").arg(programName()).arg(uniformName));
}
}
}
for (it = m_fixedUniformsNameLocationMap.begin(); it != m_fixedUniformsNameLocationMap.end(); ++it)
{
int uniformLocation = it->second;
if (m_appliedUniformLocations.find(uniformLocation) == m_appliedUniformLocations.end())
{
CVF_LOG_RENDER_ERROR(oglContext, String("In program '%1', fixed uniform not set: %2").arg(programName()).arg(String(it->first)));
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgram::disableUniformTrackingForUniform(const char* name)
{
m_uniformsDisabledFromTracking.insert(name);
}
//--------------------------------------------------------------------------------------------------
/// Returns integer that represents the location of the specific uniform variable
///
/// This function returns -1 if the name does not correspond to an active uniform variable in
/// the program.
//--------------------------------------------------------------------------------------------------
int ShaderProgram::uniformLocation(const char* name) const
{
std::map<std::string, int>::const_iterator it = m_uniformsNameLocationMap.find(name);
if (it != m_uniformsNameLocationMap.end())
{
return it->second;
}
// Not found amongst general uniforms. Now try the fixed ones
it = m_fixedUniformsNameLocationMap.find(name);
if (it != m_fixedUniformsNameLocationMap.end())
{
return it->second;
}
return -1;
}
//--------------------------------------------------------------------------------------------------
/// Does discovery of active uniforms in this program.
///
/// Finds all active uniforms in the (linked) shader program and categorizes them as either fixed
/// or general uniforms. Stores the location for the uniforms for later usage.
//--------------------------------------------------------------------------------------------------
void ShaderProgram::discoverActiveUniforms(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
m_fixedUniformsMap.clear();
m_fixedUniformsNameLocationMap.clear();
m_uniformsNameLocationMap.clear();
m_appliedUniformLocations.clear();
GLint numActiveUniforms = 0;
GLint maxUniformNameLength = 0;
glGetProgramiv(m_oglRcProgram->oglId(), GL_ACTIVE_UNIFORMS, &numActiveUniforms);
glGetProgramiv(m_oglRcProgram->oglId(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformNameLength);
if (numActiveUniforms <= 0 || maxUniformNameLength <= 0)
{
return;
}
CharArray uniformNameBuffer(static_cast<size_t>(maxUniformNameLength), 0);
const GLsizei bufferSize = static_cast<GLsizei>(uniformNameBuffer.size());
uint i;
for (i = 0; i < static_cast<uint>(numActiveUniforms); i++)
{
GLsizei numCharsInName = 0;
GLint uniformSize = 0;
GLenum uniformDataType = 0;
glGetActiveUniform(m_oglRcProgram->oglId(), i, bufferSize, &numCharsInName, &uniformSize, &uniformDataType, uniformNameBuffer.ptr());
CVF_CHECK_OGL(oglContext);
//Trace::show("%d: uniformSize=%d uniformDataType=%d uniformName=%s", i, uniformSize, uniformDataType, uniformNameBuffer.ptr());
if (numCharsInName > 0)
{
const char* uniformName = uniformNameBuffer.ptr();
int location = glGetUniformLocation(m_oglRcProgram->oglId(), uniformName);
CVF_CHECK_OGL(oglContext);
FixedUniform fixedUniform;
if (ShaderProgram::mapUniformNameToFixedUniformEnum(uniformName, &fixedUniform))
{
m_fixedUniformsMap[fixedUniform] = location;
m_fixedUniformsNameLocationMap[uniformName] = location;
}
else
{
m_uniformsNameLocationMap[uniformName] = location;
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::mapUniformNameToFixedUniformEnum(const char* uniformName, FixedUniform* fixedUniform)
{
CVF_ASSERT(uniformName);
CVF_ASSERT(fixedUniform);
if (System::strcmp(uniformName, "cvfu_projectionMatrix") == 0) { *fixedUniform = PROJECTION_MATRIX; return true; }
else if (System::strcmp(uniformName, "cvfu_viewMatrix") == 0) { *fixedUniform = VIEW_MATRIX; return true; }
else if (System::strcmp(uniformName, "cvfu_viewMatrixInverse") == 0) { *fixedUniform = VIEW_MATRIX_INVERSE; return true; }
else if (System::strcmp(uniformName, "cvfu_modelMatrix") == 0) { *fixedUniform = MODEL_MATRIX; return true; }
else if (System::strcmp(uniformName, "cvfu_modelMatrixInverse") == 0) { *fixedUniform = MODEL_MATRIX_INVERSE; return true; }
else if (System::strcmp(uniformName, "cvfu_modelMatrixInverseTranspose") == 0) { *fixedUniform = MODEL_MATRIX_INVERSE_TRANSPOSE; return true; }
else if (System::strcmp(uniformName, "cvfu_modelViewMatrix") == 0) { *fixedUniform = MODEL_VIEW_MATRIX; return true; }
else if (System::strcmp(uniformName, "cvfu_modelViewMatrixInverse") == 0) { *fixedUniform = MODEL_VIEW_MATRIX_INVERSE; return true; }
else if (System::strcmp(uniformName, "cvfu_modelViewProjectionMatrix") == 0) { *fixedUniform = MODEL_VIEW_PROJECTION_MATRIX; return true; }
else if (System::strcmp(uniformName, "cvfu_normalMatrix") == 0) { *fixedUniform = NORMAL_MATRIX; return true; }
else if (System::strcmp(uniformName, "cvfu_pixelHeightAtUnitDistance") == 0) { *fixedUniform = PIXEL_HEIGHT_AT_UNIT_DISTANCE; return true; }
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the index of the vertex attribute that is bound to attribute variable specified by name
///
/// Returns -1 if the name does not correspond to an active attribute or if name starts with the
/// reserved "gl_" prefix.
///
/// \sa http://www.opengl.org/sdk/docs/man3/xhtml/glGetAttribLocation.xml
//--------------------------------------------------------------------------------------------------
int ShaderProgram::attributeLocation(OpenGLContext* oglContext, const char* name) const
{
CVF_CALLSITE_OPENGL(oglContext);
if (OglRc::safeOglId(m_oglRcProgram.p()) != 0)
{
GLint attribIndex = glGetAttribLocation(m_oglRcProgram->oglId(), name);
return attribIndex;
}
return -1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgram::bindFixedAttributes(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_ASSERT(OglRc::safeOglId(m_oglRcProgram.p()) != 0);
glBindAttribLocation(m_oglRcProgram->oglId(), VERTEX, "cvfa_vertex");
glBindAttribLocation(m_oglRcProgram->oglId(), NORMAL, "cvfa_normal");
glBindAttribLocation(m_oglRcProgram->oglId(), COLOR, "cvfa_color");
glBindAttribLocation(m_oglRcProgram->oglId(), TEX_COORD_2F_0,"cvfa_texCoord");
CVF_CHECK_OGL(oglContext);
}
//--------------------------------------------------------------------------------------------------
/// Query if the current OpenGL context supports shaders
//--------------------------------------------------------------------------------------------------
bool ShaderProgram::supportedOpenGL(OpenGLContext* oglContext)
{
return oglContext->capabilities()->supportsOpenGL2();
}
} // namespace cvf
@@ -0,0 +1,134 @@
//##################################################################################################
//
// 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 "cvfShader.h"
#include "cvfCollection.h"
#include <map>
namespace cvf {
class Uniform;
class UniformSet;
class MatrixState;
class OpenGLContext;
class OglRcProgram;
//==================================================================================================
//
// Encapsulates a GLSL shader program
//
//==================================================================================================
class ShaderProgram : public Object
{
public:
enum FixedUniform
{
PROJECTION_MATRIX,
VIEW_MATRIX,
VIEW_MATRIX_INVERSE,
MODEL_MATRIX,
MODEL_MATRIX_INVERSE,
MODEL_MATRIX_INVERSE_TRANSPOSE,
MODEL_VIEW_MATRIX,
MODEL_VIEW_MATRIX_INVERSE,
MODEL_VIEW_PROJECTION_MATRIX,
NORMAL_MATRIX,
PIXEL_HEIGHT_AT_UNIT_DISTANCE
};
enum FixedAttribute
{
VERTEX = 0, // At least Nvidia has the following aliases for gl_Vertex, gl_Normal and gl_Color
NORMAL = 2, // Source: http://developer.download.nvidia.com/opengl/glsl/glsl_release_notes.pdf
COLOR = 3,
TEX_COORD_2F_0 = 8
};
public:
ShaderProgram(const String& programName = String());
~ShaderProgram();
void setProgramName(const String& programName);
String programName() const;
void addShader(Shader* shader);
uint shaderCount() const;
Shader* shader(uint index);
bool linkProgram(OpenGLContext* oglContext);
bool useProgram(OpenGLContext* oglContext) const;
static void useNoProgram(OpenGLContext* oglContext);
bool isProgramUsed(OpenGLContext* oglContext) const;
OglId programOglId() const;
void deleteProgram(OpenGLContext* oglContext);
bool validateProgram(OpenGLContext* oglContext) const;
String programInfoLog(OpenGLContext* oglContext) const;
int uniformLocation(const char* name) const;
void setDefaultUniform(Uniform* uniform);
bool applyDefaultUniforms(OpenGLContext* oglContext);
bool applyUniform(OpenGLContext* oglContext, const Uniform& uniform);
bool applyUniforms(OpenGLContext* oglContext, const UniformSet& uniformSet);
void applyActiveUniformsOnly(OpenGLContext* oglContext, const UniformSet& uniformSet);
void applyFixedUniforms(OpenGLContext* oglContext, const MatrixState& matrixState);
void clearUniformApplyTracking();
void checkReportAllUniformsApplied(OpenGLContext* oglContext) const;
void disableUniformTrackingForUniform(const char* name);
int attributeLocation(OpenGLContext* oglContext, const char* name) const;
static bool supportedOpenGL(OpenGLContext* oglContext);
private:
bool createProgram(OpenGLContext* oglContext);
bool needsLinking() const;
void discoverActiveUniforms(OpenGLContext* oglContext);
static bool mapUniformNameToFixedUniformEnum(const char* uniformName, FixedUniform* fixedUniform);
static void applyUniformAtLocation(OpenGLContext* oglContext, int location, const Uniform& uniform);
void bindFixedAttributes(OpenGLContext* oglContext);
private:
String m_programName; // Name of this program. Primarily used when reporting errors.
ref<OglRcProgram> m_oglRcProgram; // Reference to OglRc object that contains the program's OpenGL id
Collection<Shader> m_shaders; //
std::vector<int> m_linkedShaderVersionTicks;
bool m_needsLinking; // Flag to indicate that this shader program must be linked
ref<UniformSet> m_defaultUniformSet; // The shader program's default uniform set (if any). Applied using applyDefaultUniforms() (before any other appky functions)
std::map<FixedUniform, int> m_fixedUniformsMap; // Maps the CVF fixed uniforms that were discovered to their locations
std::map<std::string, int> m_fixedUniformsNameLocationMap; // Maps fixed uniform names to their locations. Populated during discovery of active uniforms
std::map<std::string, int> m_uniformsNameLocationMap; // Maps general uniform names to their locations. Populated during discovery of active uniforms
std::set<int> m_appliedUniformLocations; // Tracks the uniforms that have been applied since the last call to clearUniformApplyTracking()
std::set<std::string> m_uniformsDisabledFromTracking; // Array with the uniforms that should be exempt from the uniform tracking
};
}
@@ -0,0 +1,348 @@
//##################################################################################################
//
// 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 "cvfShaderProgramGenerator.h"
#include "cvfShaderProgram.h"
#include "cvfShaderSourceProvider.h"
#include "cvfMath.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::ShaderProgramGenerator
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ShaderProgramGenerator::ShaderProgramGenerator(String shaderProgramName, ShaderSourceProvider* sourceProvider)
{
CVF_ASSERT(sourceProvider);
m_sourceProvider = sourceProvider;
m_shaderProgramName = shaderProgramName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgramGenerator::addVertexCode(ShaderSourceRepository::ShaderIdent shaderIdent)
{
String code = m_sourceProvider->getSourceFromRepository(shaderIdent);
m_vertexCodes.push_back(code);
m_vertexNames.push_back(ShaderSourceRepository::shaderIdentString(shaderIdent));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgramGenerator::addFragmentCode(ShaderSourceRepository::ShaderIdent shaderIdent)
{
String code = m_sourceProvider->getSourceFromRepository(shaderIdent);
m_fragmentCodes.push_back(code);
m_fragmentNames.push_back(ShaderSourceRepository::shaderIdentString(shaderIdent));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgramGenerator::addGeometryCode(ShaderSourceRepository::ShaderIdent shaderIdent)
{
String code = m_sourceProvider->getSourceFromRepository(shaderIdent);
m_geometryCodes.push_back(code);
m_geometryNames.push_back(ShaderSourceRepository::shaderIdentString(shaderIdent));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgramGenerator::addVertexCode(const String& vertShaderCode)
{
m_vertexNames.push_back("Vert");
m_vertexCodes.push_back(vertShaderCode);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgramGenerator::addFragmentCode(const String& fragShaderCode)
{
m_fragmentNames.push_back("Frag");
m_fragmentCodes.push_back(fragShaderCode);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgramGenerator::addVertexCodeFromFile(String shaderName)
{
String code = m_sourceProvider->getSourceFromFile(shaderName);
m_vertexCodes.push_back(code);
m_vertexNames.push_back(shaderName);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgramGenerator::addFragmentCodeFromFile(String shaderName)
{
String code = m_sourceProvider->getSourceFromFile(shaderName);
m_fragmentCodes.push_back(code);
m_fragmentNames.push_back(shaderName);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgramGenerator::configureStandardHeadlightColor()
{
addVertexCode(ShaderSourceRepository::vs_Standard);
addFragmentCode(ShaderSourceRepository::src_Color);
addFragmentCode(ShaderSourceRepository::light_SimpleHeadlight);
addFragmentCode(ShaderSourceRepository::fs_Standard);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderProgramGenerator::configureStandardHeadlightTexture()
{
addVertexCode(ShaderSourceRepository::vs_Standard);
addFragmentCode(ShaderSourceRepository::src_Texture);
addFragmentCode(ShaderSourceRepository::light_SimpleHeadlight);
addFragmentCode(ShaderSourceRepository::fs_Standard);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<ShaderProgram> ShaderProgramGenerator::generate()
{
CVF_ASSERT((m_vertexCodes.size() > 0) && (m_fragmentCodes.size() > 0));
ShaderSourceCombiner vertexCombiner(m_vertexCodes, m_vertexNames);
ShaderSourceCombiner fragmentCombiner(m_fragmentCodes, m_fragmentNames);
String vertexSource = vertexCombiner.combinedSource();
String fragmentSource = fragmentCombiner.combinedSource();
// String vertexSource = combineShaders(m_vertexCodes, m_vertexNames);
// String fragmentSource = combineShaders(m_fragmentCodes, m_fragmentNames);
ref<ShaderProgram> prog = new ShaderProgram(m_shaderProgramName);
ref<Shader> vertexShader = new Shader(Shader::VERTEX_SHADER, m_shaderProgramName + "-vert", vertexSource);
ref<Shader> fragmentShader = new Shader(Shader::FRAGMENT_SHADER, m_shaderProgramName + "-frag", fragmentSource);
prog->addShader(vertexShader.p());
prog->addShader(fragmentShader.p());
if (m_geometryCodes.size() > 0)
{
ShaderSourceCombiner geometryCombiner(m_geometryCodes, m_geometryNames);
String geometrySource = geometryCombiner.combinedSource();
// String geometrySource = combineShaders(m_geometryCodes, m_geometryNames);
ref<Shader> geometryShader = new Shader(Shader::GEOMETRY_SHADER, m_shaderProgramName + "-geo", geometrySource);
prog->addShader(geometryShader.p());
}
return prog;
}
//==================================================================================================
///
/// \class cvf::ShaderSourceCombiner
/// \ingroup Render
///
/// Helper class for combining shader source code (bits) into one source code string
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ShaderSourceCombiner::ShaderSourceCombiner(const std::vector<String>& shaderCodes, const std::vector<String>& shaderNames)
: m_shaderCodes(shaderCodes),
m_shaderNames(shaderNames),
m_enableDebugComments(true)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String ShaderSourceCombiner::combinedSource() const
{
uint maxVersion = 0;
size_t i;
for (i = 0; i < m_shaderCodes.size(); i++)
{
uint thisVer = findVersion(m_shaderCodes[i]);
maxVersion = CVF_MAX(thisVer, maxVersion);
}
String combinedSource;
std::set<String> globalKeywordLinesAlreadyAdded;
if (maxVersion > 0)
{
combinedSource = String("#version %1\n\n").arg(maxVersion);
}
#ifdef CVF_OPENGL_ES
combinedSource += "#define CVF_OPENGL_ES\n";
#endif
for (i = 0; i < m_shaderCodes.size(); i++)
{
if (m_enableDebugComments)
{
combinedSource += "\n//=========================================================================================================\n//\n";
combinedSource += String("// File: %1\n//-------------------------------------\n\n").arg(m_shaderNames[i]);
}
String source = m_shaderCodes[i];
std::vector<String> sourceLines = source.split("\n");
std::vector<String>::iterator it;
for (it = sourceLines.begin(); it != sourceLines.end(); ++it)
{
String sourceLine = *it;
bool addThisLine = true;
if (sourceLine.find("#version") != String::npos)
{
addThisLine = false;
}
if (startsWithGlobalKeyword(sourceLine))
{
String simplifiedLine = sourceLine.simplified();
if (globalKeywordLinesAlreadyAdded.find(simplifiedLine) != globalKeywordLinesAlreadyAdded.end())
{
// Line already added
addThisLine = false;
}
else
{
globalKeywordLinesAlreadyAdded.insert(simplifiedLine);
}
}
if (addThisLine)
{
combinedSource += (sourceLine + "\n");
}
}
}
return combinedSource;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderSourceCombiner::enableDebugComments(bool enableDebugComments)
{
m_enableDebugComments = enableDebugComments;
}
//--------------------------------------------------------------------------------------------------
/// Reads the first line of the shader and checks for "#version xxx"
//--------------------------------------------------------------------------------------------------
uint ShaderSourceCombiner::findVersion(const String& shaderCode)
{
size_t firstNewline = shaderCode.find("\n");
if (firstNewline == String::npos)
{
return 0;
}
String firstLine = shaderCode.subString(0, firstNewline);
std::vector<String> firstLineArr = firstLine.split(" ");
if (firstLineArr.size() == 0)
{
return 0;
}
if (firstLineArr[0] != "#version")
{
return 0;
}
uint version = static_cast<uint>(firstLineArr[1].toInt(0));
return version;
}
//--------------------------------------------------------------------------------------------------
/// Check if the code line starts with one of the global keywords uniform, varying or attribute
//--------------------------------------------------------------------------------------------------
bool ShaderSourceCombiner::startsWithGlobalKeyword(const String& codeLine)
{
if (codeLine.size() < 1)
{
return false;
}
std::wstring str = codeLine.trimmedLeft().toStdWString();
// Same whitespace characters as isspace()
const std::wstring whitespaces(L" \t\n\v\f\r");
size_t pos = str.find_first_of(whitespaces);
if (pos != std::wstring::npos && pos > 0)
{
const std::wstring firstWord = str.substr(0, pos);
if (firstWord.compare(L"uniform") == 0 ||
firstWord.compare(L"attribute") == 0 ||
firstWord.compare(L"varying") == 0)
{
return true;
}
}
return false;
}
} // namespace cvf
@@ -0,0 +1,93 @@
//##################################################################################################
//
// 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 "cvfShaderSourceRepository.h"
namespace cvf {
class ShaderSourceProvider;
class ShaderProgram;
//==================================================================================================
//
//
//
//==================================================================================================
class ShaderProgramGenerator
{
public:
ShaderProgramGenerator(String shaderProgramName, ShaderSourceProvider* sourceProvider);
void addVertexCode(ShaderSourceRepository::ShaderIdent shaderIdent);
void addFragmentCode(ShaderSourceRepository::ShaderIdent shaderIdent);
void addGeometryCode(ShaderSourceRepository::ShaderIdent shaderIdent);
void addVertexCode(const String& vertShaderCode);
void addFragmentCode(const String& fragShaderCode);
void addVertexCodeFromFile(String shaderName);
void addFragmentCodeFromFile(String shaderName);
void configureStandardHeadlightColor();
void configureStandardHeadlightTexture();
ref<ShaderProgram> generate();
private:
ShaderSourceProvider* m_sourceProvider;
String m_shaderProgramName;
std::vector<String> m_vertexCodes;
std::vector<String> m_fragmentCodes;
std::vector<String> m_geometryCodes;
std::vector<String> m_vertexNames;
std::vector<String> m_fragmentNames;
std::vector<String> m_geometryNames;
};
//==================================================================================================
//
//
//
//==================================================================================================
class ShaderSourceCombiner
{
public:
ShaderSourceCombiner(const std::vector<String>& shaderCodes, const std::vector<String>& shaderNames);
void enableDebugComments(bool enableDebugComments);
String combinedSource() const;
private:
static uint findVersion(const String& shaderCode);
static bool startsWithGlobalKeyword(const String& codeLine);
private:
const std::vector<String>& m_shaderCodes;
const std::vector<String>& m_shaderNames;
bool m_enableDebugComments;
};
}
@@ -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 "cvfShaderSourceProvider.h"
#include "cvfShaderProgram.h"
#include <sys/stat.h>
#include <stdio.h>
#include <fstream>
namespace cvf {
//==================================================================================================
///
/// \class cvf::ShaderSourceProvider
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Private constructor
//--------------------------------------------------------------------------------------------------
ShaderSourceProvider::ShaderSourceProvider()
{
m_sourceRepository = new ShaderSourceRepository;
}
//--------------------------------------------------------------------------------------------------
/// Private destructor
//--------------------------------------------------------------------------------------------------
ShaderSourceProvider::~ShaderSourceProvider()
{
}
//--------------------------------------------------------------------------------------------------
/// Get a pointer to the singleton instance.
//--------------------------------------------------------------------------------------------------
ShaderSourceProvider* ShaderSourceProvider::instance()
{
static ref<ShaderSourceProvider> staticInstance = new ShaderSourceProvider;
return staticInstance.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String ShaderSourceProvider::getSourceFromRepository(ShaderSourceRepository::ShaderIdent shaderIdent)
{
CVF_ASSERT(m_sourceRepository.notNull());
return m_sourceRepository->shaderSource(shaderIdent);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String ShaderSourceProvider::getSourceFromFile(String shaderName)
{
const String fileName = shaderName + ".glsl";
size_t i;
for (i = 0; i < m_searchDirectories.size(); i++)
{
String fullPath = m_searchDirectories[i] + fileName;
CharArray fileContents;
if (loadFile(fullPath, &fileContents))
{
return String(fileContents.ptr());
}
}
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ShaderSourceProvider::setSourceRepository(ShaderSourceRepository* repository)
{
m_sourceRepository = repository;
}
//--------------------------------------------------------------------------------------------------
/// Add directory to list of search directories
///
/// \param directory Directory with trailing slash
//--------------------------------------------------------------------------------------------------
void ShaderSourceProvider::addFileSearchDirectory(String directory)
{
m_searchDirectories.push_back(directory);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ShaderSourceProvider::loadFile(const String& fullFileName, CharArray* fileContents)
{
#ifdef WIN32
std::ifstream file(fullFileName.ptr());
#else
std::ifstream file(fullFileName.toUtf8().ptr());
#endif
if (!file.is_open())
{
return false;
}
std::string line;
while (file.good())
{
getline(file, line);
size_t c;
for (c = 0; c < line.length(); c++)
{
fileContents->push_back(line[c]);
}
fileContents->push_back('\n');
}
file.close();
return true;
}
} // namespace cvf
@@ -0,0 +1,56 @@
//##################################################################################################
//
// 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 "cvfShaderSourceRepository.h"
#include <vector>
namespace cvf {
//==================================================================================================
//
//
//
//==================================================================================================
class ShaderSourceProvider : public Object
{
public:
static ShaderSourceProvider* instance();
String getSourceFromRepository(ShaderSourceRepository::ShaderIdent shaderIdent);
String getSourceFromFile(String shaderName);
void setSourceRepository(ShaderSourceRepository* repository);
void addFileSearchDirectory(String directory);
private:
static bool loadFile(const String& fullFileName, CharArray* fileContents);
ShaderSourceProvider();
virtual ~ShaderSourceProvider();
private:
ref<ShaderSourceRepository> m_sourceRepository; // Reference to the shader source repository
std::vector<String> m_searchDirectories; // Array of directories to look in when creating shader from file
};
}
@@ -0,0 +1,195 @@
//##################################################################################################
//
// 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 "cvfString.h"
#include "cvfShaderSourceRepository.h"
#include "cvfShaderSourceStrings.h"
#include <fstream>
namespace cvf {
//==================================================================================================
///
/// \class cvf::ShaderSourceRepository
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ShaderSourceRepository::ShaderSourceRepository()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ShaderSourceRepository::~ShaderSourceRepository()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String ShaderSourceRepository::shaderSource(ShaderIdent shaderIdent)
{
String shaderProg;
CharArray rawSource;
if (rawShaderSource(shaderIdent, &rawSource))
{
if (rawSource.size() > 0)
{
#ifdef CVF_OPENGL_ES
// Always version 100 on OpenGL ES
shaderProg = "#version 100\nprecision highp float;\n";
#else
// Default on desktop is GLSL 1.2 (OpenGL 2.1) unless the shader explicitly specifies a version
if (rawSource[0] != '#')
{
shaderProg = "#version 120\n";
}
#endif
shaderProg += rawSource.ptr();
}
}
return shaderProg;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const char* ShaderSourceRepository::shaderIdentString(ShaderIdent shaderIdent)
{
#define CVF_IDENT_HANDLE_CASE(THE_ENUM) case THE_ENUM: return #THE_ENUM;
switch (shaderIdent)
{
CVF_IDENT_HANDLE_CASE(calcClipDistances);
CVF_IDENT_HANDLE_CASE(calcShadowCoord);
CVF_IDENT_HANDLE_CASE(src_Color);
CVF_IDENT_HANDLE_CASE(src_Texture);
CVF_IDENT_HANDLE_CASE(src_TextureGlobalAlpha);
CVF_IDENT_HANDLE_CASE(src_TextureFromPointCoord);
CVF_IDENT_HANDLE_CASE(src_TextureRectFromFragCoord_v33);
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(checkDiscard_ClipDistances);
CVF_IDENT_HANDLE_CASE(vs_Standard);
CVF_IDENT_HANDLE_CASE(vs_EnvironmentMapping);
CVF_IDENT_HANDLE_CASE(vs_FullScreenQuad);
CVF_IDENT_HANDLE_CASE(vs_Minimal);
CVF_IDENT_HANDLE_CASE(vs_MinimalTexture);
CVF_IDENT_HANDLE_CASE(vs_VectorDrawer);
CVF_IDENT_HANDLE_CASE(vs_DistanceScaledPoints);
CVF_IDENT_HANDLE_CASE(vs_ParticleTraceComets);
CVF_IDENT_HANDLE_CASE(fs_Standard);
CVF_IDENT_HANDLE_CASE(fs_Shadow_v33);
CVF_IDENT_HANDLE_CASE(fs_Unlit);
CVF_IDENT_HANDLE_CASE(fs_Void);
CVF_IDENT_HANDLE_CASE(fs_FixedColorMagenta);
CVF_IDENT_HANDLE_CASE(fs_Text);
CVF_IDENT_HANDLE_CASE(fs_VectorDrawer);
CVF_IDENT_HANDLE_CASE(fs_CenterLitSpherePoints);
CVF_IDENT_HANDLE_CASE(fs_ParticleTraceComets);
CVF_IDENT_HANDLE_CASE(fs_GradientTopBottom);
CVF_IDENT_HANDLE_CASE(fs_GradientTopMiddleBottom);
CVF_IDENT_HANDLE_CASE(gs_PassThroughTriangle_v33);
}
CVF_FAIL_MSG("Unhandled shader ident");
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ShaderSourceRepository::rawShaderSource(ShaderIdent shaderIdent, CharArray* rawSource)
{
#define CVF_SOURCE_HANDLE_CASE(THE_ENUM) case THE_ENUM: *rawSource = CharArray(THE_ENUM##_inl); return true;
switch (shaderIdent)
{
CVF_SOURCE_HANDLE_CASE(calcClipDistances);
CVF_SOURCE_HANDLE_CASE(calcShadowCoord);
CVF_SOURCE_HANDLE_CASE(src_Color);
CVF_SOURCE_HANDLE_CASE(src_Texture);
CVF_SOURCE_HANDLE_CASE(src_TextureGlobalAlpha);
CVF_SOURCE_HANDLE_CASE(src_TextureFromPointCoord);
CVF_SOURCE_HANDLE_CASE(src_TextureRectFromFragCoord_v33);
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(checkDiscard_ClipDistances);
CVF_SOURCE_HANDLE_CASE(vs_Standard);
CVF_SOURCE_HANDLE_CASE(vs_EnvironmentMapping);
CVF_SOURCE_HANDLE_CASE(vs_FullScreenQuad);
CVF_SOURCE_HANDLE_CASE(vs_Minimal);
CVF_SOURCE_HANDLE_CASE(vs_MinimalTexture);
CVF_SOURCE_HANDLE_CASE(vs_VectorDrawer);
CVF_SOURCE_HANDLE_CASE(vs_DistanceScaledPoints);
CVF_SOURCE_HANDLE_CASE(vs_ParticleTraceComets);
CVF_SOURCE_HANDLE_CASE(fs_Standard);
CVF_SOURCE_HANDLE_CASE(fs_Shadow_v33);
CVF_SOURCE_HANDLE_CASE(fs_Unlit);
CVF_SOURCE_HANDLE_CASE(fs_Void);
CVF_SOURCE_HANDLE_CASE(fs_FixedColorMagenta);
CVF_SOURCE_HANDLE_CASE(fs_Text);
CVF_SOURCE_HANDLE_CASE(fs_VectorDrawer);
CVF_SOURCE_HANDLE_CASE(fs_CenterLitSpherePoints);
CVF_SOURCE_HANDLE_CASE(fs_ParticleTraceComets);
CVF_SOURCE_HANDLE_CASE(fs_GradientTopBottom);
CVF_SOURCE_HANDLE_CASE(fs_GradientTopMiddleBottom);
CVF_SOURCE_HANDLE_CASE(gs_PassThroughTriangle_v33);
}
CVF_FAIL_MSG("Unhandled shader source ident");
return false;
}
} // namespace cvf
@@ -0,0 +1,92 @@
//##################################################################################################
//
// 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 "cvfObject.h"
#include "cvfString.h"
namespace cvf {
class CharArray;
//==================================================================================================
//
//
//
//==================================================================================================
class ShaderSourceRepository : public Object
{
public:
enum ShaderIdent
{
calcClipDistances,
calcShadowCoord,
src_Color,
src_Texture,
src_TextureGlobalAlpha,
src_TextureFromPointCoord,
src_TextureRectFromFragCoord_v33,
light_Phong,
light_PhongDual,
light_SimpleHeadlight,
light_SimpleHeadlight_spec_uniform,
light_AmbientDiffuse,
checkDiscard_ClipDistances,
vs_Standard,
vs_EnvironmentMapping,
vs_FullScreenQuad,
vs_Minimal,
vs_MinimalTexture,
vs_VectorDrawer,
vs_DistanceScaledPoints,
vs_ParticleTraceComets,
fs_Standard,
fs_Shadow_v33,
fs_Unlit,
fs_Void,
fs_FixedColorMagenta,
fs_Text,
fs_VectorDrawer,
fs_CenterLitSpherePoints,
fs_ParticleTraceComets,
fs_GradientTopBottom,
fs_GradientTopMiddleBottom,
gs_PassThroughTriangle_v33
};
public:
ShaderSourceRepository();
virtual ~ShaderSourceRepository();
String shaderSource(ShaderIdent shaderIdent);
static const char* shaderIdentString(ShaderIdent shaderIdent);
protected:
virtual bool rawShaderSource(ShaderIdent shaderIdent, CharArray* rawSource);
};
}
@@ -0,0 +1,96 @@
//##################################################################################################
//
// 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 "cvfShaderSourceRepositoryFile.h"
#include <fstream>
namespace cvf {
//==================================================================================================
///
/// \class cvf::ShaderSourceRepositoryFile
/// \ingroup Render
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
///
/// \param directory Directory with trailing slash
//--------------------------------------------------------------------------------------------------
ShaderSourceRepositoryFile::ShaderSourceRepositoryFile(const String& directory)
: m_directory(directory)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ShaderSourceRepositoryFile::rawShaderSource(ShaderIdent shaderIdent, CharArray* rawSource)
{
String fullFileName = fileNameFromIdent(shaderIdent);
#ifdef WIN32
std::ifstream file(fullFileName.ptr());
#else
std::ifstream file(fullFileName.toUtf8().ptr());
#endif
if (file.is_open())
{
std::string line;
while (file.good())
{
getline(file, line);
size_t c;
for (c = 0; c < line.length(); c++)
{
rawSource->push_back(line[c]);
}
rawSource->push_back('\n');
}
file.close();
return true;
}
return ShaderSourceRepository::rawShaderSource(shaderIdent, rawSource);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String ShaderSourceRepositoryFile::fileNameFromIdent(ShaderIdent shaderIdent)
{
String fileName = m_directory + shaderIdentString(shaderIdent) + ".glsl";
return fileName;
}
} // namespace cvf
@@ -0,0 +1,46 @@
//##################################################################################################
//
// 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 "cvfString.h"
#include "cvfShaderSourceRepository.h"
namespace cvf {
//==================================================================================================
//
//
//
//==================================================================================================
class ShaderSourceRepositoryFile : public ShaderSourceRepository
{
public:
ShaderSourceRepositoryFile(const String& directory);
private:
virtual bool rawShaderSource(ShaderIdent shaderIdent, CharArray* rawSource);
String fileNameFromIdent(ShaderIdent shaderIdent);
private:
String m_directory;
};
}
Loaded 100 of 657 files, more files were not shown because too many files have changed in this diff. Show more