mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-14 17:32:13 -05:00
Initial commit of ResInsight version 0.4.8
This commit is contained in:
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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ¤tProgram); // 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
Reference in new issue
Block a user