Initial commit of ResInsight version 0.4.8

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

No files matched your search

@@ -0,0 +1,72 @@
cmake_minimum_required(VERSION 2.8)
project(LibViewing)
# Use our strict compile flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STRICT_CXX_FLAGS}")
include_directories(../LibCore)
include_directories(../LibGeometry)
include_directories(../LibRender)
set(CEE_HEADER_FILES
cvfClipPlaneSet.h
cvfConstantFrameRate.h
cvfCullSettings.h
cvfDynamicUniformSet.h
cvfEffect.h
cvfHitItem.h
cvfHitItemCollection.h
cvfLibViewing.h
cvfLocators.h
cvfManipulatorTrackball.h
cvfModel.h
cvfModelBasicList.h
cvfModelBasicTree.h
cvfPart.h
cvfPartRenderHintCollection.h
cvfPerformanceInfo.h
cvfRayIntersectSpec.h
cvfRenderEngine.h
cvfRendering.h
cvfRenderQueue.h
cvfRenderQueueBuilder.h
cvfRenderQueueSorter.h
cvfRenderSequence.h
cvfScene.h
cvfSingleQuadRenderingGenerator.h
cvfTransform.h
)
set(CEE_SOURCE_FILES
cvfClipPlaneSet.cpp
cvfConstantFrameRate.cpp
cvfCullSettings.cpp
cvfDynamicUniformSet.cpp
cvfEffect.cpp
cvfHitItem.cpp
cvfHitItemCollection.cpp
cvfLocators.cpp
cvfManipulatorTrackball.cpp
cvfModel.cpp
cvfModelBasicList.cpp
cvfModelBasicTree.cpp
cvfPart.cpp
cvfPartRenderHintCollection.cpp
cvfPerformanceInfo.cpp
cvfRayIntersectSpec.cpp
cvfRenderEngine.cpp
cvfRendering.cpp
cvfRenderQueue.cpp
cvfRenderQueueBuilder.cpp
cvfRenderQueueSorter.cpp
cvfRenderSequence.cpp
cvfScene.cpp
cvfSingleQuadRenderingGenerator.cpp
cvfTransform.cpp
)
add_library(${PROJECT_NAME} ${CEE_HEADER_FILES} ${CEE_SOURCE_FILES})
@@ -0,0 +1,139 @@
//##################################################################################################
//
// 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 "cvfClipPlaneSet.h"
#include "cvfUniformSet.h"
#include "cvfCamera.h"
#include "cvfRendering.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::ClipPlaneSet
/// \ingroup Viewing
///
/// A dynamic uniform set used to control model clipping.
///
/// The class is a DynamicUniformSet capable of controlling up to 6 clipping planes. The purpose
/// of the class is provide two uniforms:
/// * u_clipPlaneCount : the number of active clipping planes
/// * u_ecClipPlanes : The clip planes in eye coordinates
///
/// A dynamic uniform is required as the clipping planes needs to be specified in eye coordinates,
/// and thus needs to be updated before each rendering.
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
ClipPlaneSet::ClipPlaneSet()
{
m_planeCountUniform = new UniformInt("u_clipPlaneCount", 0);
m_ecPlanesUniformArray = new UniformFloat("u_ecClipPlanes", Vec4f::ZERO);
m_combinedUniformSet = new UniformSet;
m_combinedUniformSet->setUniform(m_planeCountUniform.p());
m_combinedUniformSet->setUniform(m_ecPlanesUniformArray.p());
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
ClipPlaneSet::~ClipPlaneSet()
{
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of planes currently specified
//--------------------------------------------------------------------------------------------------
size_t ClipPlaneSet::planeCount() const
{
return m_wcPlanes.size();
}
//--------------------------------------------------------------------------------------------------
/// Add a clipping plane. Note that max 6 planes are supported
//--------------------------------------------------------------------------------------------------
void ClipPlaneSet::addPlane(const Plane& plane)
{
CVF_ASSERT(planeCount() < 6);
m_wcPlanes.push_back(plane);
}
//--------------------------------------------------------------------------------------------------
/// Remove all specified clipping planes
//--------------------------------------------------------------------------------------------------
void ClipPlaneSet::clear()
{
m_wcPlanes.clear();
}
//--------------------------------------------------------------------------------------------------
/// Pre-render update to transform the clipping planes into the correct eye coordinates.
//--------------------------------------------------------------------------------------------------
void ClipPlaneSet::update(Rendering* rendering)
{
const cvf::Camera* cam = rendering->camera();
CVF_ASSERT(cam);
const Mat4d& vm = cam->viewMatrix();
size_t planeCount = m_wcPlanes.size();
Vec4fArray planeArray;
if (planeCount > 0)
{
planeArray.resize(planeCount);
size_t i;
for (i = 0; i < planeCount; i++)
{
Plane ecPlane(m_wcPlanes[i]);
ecPlane.transform(vm);
Vec4d planeVec(ecPlane.A(), ecPlane.B(), ecPlane.C(), ecPlane.D());
planeArray[i] = Vec4f(planeVec);
}
}
else
{
// Insert a dummy
planeArray.resize(1);
planeArray[0] = Vec4f::ZERO;
}
m_planeCountUniform->set(static_cast<int>(planeCount));
m_ecPlanesUniformArray->setArray(planeArray);
}
//--------------------------------------------------------------------------------------------------
/// Get the combined uniform set consisting of the two uniforms u_clipPlaneCount and u_ecClipPlanes
//--------------------------------------------------------------------------------------------------
UniformSet* ClipPlaneSet::uniformSet()
{
return m_combinedUniformSet.p();
}
} // namespace cvf
@@ -0,0 +1,55 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfPlane.h"
#include "cvfUniform.h"
#include "cvfDynamicUniformSet.h"
#include <vector>
namespace cvf {
//==================================================================================================
//
// ClipPlaneSet
//
//==================================================================================================
class ClipPlaneSet : public DynamicUniformSet
{
public:
ClipPlaneSet();
~ClipPlaneSet();
size_t planeCount() const;
void addPlane(const Plane& plane);
void clear();
virtual void update(Rendering* rendering);
virtual UniformSet* uniformSet();
private:
std::vector<Plane> m_wcPlanes; // Planes in world coordinates
ref<UniformInt> m_planeCountUniform; // Uniform holding the plane count
ref<UniformFloat> m_ecPlanesUniformArray; // Uniform array holding one vec4 for each plane
ref<UniformSet> m_combinedUniformSet; // Uniform set containing the two uniforms
};
}
@@ -0,0 +1,282 @@
//##################################################################################################
//
// 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 "cvfConstantFrameRate.h"
#include "cvfTrace.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::ConstantFrameRate
/// \ingroup Viewing
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ConstantFrameRate::ConstantFrameRate()
{
m_targetFrameRate = 10.0;
m_minNumPartsToDraw = 1;
m_enableDistanceSorting = false;
m_numPartsToDraw = -1.0;
m_pixelSizeCullingWasOn = false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ConstantFrameRate::setTargetFrameRate(double targetFrameRate)
{
CVF_ASSERT(targetFrameRate >= 0);
m_targetFrameRate = targetFrameRate;
if (m_targetFrameRate < 0) m_targetFrameRate = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ConstantFrameRate::setMinNumPartsToDraw(int minNumParts)
{
CVF_ASSERT(minNumParts >= 1);
m_minNumPartsToDraw = minNumParts;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ConstantFrameRate::enableDistanceSorting(bool enableDistanceSorting)
{
m_enableDistanceSorting = enableDistanceSorting;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double ConstantFrameRate::targetFrameRate() const
{
return m_targetFrameRate;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int ConstantFrameRate::minNumPartsToDraw() const
{
return m_minNumPartsToDraw;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ConstantFrameRate::isDistanceSortingEnabled() const
{
return m_enableDistanceSorting;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ConstantFrameRate::attachRendering(Rendering* rendering)
{
if (rendering == m_rendering.p()) return;
if (m_rendering.notNull())
{
m_rendering->setRenderQueueSorter(m_previousSorter.p());
m_rendering->clearMaxNumPartsToDraw();
m_rendering->cullSettings()->enablePixelSizeCulling(m_pixelSizeCullingWasOn);
m_rendering = NULL;
}
if (rendering)
{
m_previousSorter = rendering->renderQueueSorter();
m_pixelSizeCullingWasOn = rendering->cullSettings()->isPixelSizeCullingEnabled();
m_rendering = rendering;
m_rendering->clearMaxNumPartsToDraw();
RenderQueueSorterTargetFramerate* rqs = new RenderQueueSorterTargetFramerate;
m_rendering->setRenderQueueSorter(rqs);
// Currently, we need to enable pixel size culling in order to get CeeViz to
// compute the screen projected areas of the part's bounding boxes
m_rendering->cullSettings()->enablePixelSizeCulling(true);
m_numPartsToDraw = -1.0;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Rendering* ConstantFrameRate::attachedRendering()
{
return m_rendering.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ConstantFrameRate::adjust(double currentFrameRate)
{
CVF_ASSERT(m_rendering.notNull());
if (m_rendering.isNull()) return;
const int maxNumPartsToDraw = 10000000;
const int maxNumPartsToDistanceSort = 1000;
const double lastDrawTime = (currentFrameRate > 0) ? 1.0/currentFrameRate : 999.0;
const double targetDrawTime = (m_targetFrameRate > 0) ? 1.0/m_targetFrameRate : 999.0;
// Initialize if this is first call
if (m_numPartsToDraw < 0)
{
PerformanceInfo perfInfo = m_rendering->performanceInfo();
m_numPartsToDraw = static_cast<double>(perfInfo.renderedPartsCount);
if (m_numPartsToDraw < m_minNumPartsToDraw) m_numPartsToDraw = m_minNumPartsToDraw;
}
double numPartsToDistanceSort = 0;
double absDiff = Math::abs(lastDrawTime - targetDrawTime);
double fractionDiff = absDiff/targetDrawTime;
if (fractionDiff > 0.05)
{
if (lastDrawTime > targetDrawTime)
{
// We need fewer parts!!
// Ratio always > 1
double ratio = lastDrawTime/targetDrawTime;
m_numPartsToDraw = m_numPartsToDraw/(1 + 0.5*(ratio - 1));
if (m_numPartsToDraw < m_minNumPartsToDraw) m_numPartsToDraw = m_minNumPartsToDraw;
}
else
{
// We need more parts!!
// Ratio always <= 1
double ratio = lastDrawTime/targetDrawTime;
m_numPartsToDraw = m_numPartsToDraw/(0.5*ratio);
}
// Unlikely that we'll ever exceed max of 10 mill parts
if (m_numPartsToDraw > maxNumPartsToDraw) m_numPartsToDraw = maxNumPartsToDraw;
}
if (m_enableDistanceSorting)
{
numPartsToDistanceSort = 0.2*m_numPartsToDraw;
if (numPartsToDistanceSort > maxNumPartsToDistanceSort) numPartsToDistanceSort = maxNumPartsToDistanceSort;
}
Trace::show("m_numPartsToDraw=%f numPartsToDistanceSort=%f", m_numPartsToDraw, numPartsToDistanceSort);
RenderQueueSorterTargetFramerate* rqs = dynamic_cast<RenderQueueSorterTargetFramerate*>(m_rendering->renderQueueSorter());
if (rqs)
{
rqs->setMaxNumPartsToDraw(static_cast<uint>(m_numPartsToDraw + 0.5));
rqs->setNumPartsToDistanceSort(static_cast<uint>(numPartsToDistanceSort + 0.5));
}
m_rendering->setMaxNumPartsToDraw(static_cast<size_t>(m_numPartsToDraw + 0.5));
}
/*
double g_targetDrawTime = 0.05;
double g_numDistSorted = 1000;
double g_numPartsToDRaw = 5000;
void AdjustSettingsBasedOnTargetDrawTime(double lastFrameDrawTime, Rendering* rendering)
{
if (g_targetDrawTime <= 0) return;
double absDiff = abs(lastFrameDrawTime - g_targetDrawTime);
double fractionDiff = absDiff/g_targetDrawTime;
if (fractionDiff > 0.05)
{
if (lastFrameDrawTime > g_targetDrawTime)
{
// Ratio always > 1
double ratio = lastFrameDrawTime/g_targetDrawTime;
g_numPartsToDRaw = g_numPartsToDRaw/(1 + 0.5*(ratio - 1));
if (g_numPartsToDRaw < 10) g_numPartsToDRaw = 10;
}
else
{
// We need more parts!!
// Ratio always <= 1
double ratio = lastFrameDrawTime/g_targetDrawTime;
g_numPartsToDRaw = g_numPartsToDRaw/(0.5*ratio);
}
if (g_numPartsToDRaw > 10000000)
{
g_numPartsToDRaw = 10000000;
}
g_numDistSorted = (int)(0.2*g_numPartsToDRaw);
if (g_numDistSorted < 1) g_numDistSorted = 1;
}
Trace::show("g_numPartsToDRaw=%f g_numDistSorted=%f", g_numPartsToDRaw, g_numDistSorted);
RenderQueueSorterTargetFramerate* rqs = dynamic_cast<RenderQueueSorterTargetFramerate*>(rendering->renderQueueSorter());
if (rqs)
{
rqs->setMaxNumPartsToDraw(static_cast<size_t>(g_numPartsToDRaw + 0.5));
rqs->setNumPartsToDistanceSort(static_cast<size_t>(g_numDistSorted + 0.5));
}
rendering->setMaxNumPartsToDraw(static_cast<size_t>(g_numPartsToDRaw));
}
*/
} // 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 "cvfRendering.h"
#include "cvfRenderQueueSorter.h"
namespace cvf {
//==================================================================================================
//
//
//
//==================================================================================================
class ConstantFrameRate : public Object
{
public:
ConstantFrameRate();
void setTargetFrameRate(double targetFrameRate);
void setMinNumPartsToDraw(int minNumParts);
void enableDistanceSorting(bool enableDistanceSorting);
double targetFrameRate() const;
int minNumPartsToDraw() const;
bool isDistanceSortingEnabled() const;
void attachRendering(Rendering* rendering);
Rendering* attachedRendering();
void adjust(double currentFrameRate);
private:
double m_targetFrameRate; // Target frame rate in frames per second
int m_minNumPartsToDraw; // The lower bound on the number of parts we're allowed to draw
bool m_enableDistanceSorting; // If true, we'll try and do distance sorting for the colest 10% of the parts
double m_numPartsToDraw; // Calculated number of parts to draw. This is the value we'll adjust
ref<Rendering> m_rendering; // The attached rendering
bool m_pixelSizeCullingWasOn;
ref<RenderQueueSorter> m_previousSorter; // The sorter that was current in the rendering when it was attached
};
}
@@ -0,0 +1,103 @@
//##################################################################################################
//
// 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 "cvfCullSettings.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::CullSettings
/// \ingroup Viewing
///
/// A class for storing settings regarding culling of parts
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CullSettings::CullSettings()
: m_viewFrustumCulling(true),
m_pixelSizeCulling(false),
m_pixelSizeCullingAreaThreshold(80)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CullSettings::enableViewFrustumCulling(bool enable)
{
m_viewFrustumCulling = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool CullSettings::isViewFrustumCullingEnabled() const
{
return m_viewFrustumCulling;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CullSettings::enablePixelSizeCulling(bool enable)
{
m_pixelSizeCulling = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool CullSettings::isPixelSizeCullingEnabled() const
{
return m_pixelSizeCulling;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CullSettings::setPixelSizeCullingAreaThreshold(double pixelArea)
{
m_pixelSizeCullingAreaThreshold = pixelArea;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double CullSettings::pixelSizeCullingAreaThreshold() const
{
return m_pixelSizeCullingAreaThreshold;
}
} // 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
namespace cvf {
//==================================================================================================
//
// CullSettings
//
//==================================================================================================
class CullSettings
{
public:
CullSettings();
void enableViewFrustumCulling(bool enable);
bool isViewFrustumCullingEnabled() const;
void enablePixelSizeCulling(bool enable);
bool isPixelSizeCullingEnabled() const;
void setPixelSizeCullingAreaThreshold(double pixelArea);
double pixelSizeCullingAreaThreshold() const;
private:
bool m_viewFrustumCulling; // Enable/disable view frustum culling
bool m_pixelSizeCulling; // Enable/disable pixel size culling
double m_pixelSizeCullingAreaThreshold; // Objects where the bounding sphere projects to an area smaller than this value will be culled.
};
}
@@ -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.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfDynamicUniformSet.h"
#include "cvfRendering.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::DynamicUniformSet
/// \ingroup Viewing
///
///
///
//==================================================================================================
//------------------------------------------------------------------------------------------------
///
//------------------------------------------------------------------------------------------------
DynamicUniformSet::DynamicUniformSet()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
DynamicUniformSet::~DynamicUniformSet()
{
}
} // namespace cvf
@@ -0,0 +1,45 @@
//##################################################################################################
//
// 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 UniformSet;
class Rendering;
//==================================================================================================
//
// DynamicUniformSet
//
//==================================================================================================
class DynamicUniformSet : public Object
{
public:
DynamicUniformSet();
virtual ~DynamicUniformSet();
virtual UniformSet* uniformSet() = 0;
virtual void update(Rendering* rendering) = 0; // pre-render update
};
}
@@ -0,0 +1,286 @@
//##################################################################################################
//
// 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 "cvfEffect.h"
#include "cvfTexture.h"
#include "cvfShaderProgram.h"
#include "cvfUniformSet.h"
#include "cvfRenderStateSet.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#include "cvfTexture2D_FF.h"
#endif
namespace cvf {
//==================================================================================================
///
/// \class cvf::Effect
/// \ingroup Viewing
///
/// The effect class defines how a drawable should be rendered. (Shader program, uniforms, OpenGL state etc)
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Effect::Effect()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Effect::~Effect()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Effect::setShaderProgram(ShaderProgram* shaderProgram)
{
m_shaderProgram = shaderProgram;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ShaderProgram* Effect::shaderProgram()
{
return m_shaderProgram.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const ShaderProgram* Effect::shaderProgram() const
{
return m_shaderProgram.p();
}
//--------------------------------------------------------------------------------------------------
/// Set or add a uniform
///
/// Any existing uniform with the same name will be replaced
//--------------------------------------------------------------------------------------------------
void Effect::setUniform(Uniform* uniform)
{
CVF_ASSERT(uniform);
if (m_uniformSet.isNull())
{
m_uniformSet = new UniformSet;
}
CVF_ASSERT(m_uniformSet.notNull());
m_uniformSet->setUniform(uniform);
}
//--------------------------------------------------------------------------------------------------
/// Set all uniforms contained in \a sourceUniformSet
//--------------------------------------------------------------------------------------------------
void Effect::setUniformsFromUniformSet(UniformSet* sourceUniformSet)
{
size_t uniformCount = sourceUniformSet->count();
for (size_t i = 0; i < uniformCount; i++)
{
setUniform(sourceUniformSet->uniform(i));
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Effect::setUniformSet(UniformSet* uniformSet)
{
m_uniformSet = uniformSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const UniformSet* Effect::uniformSet() const
{
return m_uniformSet.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
UniformSet* Effect::uniformSet()
{
return m_uniformSet.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Effect::setRenderState(RenderState* renderState)
{
if (m_renderStateSet.isNull())
{
m_renderStateSet = new RenderStateSet;
}
CVF_ASSERT(m_renderStateSet.notNull());
m_renderStateSet->setRenderState(renderState);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderState* Effect::renderStateOfType(RenderState::Type type)
{
if (m_renderStateSet.notNull())
{
return m_renderStateSet->renderStateOfType(type);
}
else
{
return NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RenderState* Effect::renderStateOfType(RenderState::Type type) const
{
if (m_renderStateSet.notNull())
{
return m_renderStateSet->renderStateOfType(type);
}
else
{
return NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Effect::removeRenderState(RenderState::Type type)
{
if (m_renderStateSet.notNull())
{
RenderState* rs = m_renderStateSet->renderStateOfType(type);
if (rs)
{
m_renderStateSet->removeRenderState(rs);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Effect::setRenderStateSet(RenderStateSet* renderStateSet)
{
m_renderStateSet = renderStateSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderStateSet* Effect::renderStateSet()
{
return m_renderStateSet.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RenderStateSet* Effect::renderStateSet() const
{
return m_renderStateSet.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Effect::deleteOrReleaseOpenGLResources(OpenGLContext* oglContext)
{
if (m_shaderProgram.notNull())
{
m_shaderProgram->deleteProgram(oglContext);
uint numShaders = m_shaderProgram->shaderCount();
uint i;
for (i = 0; i < numShaders; i++)
{
Shader* shader = m_shaderProgram->shader(i);
shader->deleteShader(oglContext);
}
}
if (m_renderStateSet.notNull())
{
TextureBindings* textureBindings = static_cast<TextureBindings*>(m_renderStateSet->renderStateOfType(RenderState::TEXTURE_BINDINGS));
if (textureBindings)
{
int bindingCount = textureBindings->bindingCount();
int i;
for (i = 0; i < bindingCount; i++)
{
Texture* texture = textureBindings->texture(i);
texture->deleteTexture(oglContext);
}
}
#ifndef CVF_OPENGL_ES
TextureMapping_FF* textureMapping = static_cast<TextureMapping_FF*>(m_renderStateSet->renderStateOfType(RenderState::TEXTURE_MAPPING_FF));
if (textureMapping)
{
Texture2D_FF* texture = textureMapping->texture();
if (texture)
{
texture->deleteTexture(oglContext);
}
}
#endif
}
}
} // namespace cvf
@@ -0,0 +1,73 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfObject.h"
#include "cvfRenderState.h"
namespace cvf {
class ShaderProgram;
class Uniform;
class UniformSet;
class RenderStateSet;
class OpenGLContext;
//==================================================================================================
//
// The effect class defines how the drawable should be rendered. (Shader program, uniforms, OpenGL state etc)
//
//==================================================================================================
class Effect : public Object
{
public:
Effect();
~Effect();
void setShaderProgram(ShaderProgram* shaderProgram);
ShaderProgram* shaderProgram();
const ShaderProgram* shaderProgram() const;
void setUniform(Uniform* uniform);
void setUniformsFromUniformSet(UniformSet* sourceUniformSet);
void setUniformSet(UniformSet* uniformSet);
UniformSet* uniformSet();
const UniformSet* uniformSet() const;
void setRenderState(RenderState* renderState);
RenderState* renderStateOfType(RenderState::Type type);
const RenderState* renderStateOfType(RenderState::Type type) const;
void removeRenderState(RenderState::Type type);
void setRenderStateSet(RenderStateSet* renderStateSet);
RenderStateSet* renderStateSet();
const RenderStateSet* renderStateSet() const;
void deleteOrReleaseOpenGLResources(OpenGLContext* oglContext);
private:
ref<ShaderProgram> m_shaderProgram;
ref<UniformSet> m_uniformSet;
ref<RenderStateSet> m_renderStateSet;
};
}
@@ -0,0 +1,112 @@
//##################################################################################################
//
// 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 "cvfHitItem.h"
#include "cvfPart.h"
#include "cvfHitDetail.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::HitItem
/// \ingroup Geometry
///
/// This class contains the result of an intersection between a ray and a part.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
HitItem::HitItem(double distanceAlongRay, const Vec3d& intersectionPoint)
: m_distanceAlongRay(distanceAlongRay),
m_intersectionPoint(intersectionPoint)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
HitItem::~HitItem()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double HitItem::distanceAlongRay() const
{
return m_distanceAlongRay;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Vec3d& HitItem::intersectionPoint() const
{
return m_intersectionPoint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Part* HitItem::part() const
{
return m_part.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void HitItem::setPart(const Part* part)
{
m_part = part;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void HitItem::setDetail(HitDetail* detail)
{
m_detail = detail;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const HitDetail* HitItem::detail() const
{
return m_detail.p();
}
} // namespace cvf
@@ -0,0 +1,58 @@
//##################################################################################################
//
// 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 Part;
class HitDetail;
//==================================================================================================
//
// HitItem
//
//==================================================================================================
class HitItem : public Object
{
public:
HitItem(double distanceAlongRay, const Vec3d& intersectionPoint);
~HitItem();
double distanceAlongRay() const;
const Vec3d& intersectionPoint() const;
void setPart(const Part* part);
const Part* part() const;
void setDetail(HitDetail* detail);
const HitDetail* detail() const;
private:
double m_distanceAlongRay; // Distance from ray origin
Vec3d m_intersectionPoint;
cref<Part> m_part; // Reference to the part that was hit
ref<HitDetail> m_detail; // Optional detail on the intersection
};
}
@@ -0,0 +1,145 @@
//##################################################################################################
//
// 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 "cvfHitItemCollection.h"
#include <algorithm>
namespace cvf {
//==================================================================================================
///
/// \class cvf::HitItemCollection
/// \ingroup Viewing
///
/// This class is used to aggregate hits during picking. The items can be sorted by distance
/// with the sort() method.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
HitItemCollection::HitItemCollection()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
HitItemCollection::~HitItemCollection()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void HitItemCollection::add(HitItem* item)
{
m_items.push_back(item);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t HitItemCollection::count() const
{
return m_items.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
HitItem* HitItemCollection::item(size_t index)
{
CVF_ASSERT(index < count());
return m_items.at(index).p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const HitItem* HitItemCollection::item(size_t index) const
{
CVF_ASSERT(index < count());
return m_items.at(index).p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
HitItem* HitItemCollection::firstItem()
{
if (m_items.size() > 0)
{
return m_items.at(0).p();
}
else
{
return NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const HitItem* HitItemCollection::firstItem() const
{
if (m_items.size() > 0)
{
return m_items.at(0).p();
}
else
{
return NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void HitItemCollection::sort()
{
std::sort(m_items.begin(), m_items.end(), compareFunc);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool HitItemCollection::compareFunc(const ref<HitItem>& a, const ref<HitItem>& b)
{
return a->distanceAlongRay() < b->distanceAlongRay();
}
} // namespace cvf
@@ -0,0 +1,58 @@
//##################################################################################################
//
// 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 "cvfHitItem.h"
#include <vector>
namespace cvf {
//==================================================================================================
//
//
//
//==================================================================================================
class HitItemCollection : Object
{
public:
HitItemCollection();
~HitItemCollection();
void add(HitItem* item);
size_t count() const;
HitItem* item(size_t index);
const HitItem* item(size_t index) const;
HitItem* firstItem();
const HitItem* firstItem() const;
void sort();
private:
static bool compareFunc(const ref<HitItem>& a, const ref<HitItem>& b);
private:
std::vector<ref<HitItem> > m_items;
};
}
@@ -0,0 +1,49 @@
//##################################################################################################
//
// 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 Viewing Viewing module
/// @}
#include "cvfClipPlaneSet.h"
#include "cvfConstantFrameRate.h"
#include "cvfDynamicUniformSet.h"
#include "cvfEffect.h"
#include "cvfHitItem.h"
#include "cvfHitItemCollection.h"
#include "cvfLocators.h"
#include "cvfManipulatorTrackball.h"
#include "cvfModel.h"
#include "cvfModelBasicList.h"
#include "cvfModelBasicTree.h"
#include "cvfPart.h"
#include "cvfPartRenderHintCollection.h"
#include "cvfPerformanceInfo.h"
#include "cvfRayIntersectSpec.h"
#include "cvfRenderEngine.h"
#include "cvfRendering.h"
#include "cvfRenderQueue.h"
#include "cvfRenderQueueSorter.h"
#include "cvfScene.h"
#include "cvfSingleQuadRenderingGenerator.h"
#include "cvfTransform.h"
#include "cvfRenderSequence.h"
@@ -0,0 +1,319 @@
//##################################################################################################
//
// 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 "cvfLocators.h"
#include "cvfCamera.h"
#include "cvfViewport.h"
#include "cvfRay.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::LocatorTranslateOnPlane
/// \ingroup Viewing
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
LocatorTranslateOnPlane::LocatorTranslateOnPlane(Camera* camera)
: m_camera(camera),
m_plane(0, 0, 1, 0),
m_pos(0, 0, 0),
m_lastPos(0, 0, 0)
{
CVF_ASSERT(camera);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
LocatorTranslateOnPlane::~LocatorTranslateOnPlane()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void LocatorTranslateOnPlane::setPosition(const Vec3d& position, const Vec3d& planeNormal)
{
m_pos = position;
m_plane.setFromPointAndNormal(position, planeNormal);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Vec3d LocatorTranslateOnPlane::position() const
{
return m_pos;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void LocatorTranslateOnPlane::start(int winCoordX, int winCoordY)
{
CVF_ASSERT(m_camera.notNull());
ref<Ray> ray = m_camera->rayFromWinCoord(winCoordX, winCoordY);
Vec3d isect(0, 0, 0);
ray->planeIntersect(m_plane, &isect);
m_lastPos = isect;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool LocatorTranslateOnPlane::update(int winCoordX, int winCoordY)
{
CVF_ASSERT(m_camera.notNull());
Vec3d oldPos = m_pos;
ref<Ray> ray = m_camera->rayFromWinCoord(winCoordX, winCoordY);
Vec3d isect(0, 0, 0);
if (ray->planeIntersect(m_plane, &isect))
{
Vec3d delta = (isect - m_lastPos);
m_plane.projectVector(delta, &delta);
m_pos += delta;
m_lastPos = isect;
}
if (m_pos == oldPos)
{
return false;
}
else
{
return true;
}
}
//==================================================================================================
///
/// \class cvf::LocatorPanWalkRotate
/// \ingroup Viewing
///
/// Currently, rotate is not supported
///
//==================================================================================================
LocatorPanWalkRotate::LocatorPanWalkRotate(Camera* camera)
: m_camera(camera),
m_operation(PAN),
m_pos(0, 0, 0),
m_lastWinPosX(0),
m_lastWinPosY(0)
{
CVF_ASSERT(camera);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
LocatorPanWalkRotate::~LocatorPanWalkRotate()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void LocatorPanWalkRotate::setOperation(Operation op)
{
m_operation = op;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void LocatorPanWalkRotate::setPosition(const Vec3d& position)
{
m_pos = position;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Vec3d LocatorPanWalkRotate::position() const
{
return m_pos;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void LocatorPanWalkRotate::start(int winCoordX, int winCoordY)
{
m_lastWinPosX = winCoordX;
m_lastWinPosY = winCoordY;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool LocatorPanWalkRotate::update(int winCoordX, int winCoordY)
{
CVF_ASSERT(m_camera.notNull());
if (winCoordX == m_lastWinPosX && winCoordY == m_lastWinPosY) return false;
const double vpPixSizeX = m_camera->viewport()->width();
const double vpPixSizeY = m_camera->viewport()->height();
if (vpPixSizeX <= 0 || vpPixSizeY <= 0) return false;
// Normalized movement in screen plane
const double tx = (winCoordX - m_lastWinPosX)/vpPixSizeX;
const double ty = (winCoordY - m_lastWinPosY)/vpPixSizeY;
Vec3d oldPos = m_pos;
if (m_operation == PAN)
{
updatePan(tx, ty);
}
else if (m_operation == WALK)
{
updateWalk(ty);
}
m_lastWinPosX = winCoordX;
m_lastWinPosY = winCoordY;
if (m_pos == oldPos)
{
return false;
}
else
{
return true;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void LocatorPanWalkRotate::updatePan(double tx, double ty)
{
CVF_ASSERT(m_camera.notNull());
// Viewport size in world coordinates
const double aspect = m_camera->aspectRatio();
const double vpWorldSizeY = m_camera->frontPlaneFrustumHeight();
const double vpWorldSizeX = vpWorldSizeY*aspect;
const Vec3d camUp = m_camera->up();
const Vec3d camRight = m_camera->right();
Camera::ProjectionType projType = m_camera->projection();
if (projType == Camera::PERSPECTIVE)
{
// Compute distance from camera to point projected onto camera forward direction
const Vec3d camPos = m_camera->position();
const Vec3d camDir = m_camera->direction();
const Vec3d vDiff = m_pos - camPos;
const double camPointDist = Math::abs(camDir*vDiff);
const double nearPlane = m_camera->nearPlane();
Vec3d vX = camRight*((tx*vpWorldSizeX)/nearPlane)*camPointDist;
Vec3d vY = -camUp*((ty*vpWorldSizeY)/nearPlane)*camPointDist;
Vec3d translation = vX + vY;
m_pos += translation;
}
else if (projType == Camera::ORTHO)
{
Vec3d vX = camRight*tx*vpWorldSizeX;
Vec3d vY = -camUp*ty*vpWorldSizeY;
Vec3d translation = vX + vY;
m_pos += translation;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void LocatorPanWalkRotate::updateWalk(double ty)
{
CVF_ASSERT(m_camera.notNull());
const double vpWorldSizeY = m_camera->frontPlaneFrustumHeight();
const Vec3d camDir = m_camera->direction();
Camera::ProjectionType projType = m_camera->projection();
// This is the distance that we will move the point in response to a full (whole viewport) movement of the mouse
// Might need to revisit this to determine target distance
// In that case it might be an idea to look at the trackball manipulator
double targetDist = 0;
if (projType == Camera::PERSPECTIVE)
{
// Compute distance from camera to point projected onto camera forward direction
const Vec3d camPos = m_camera->position();
const Vec3d vDiff = m_pos - camPos;
const double camPointDist = Math::abs(camDir*vDiff);
targetDist = camPointDist;
}
else if (projType == Camera::ORTHO)
{
targetDist = vpWorldSizeY;
}
double moveDist = ty*targetDist;
Vec3d translation = camDir*moveDist;
m_pos += translation;
}
} // namespace cvf
@@ -0,0 +1,116 @@
//##################################################################################################
//
// 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 "cvfPlane.h"
namespace cvf {
class Camera;
//==================================================================================================
//
//
//
//==================================================================================================
class Locator : public Object
{
public:
Locator() {};
virtual Vec3d position() const = 0;
virtual void start(int winCoordX, int winCoordY) = 0;
virtual bool update(int winCoordX, int winCoordY) = 0;
};
//==================================================================================================
//
// Locator for translating a point limited by a plane
//
//==================================================================================================
class LocatorTranslateOnPlane : public Locator
{
public:
LocatorTranslateOnPlane(Camera* camera);
~LocatorTranslateOnPlane();
void setPosition(const Vec3d& position, const Vec3d& planeNormal);
virtual Vec3d position() const;
virtual void start(int winCoordX, int winCoordY);
virtual bool update(int winCoordX, int winCoordY);
public:
ref<Camera> m_camera;
Plane m_plane; // Default plane is XY plane
Vec3d m_pos;
Vec3d m_lastPos;
};
//==================================================================================================
//
//
//
//==================================================================================================
class LocatorPanWalkRotate : public Locator
{
public:
enum Operation
{
PAN,
WALK
//ROTATE // TODO
};
public:
LocatorPanWalkRotate(Camera* camera);
~LocatorPanWalkRotate();
void setOperation(Operation op);
void setPosition(const Vec3d& position);
virtual Vec3d position() const;
virtual void start(int winCoordX, int winCoordY);
virtual bool update(int winCoordX, int winCoordY);
private:
void updatePan(double tx, double ty);
void updateWalk(double ty);
private:
ref<Camera> m_camera;
Operation m_operation; // Default operation is PAN
Vec3d m_pos;
int m_lastWinPosX;
int m_lastWinPosY;
};
// Ideas from name discussion regarding other locator classes
//class LocatorTranslateOnLine;
//class LocatorRotateRoundAxis;
}
@@ -0,0 +1,459 @@
//##################################################################################################
//
// 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 "cvfManipulatorTrackball.h"
#include "cvfCamera.h"
#include "cvfViewport.h"
#include <cmath>
#include <cstdlib>
namespace cvf {
//==================================================================================================
///
/// \class cvf::ManipulatorTrackball
/// \ingroup Viewing
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ManipulatorTrackball::ManipulatorTrackball()
{
m_rotationPoint.setZero();
m_activeNavigation = NONE;
m_lastPosX = 0;
m_lastPosY = 0;
m_walkStartCameraPos.setZero();
m_walkSensitivity = 1.0;
m_rotateSensitivity = 1.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ManipulatorTrackball::~ManipulatorTrackball()
{
// Empty destructor to avoid errors with undefined types when cvf::ref's destructor gets called
}
//--------------------------------------------------------------------------------------------------
/// Set the camera that should be manipulated
//--------------------------------------------------------------------------------------------------
void ManipulatorTrackball::setCamera(Camera* camera)
{
m_camera = camera;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ManipulatorTrackball::setRotationPoint(const Vec3d& rotPoint)
{
m_rotationPoint = rotPoint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ManipulatorTrackball::NavigationType ManipulatorTrackball::activeNavigation() const
{
return m_activeNavigation;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ManipulatorTrackball::startNavigation(NavigationType navigationType, int winCoordX, int winCoordY)
{
if (m_camera.isNull()) return;
if (m_activeNavigation == navigationType) return;
m_lastPosX = winCoordX;
m_lastPosY = winCoordY;
// Register camera's starting position for walk
m_walkStartCameraPos = m_camera->position();
m_activeNavigation = navigationType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ManipulatorTrackball::updateNavigation(int winCoordX, int winCoordY)
{
if (m_activeNavigation == PAN)
{
return pan(winCoordX, winCoordY);
}
else if (m_activeNavigation == WALK)
{
return walk(winCoordX, winCoordY);
}
else if (m_activeNavigation == ZOOM)
{
return zoom(winCoordX, winCoordY);
}
else if (m_activeNavigation == ROTATE)
{
return rotate(winCoordX, winCoordY);
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ManipulatorTrackball::endNavigation()
{
m_activeNavigation = NONE;
}
//--------------------------------------------------------------------------------------------------
/// Pan the camera up/down and left/right
///
/// \return Returns true if input caused changes to the camera an false if no changes occurred
//--------------------------------------------------------------------------------------------------
bool ManipulatorTrackball::pan(int posX, int posY)
{
if (m_camera.isNull()) return false;
if (posX == m_lastPosX && posY == m_lastPosY) return false;
const double vpPixSizeX = m_camera->viewport()->width();
const double vpPixSizeY = m_camera->viewport()->height();
if (vpPixSizeX <= 0 || vpPixSizeY <= 0) return false;
// Normalized movement in screen plane
double tx = (posX - m_lastPosX)/vpPixSizeX;
double ty = (posY - m_lastPosY)/vpPixSizeY;
// Viewport size in world coordinates
const double aspect = m_camera->aspectRatio();
const double vpWorldSizeY = m_camera->frontPlaneFrustumHeight();
const double vpWorldSizeX = vpWorldSizeY*aspect;
const Vec3d camUp = m_camera->up();
const Vec3d camRight = m_camera->right();
Vec3d translation(0, 0, 0);
Camera::ProjectionType projType = m_camera->projection();
if (projType == Camera::PERSPECTIVE)
{
const Vec3d camPos = m_camera->position();
const Vec3d camDir = m_camera->direction();
const double nearPlane = m_camera->nearPlane();
// Compute distance from camera to rotation point projected onto camera forward direction
const Vec3d vDiff = m_rotationPoint - camPos;
const double camRotPointDist = Math::abs(camDir*vDiff);
Vec3d vX = camRight*((tx*vpWorldSizeX)/nearPlane)*camRotPointDist;
Vec3d vY = -camUp*((ty*vpWorldSizeY)/nearPlane)*camRotPointDist;
translation = vX + vY;
}
else if (projType == Camera::ORTHO)
{
Vec3d vX = camRight*tx*vpWorldSizeX;
Vec3d vY = -camUp*ty*vpWorldSizeY;
translation = vX + vY;
}
Mat4d viewMat = m_camera->viewMatrix();
viewMat.translatePostMultiply(translation);
m_camera->setViewMatrix(viewMat);
m_lastPosX = posX;
m_lastPosY = posY;
return true;
}
//--------------------------------------------------------------------------------------------------
/// Walk forward backward along the current camera direction
///
/// \return Returns true if input caused changes to the camera an false if no changes occurred
///
/// \remarks As this function moves the camera, it will have no effect when projection is orthographic
/// \todo Needs better control over movement when camera position gets close to the rotation point.
//--------------------------------------------------------------------------------------------------
bool ManipulatorTrackball::walk(int posX, int posY)
{
if (m_camera.isNull()) return false;
if (posX == m_lastPosX && posY == m_lastPosY) return false;
const double vpPixSizeY = m_camera->viewport()->height();
if (vpPixSizeY <= 0) return false;
// !!!!
// Should be a member variable, settable as a ratio of the model bounding box/sphere
const double minWalkTargetDistance = 1.0;
const double ty = (posY - m_lastPosY)/vpPixSizeY;
// Determine target distance to travel along camera direction
// This is the distance that we will move the camera in response to a full (whole viewport) movement of the mouse
const Vec3d camDir = m_camera->direction();
const Vec3d vDiff = m_rotationPoint - m_walkStartCameraPos;
double targetDist = Math::abs(camDir*vDiff);
if (targetDist < minWalkTargetDistance) targetDist = minWalkTargetDistance;
// Figure out movement to append
double moveDist = ty*targetDist*m_walkSensitivity;
Vec3d moveVec = camDir*moveDist;
Mat4d viewMat = m_camera->viewMatrix();
viewMat.translatePostMultiply(moveVec);
m_camera->setViewMatrix(viewMat);
m_lastPosX = posX;
m_lastPosY = posY;
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool ManipulatorTrackball::zoom(int posX, int posY)
{
if (m_camera.isNull()) return false;
if (posX == m_lastPosX && posY == m_lastPosY) return false;
const double vpPixSizeY = m_camera->viewport()->height();
if (vpPixSizeY <= 0) return false;
const double ty = (posY - m_lastPosY)/vpPixSizeY;
const double frustumHeight = m_camera->frontPlaneFrustumHeight();
double newFrustumHeight = frustumHeight;
if (ty >= 0.0f) newFrustumHeight = frustumHeight*(1 + ty);
else newFrustumHeight = frustumHeight/(1 - ty);
const double nearPlane = m_camera->nearPlane();
const double farPlane = m_camera->farPlane();
Camera::ProjectionType projType = m_camera->projection();
if (projType == Camera::PERSPECTIVE)
{
double fovY = 2*atan((newFrustumHeight/2)/nearPlane);
if (fovY > 0)
{
m_camera->setProjectionAsPerspective(Math::toDegrees(fovY), nearPlane, farPlane);
}
}
else if (projType == Camera::ORTHO)
{
if (newFrustumHeight > 0)
{
m_camera->setProjectionAsOrtho(newFrustumHeight, nearPlane, farPlane);
}
}
m_lastPosX = posX;
m_lastPosY = posY;
return true;
}
//--------------------------------------------------------------------------------------------------
/// Rotate
///
/// \return Returns true if input caused changes to the camera an false if no changes occurred
//--------------------------------------------------------------------------------------------------
bool ManipulatorTrackball::rotate(int posX, int posY)
{
if (m_camera.isNull()) return false;
if (posX == m_lastPosX && posY == m_lastPosY) return false;
const double vpPixSizeX = m_camera->viewport()->width();
const double vpPixSizeY = m_camera->viewport()->height();
if (vpPixSizeX <= 0 || vpPixSizeY <= 0) return false;
// Scale the new/last positions to the range [-1.0, 1.0]
double newPosX = 2.0*(posX/vpPixSizeX) - 1.0;
double newPosY = 2.0*(posY/vpPixSizeY) - 1.0;
double lastPosX = 2.0*(m_lastPosX/vpPixSizeX) - 1.0;
double lastPosY = 2.0*(m_lastPosY/vpPixSizeY) - 1.0;
Mat4d viewMat = m_camera->viewMatrix();
// Compute rotation quaternion
Quatd rotQuat = trackballRotation(lastPosX, -lastPosY, newPosX, -newPosY, viewMat, m_rotateSensitivity);
// Update navigation by modifying the view matrix
Mat4d rotMatr = rotQuat.toMatrix4();
rotMatr.translatePostMultiply(-m_rotationPoint);
rotMatr.translatePreMultiply(m_rotationPoint);
viewMat = viewMat*rotMatr;
m_camera->setViewMatrix(viewMat);
m_lastPosX = posX;
m_lastPosY = posY;
return true;
}
//--------------------------------------------------------------------------------------------------
/// Compute quaternion rotation
///
/// \param oldPosX x coordinate of the last position of the mouse, in the range [-1.0, 1.0]
/// \param oldPosY y coordinate of the last position of the mouse, in the range [-1.0, 1.0]
/// \param newPosX x coordinate of current position of the mouse, in the range [-1.0, 1.0]
/// \param newPosY y coordinate of current position of the mouse, in the range [-1.0, 1.0]
/// \param currViewMatrix Current transformation matrix. The inverse is used when calculating the rotation
/// \param sensitivityFactor Mouse sensitivity factor
///
/// Simulate a track-ball. Project the points onto the virtual trackball, then figure out the axis
/// of rotation. This is a deformed trackball-- is a trackball in the center, but is deformed into a
/// hyperbolic sheet of rotation away from the center.
//--------------------------------------------------------------------------------------------------
Quatd ManipulatorTrackball::trackballRotation(double oldPosX, double oldPosY, double newPosX, double newPosY, const Mat4d& currViewMatrix, double sensitivityFactor)
{
// This particular function was chosen after trying out several variations.
// Implemented by Gavin Bell, lots of ideas from Thant Tessman and the August '88
// issue of Siggraph's "Computer Graphics," pp. 121-129.
// This size should really be based on the distance from the center of rotation to the point on
// the object underneath the mouse. That point would then track the mouse as closely as possible.
const double TRACKBALL_RADIUS = 0.8f;
// Clamp to valid range
oldPosX = Math::clamp(oldPosX, -1.0, 1.0);
oldPosY = Math::clamp(oldPosY, -1.0, 1.0);
newPosX = Math::clamp(newPosX, -1.0, 1.0);
newPosY = Math::clamp(newPosY, -1.0, 1.0);
// First, figure out z-coordinates for projection of P1 and P2 to deformed sphere
Vec3d p1 = projectToSphere(TRACKBALL_RADIUS, oldPosX, oldPosY);
Vec3d p2 = projectToSphere(TRACKBALL_RADIUS, newPosX, newPosY);
// Axis of rotation is the cross product of P1 and P2
Vec3d a = p1 ^ p2;
// Figure out how much to rotate around that axis.
Vec3d d = p1 - p2;
double t = d.length()/(2.0*TRACKBALL_RADIUS);
// Avoid problems with out-of-control values...
t = Math::clamp(t, -1.0, 1.0);
double phi = 2.0*asin(t);
// Scale by sensitivity factor
phi *= sensitivityFactor;
// Use inverted matrix to find rotation axis
Mat4d invMatr = currViewMatrix.getInverted();
a.transformVector(invMatr);
// Get quaternion to be returned by pointer
Quatd quat = Quatd::fromAxisAngle(a, phi);
return quat;
}
//--------------------------------------------------------------------------------------------------
/// Project an x,y pair onto sphere
///
/// \param radius Radius of the sphere
/// \param posX X coordinate
/// \param posY Y coordinate
///
/// \return Vector containing the projected point
///
/// Projects the x,y pair onto a sphere with the given radius \b or a hyperbolic sheet if we
/// are away from the center of the sphere.
//--------------------------------------------------------------------------------------------------
Vec3d ManipulatorTrackball::projectToSphere(double radius, double posX, double posY)
{
double d = sqrt(posX*posX + posY*posY);
if (d < radius*SQRT1_2_D)
{
// Inside sphere
double projectedZ = sqrt(radius*radius - d*d);
return Vec3d(posX, posY, projectedZ);
}
else
{
// On hyperbola
double t = radius/SQRT2_D;
double projectedZ = t*t/d;
return Vec3d(posX, posY, projectedZ);
}
}
//--------------------------------------------------------------------------------------------------
/// Repositions and orients the camera to view the rotation point along the
/// direction "alongDirection". The distance to the rotation point is maintained.
///
//--------------------------------------------------------------------------------------------------
void ManipulatorTrackball::setView( const Vec3d& alongDirection, const Vec3d& upDirection )
{
if (m_camera.isNull()) return;
Vec3d dir = alongDirection;
if (!dir.normalize()) return;
Vec3d up = upDirection;
if(!up.normalize()) up = Vec3d::Z_AXIS;
if((up * dir) < 1e-2) up = dir.perpendicularVector();
Vec3d cToE = m_camera->position() - m_rotationPoint;
Vec3d newEye = m_rotationPoint - cToE.length() * dir;
m_camera->setFromLookAt(newEye, m_rotationPoint, upDirection);
}
} // namespace cvf
@@ -0,0 +1,83 @@
//##################################################################################################
//
// 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 "cvfQuat.h"
#include "cvfMatrix4.h"
namespace cvf {
class Camera;
//==================================================================================================
//
//
//
//==================================================================================================
class ManipulatorTrackball : public Object
{
public:
enum NavigationType
{
NONE,
PAN,
WALK,
ZOOM,
ROTATE
};
public:
ManipulatorTrackball();
~ManipulatorTrackball();
void setCamera(Camera* camera);
void setRotationPoint(const Vec3d& rotPoint);
void setView(const Vec3d& alongDirection, const Vec3d& upDirection);
NavigationType activeNavigation() const;
void startNavigation(NavigationType navigationType, int winCoordX, int winCoordY);
bool updateNavigation(int winCoordX, int winCoordY);
void endNavigation();
private:
bool pan(int posX, int posY);
bool walk(int posX, int posY);
bool zoom(int posX, int posY);
bool rotate(int posX, int posY);
static Quatd trackballRotation(double oldPosX, double oldPosY, double newPosX, double newPosY, const Mat4d& currViewMatrix, double sensitivityFactor);
static Vec3d projectToSphere(double radius, double posX, double posY);
private:
ref<Camera> m_camera; // Camera that should be manipulated
Vec3d m_rotationPoint; // Rotation point. Used both for rotations and to control pan/walk speed
NavigationType m_activeNavigation; // The active navigation type
int m_lastPosX; // Previous mouse position
int m_lastPosY;
Vec3d m_walkStartCameraPos; // Starting camera position for a walk operation
double m_walkSensitivity; // Scale factor for sensitivity of rotations
double m_rotateSensitivity; // Scale factor for walk sensitivity
};
}
@@ -0,0 +1,129 @@
//##################################################################################################
//
// 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 "cvfModel.h"
#include "cvfOpenGLContext.h"
#include "cvfPart.h"
#include "cvfRayIntersectSpec.h"
#include "cvfRay.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Model
/// \ingroup Viewing
///
/// Model is an abstract class that can deliver Part objects to a Scene.
///
/// The model does not enforce any internal structure. This is left to derived classes. The only
/// requirement for a derived model is to be able to respond to the abstract interface.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Model::Model()
: m_partEnableMask(0xffffffff)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Model::rayIntersect(const RayIntersectSpec& rayIntersectSpec, HitItemCollection* hitItemCollection)
{
// Example implementation
cref<Ray> ray = rayIntersectSpec.ray();
if (ray.isNull())
{
return false;
}
bool anyPartsHit = false;
Collection<Part> allPartsColl;
allParts(&allPartsColl);
size_t numParts = allPartsColl.size();
size_t partIdx;
for (partIdx = 0; partIdx < numParts; partIdx++)
{
Part* part = allPartsColl.at(partIdx);
CVF_ASSERT(part);
anyPartsHit |= part->rayIntersect(*ray, hitItemCollection);
}
return anyPartsHit;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Model::setPartEnableMask(unsigned int partEnableMask)
{
m_partEnableMask = partEnableMask;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
unsigned int Model::partEnableMask() const
{
return m_partEnableMask;
}
//--------------------------------------------------------------------------------------------------
/// Delete or release all OpenGL resources held by the contained parts
///
/// \warning The OpenGL context in which the resources were created or a context that is being
/// shared must be current in the calling thread.
/// \warning Some resources are merely released (by unreferencing the object) so in order to assure
/// that the actual OpenGL resources get deleted, you may have to do cleanup through the
/// OpenGLResourceManager as afterwards (eg. deleteOrphanedManagedBufferObjects())
//--------------------------------------------------------------------------------------------------
void Model::deleteOrReleaseOpenGLResources(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
Collection<Part> allPartsColl;
allParts(&allPartsColl);
size_t numParts = allPartsColl.size();
size_t partIdx;
for (partIdx = 0; partIdx < numParts; partIdx++)
{
Part* part = allPartsColl.at(partIdx);
CVF_ASSERT(part);
part->deleteOrReleaseOpenGLResources(oglContext);
}
}
} // 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 "cvfCollection.h"
#include "cvfBoundingBox.h"
namespace cvf {
class Part;
class PartRenderHintCollection;
class Camera;
class CullSettings;
class RayIntersectSpec;
class HitItemCollection;
class OpenGLContext;
//==================================================================================================
//
// Abstract Model class
//
//==================================================================================================
class Model : public Object
{
public:
Model();
virtual String name() const = 0;
virtual void findVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const CullSettings& cullSettings, unsigned int enableMask) = 0;
virtual void allParts(Collection<Part>* partCollection) = 0;
virtual void updateBoundingBoxesRecursive() = 0;
virtual BoundingBox boundingBox() const = 0;
virtual bool rayIntersect(const RayIntersectSpec& rayIntersectSpec, HitItemCollection* hitItemCollection) = 0;
void setPartEnableMask(unsigned int partEnableMask);
unsigned int partEnableMask() const;
void deleteOrReleaseOpenGLResources(OpenGLContext* oglContext);
private:
unsigned int m_partEnableMask; // Mask will be compared against our parts when determining visible parts
};
}
@@ -0,0 +1,445 @@
//##################################################################################################
//
// 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 "cvfModelBasicList.h"
#include "cvfPart.h"
#include "cvfCamera.h"
#include "cvfCullSettings.h"
#include "cvfPartRenderHintCollection.h"
#include "cvfDrawableGeo.h"
#include "cvfTransform.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::ModelBasicList
/// \ingroup Viewing
///
/// A simple model implementation using a list of parts.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String ModelBasicList::name() const
{
return m_modelName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicList::setName(const String& name)
{
m_modelName = name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicList::addPart(Part* part)
{
CVF_ASSERT(part);
m_parts.push_back(part);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Part* ModelBasicList::part(size_t index)
{
CVF_ASSERT(index < m_parts.size());
return m_parts.at(index);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t ModelBasicList::partCount() const
{
return m_parts.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicList::removePart(Part* part)
{
CVF_ASSERT(part);
m_parts.erase(part);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicList::removeAllParts()
{
m_parts.clear();
m_boundingBox.reset();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicList::updateBoundingBoxesRecursive()
{
m_boundingBox.reset();
size_t i;
for (i = 0; i < m_parts.size(); i++)
{
Part* part = m_parts.at(i);
part->updateBoundingBox();
m_boundingBox.add(part->boundingBox());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
BoundingBox ModelBasicList::boundingBox() const
{
return m_boundingBox;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicList::findVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const CullSettings& cullSettings, unsigned int enableMask)
{
Frustum frust;
if (cullSettings.isViewFrustumCullingEnabled())
{
frust = camera.frustum();
}
// Combination of model's and incoming enable mask
unsigned int combinedEnableMask = (partEnableMask() & enableMask);
doFindVisibleParts(visibleParts, camera, frust, cullSettings, combinedEnableMask);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicList::doFindVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const Frustum& frust, const CullSettings& cullSettings, unsigned int enableMask)
{
size_t numParts = m_parts.size();
size_t i;
for (i = 0; i < numParts; i++)
{
Part* part = m_parts[i].p();
CVF_ASSERT(part);
bool culled = false;
// Check if part is enabled (visible)
if (((part->enableMask() & enableMask) > 0) && (part->drawable()))
{
double projectedAreaPixels = -1;
// View Frustum Culling
if (cullSettings.isViewFrustumCullingEnabled())
{
const BoundingBox& bb = part->boundingBox();
CVF_ASSERT(bb.isValid());
if (frust.isOutside(bb))
{
culled = true;
}
}
// Pixel size (small feature) culling
// Cull based on objects projected screen area. Objects with area smaller than specified threshold will be culled
if (cullSettings.isPixelSizeCullingEnabled() && !culled)
{
const BoundingBox& bb = part->boundingBox();
CVF_ASSERT(bb.isValid());
projectedAreaPixels = camera.computeProjectedBoundingSpherePixelArea(bb.center(), bb.radius());
if (projectedAreaPixels < cullSettings.pixelSizeCullingAreaThreshold())
{
culled = true;
}
}
// Add to collection if not culled
if (!culled)
{
if (projectedAreaPixels >= 0)
{
visibleParts->add(part, static_cast<float>(projectedAreaPixels), -1.0f);
}
else
{
visibleParts->add(part);
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicList::allParts(Collection<Part>* partCollection)
{
size_t numParts = m_parts.size();
size_t i;
for (i = 0; i < numParts; i++)
{
partCollection->push_back(m_parts.at(i));
}
}
//--------------------------------------------------------------------------------------------------
/// Intersect all parts in the model with the given ray.
//--------------------------------------------------------------------------------------------------
bool ModelBasicList::rayIntersect(const RayIntersectSpec& rayIntersectSpec, HitItemCollection* hitItemCollection)
{
return Model::rayIntersect(rayIntersectSpec, hitItemCollection);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Part* ModelBasicList::findPartByID(int64 id)
{
size_t numParts = partCount();
size_t i;
for (i = 0; i < numParts; i++)
{
Part* p = m_parts.at(i);
CVF_ASSERT(p);
if (p->id() == id)
{
return p;
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Part* ModelBasicList::findPartByName(String name)
{
size_t numParts = partCount();
size_t i;
for (i = 0; i < numParts; i++)
{
Part* p = m_parts.at(i);
CVF_ASSERT(p);
if (p->name() == name)
{
return p;
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
/// Merge all parts with primitive count below given limit. A new part is created
/// containing merged drawableGeos. Vertices are transformed if a transformation matrix exists.
///
//--------------------------------------------------------------------------------------------------
void ModelBasicList::mergeParts(double maxExtent, unsigned int minimumPrimitiveCount)
{
// Gather all parts to be merged in a collection
Collection<Part> candidates;
size_t numParts = m_parts.size();
size_t i;
for (i = 0; i < numParts; i++)
{
Part* part = m_parts.at(i);
// Update BB for all parts, as the BB is used to find parts that are close
// to each other
part->updateBoundingBox();
DrawableGeo* drawable = dynamic_cast<DrawableGeo*>(part->drawable());
if (drawable)
{
size_t primitiveCount = drawable->faceCount();
if (primitiveCount < minimumPrimitiveCount)
{
candidates.push_back(part);
}
}
}
if (candidates.size() > 1)
{
IntArray newPartIDs;
newPartIDs.resize(candidates.size());
newPartIDs.setAll(-1);
int newPartID = 0;
size_t j;
for (j = 0; j < candidates.size(); j++)
{
BoundingBox bbMerged;
if (newPartIDs[j] == -1)
{
Part* part = candidates.at(j);
bbMerged = part->boundingBox();
newPartIDs.set(j, newPartID);
if (bbMerged.isValid())
{
size_t k;
for (k = j + 1; k < candidates.size(); k++)
{
Part* candidateBB = candidates.at(k);
BoundingBox bbCandidate = candidateBB->boundingBox();
bbCandidate.add(bbMerged);
if (bbCandidate.extent().length() < maxExtent)
{
bbMerged = bbCandidate;
newPartIDs[k] = newPartID;
}
}
}
newPartID++;
}
}
// Gather all parts to be merged in a collection
Collection<Part> partsToMerge;
Part* currentCandidate = candidates.at(0);
partsToMerge.push_back(currentCandidate);
int currentPartID = 0;
for (j = 1; j < newPartIDs.size(); j++)
{
if (newPartIDs.get(j) == currentPartID)
{
Part* candidate = candidates.at(j);
partsToMerge.push_back(candidate);
}
if (newPartIDs.get(j) != currentPartID || j == newPartIDs.size() - 1)
{
if (partsToMerge.size() > 1)
{
ref<Part> mergedPart = mergeAndAddPart(partsToMerge);
addPart(mergedPart.p());
// Remove merged parts from part list
size_t k;
for (k = 0; k < partsToMerge.size(); k++)
{
Part* part = partsToMerge.at(k);
removePart(part);
}
}
partsToMerge.clear();
Part* candidate = candidates.at(j);
partsToMerge.push_back(candidate);
currentPartID = newPartIDs.get(j);
}
}
}
}
//--------------------------------------------------------------------------------------------------
/// Merge all parts in given part collection. Create and insert merged part.
/// Incoming parts are removed from list.
//--------------------------------------------------------------------------------------------------
ref<Part> ModelBasicList::mergeAndAddPart(Collection<Part>& partCollection) const
{
CVF_ASSERT(!partCollection.empty());
// Build one new drawable from collection of small drawables. Compute normal of new drawable to be able to render.
ref<DrawableGeo> mergedDrawable = new DrawableGeo;
// Merge all drawables
size_t j;
for (j = 0; j < partCollection.size(); j++)
{
Part* part = partCollection.at(j);
DrawableGeo* drawable = dynamic_cast<DrawableGeo*>(part->drawable());
if (drawable)
{
Transform* transform = part->transform();
if (transform)
{
Mat4d mat = transform->worldTransform();
mergedDrawable->mergeInto(*drawable, &mat);
}
else
{
mergedDrawable->mergeInto(*drawable, NULL);
}
}
}
mergedDrawable->computeNormals();
// First part defines properties to be used in the new merged part
Part* firstPart = partCollection.at(0);
CVF_ASSERT(firstPart);
Effect* effect = firstPart->effect(0);
ref<Part> mergedPart = new Part;
mergedPart->setDrawable(mergedDrawable.p());
mergedPart->setEffect(0, effect);
mergedPart->updateBoundingBox();
return mergedPart;
}
} // 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 "cvfModel.h"
namespace cvf {
class Frustum;
//==================================================================================================
//
// A simple model implementation using a list of parts.
//
//==================================================================================================
class ModelBasicList : public Model
{
public:
virtual String name() const;
void setName(const String& name);
void addPart(Part* part);
Part* part(size_t index);
size_t partCount() const;
void removePart(Part* part);
void removeAllParts();
virtual void findVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const CullSettings& cullSettings, unsigned int enableMask);
virtual void allParts(Collection<Part>* partCollection);
virtual void mergeParts(double maxExtent, unsigned int minimumPrimitiveCount);
void doFindVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const Frustum& frustum, const CullSettings& cullSettings, unsigned int enableMask);
virtual void updateBoundingBoxesRecursive();
virtual BoundingBox boundingBox() const;
virtual bool rayIntersect(const RayIntersectSpec& rayIntersectSpec, HitItemCollection* hitItemCollection);
Part* findPartByID(int64 id);
Part* findPartByName(String name);
private:
ref<Part> mergeAndAddPart(Collection<Part>& partCollection) const;
protected:
String m_modelName;
Collection<Part> m_parts;
BoundingBox m_boundingBox;
};
}
@@ -0,0 +1,696 @@
//##################################################################################################
//
// 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 "cvfModelBasicTree.h"
#include "cvfPart.h"
#include "cvfCamera.h"
#include "cvfCullSettings.h"
#include "cvfPartRenderHintCollection.h"
#include "cvfRayIntersectSpec.h"
#include "cvfRay.h"
#include "cvfDrawableGeo.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::ModelBasicTreeNode
/// \ingroup Viewing
///
/// A node in a ModelBasicTree.
///
/// Contains a list of part at this level and a list of children.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
ModelBasicTreeNode::ModelBasicTreeNode()
{
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
ModelBasicTreeNode::~ModelBasicTreeNode()
{
uint numChildren = childCount();
uint i;
for (i = 0; i < numChildren; i++)
{
ModelBasicTreeNode* c = child(i);
CVF_ASSERT(c);
delete c;
}
}
//--------------------------------------------------------------------------------------------------
/// Add a part to this node
//--------------------------------------------------------------------------------------------------
void ModelBasicTreeNode::addPart(Part* part)
{
CVF_ASSERT(part);
if (m_partList.isNull())
{
m_partList = new ModelBasicList;
}
m_partList->addPart(part);
}
//--------------------------------------------------------------------------------------------------
/// Get the part at the given index
//--------------------------------------------------------------------------------------------------
Part* ModelBasicTreeNode::part(uint index)
{
CVF_ASSERT(m_partList.notNull());
CVF_ASSERT(index < partCount());
return m_partList->part(index);
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of parts in this node
//--------------------------------------------------------------------------------------------------
uint ModelBasicTreeNode::partCount() const
{
if (m_partList.notNull())
{
return static_cast<uint>(m_partList->partCount());
}
else
{
return 0;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicTreeNode::removePart(Part* part)
{
if (m_partList.notNull())
{
m_partList->removePart(part);
}
uint numChildren = childCount();
uint i;
for (i = 0; i < numChildren; i++)
{
ModelBasicTreeNode* c = child(i);
CVF_ASSERT(c);
c->removePart(part);
}
}
//--------------------------------------------------------------------------------------------------
/// Add a child node to this node. The node can have any number of childern.
//--------------------------------------------------------------------------------------------------
void ModelBasicTreeNode::addChild(ModelBasicTreeNode* child)
{
CVF_ASSERT(child);
m_children.push_back(child);
}
//--------------------------------------------------------------------------------------------------
/// Returns the child node at the given index
//--------------------------------------------------------------------------------------------------
ModelBasicTreeNode* ModelBasicTreeNode::child(uint index)
{
CVF_ASSERT(index < childCount());
return m_children[index];
}
//--------------------------------------------------------------------------------------------------
/// Returns a const ptr to the child node at the given index
//--------------------------------------------------------------------------------------------------
const ModelBasicTreeNode* ModelBasicTreeNode::child(uint index) const
{
CVF_ASSERT(index < childCount());
return m_children[index];
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of children in this node
//--------------------------------------------------------------------------------------------------
uint ModelBasicTreeNode::childCount() const
{
return static_cast<uint>(m_children.size());
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of children in this node
//--------------------------------------------------------------------------------------------------
void ModelBasicTreeNode::removeChild(ModelBasicTreeNode* child)
{
std::vector<ModelBasicTreeNode*>::iterator it = std::find(m_children.begin(), m_children.end(), child);
if (it != m_children.end())
{
m_children.erase(it);
}
}
//--------------------------------------------------------------------------------------------------
/// Update the bounding box of this node (recursive)
//--------------------------------------------------------------------------------------------------
void ModelBasicTreeNode::updateBoundingBoxesRecursive()
{
m_boundingBox.reset();
uint numChildren = childCount();
uint i;
for (i = 0; i < numChildren; i++)
{
ModelBasicTreeNode* c = child(i);
CVF_ASSERT(c);
c->updateBoundingBoxesRecursive();
m_boundingBox.add(c->boundingBox());
}
if (m_partList.notNull())
{
m_partList->updateBoundingBoxesRecursive();
m_boundingBox.add(m_partList->boundingBox());
}
}
//--------------------------------------------------------------------------------------------------
/// Compute and append the visible parts in this node and all child nodes (recursive)
//--------------------------------------------------------------------------------------------------
void ModelBasicTreeNode::findVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const Frustum& frust, const CullSettings& cullSettings, unsigned int enableMask)
{
if (!m_boundingBox.isValid())
{
return;
}
const size_t numChildren = m_children.size();
const size_t numParts = m_partList.notNull() ? m_partList->partCount() : 0;
if (numChildren > 0 || numParts > 1)
{
// View Frustum culling
if (cullSettings.isViewFrustumCullingEnabled())
{
if (frust.isOutside(m_boundingBox))
{
// No parts on this level (or below) are visible. So just return
return;
}
}
// Pixel size culling
if (cullSettings.isPixelSizeCullingEnabled())
{
double area = camera.computeProjectedBoundingSpherePixelArea(m_boundingBox.center(), m_boundingBox.radius());
if (area < cullSettings.pixelSizeCullingAreaThreshold())
{
return;
}
}
}
size_t i;
for (i = 0; i < numChildren; i++)
{
ModelBasicTreeNode* c = m_children[i];
CVF_ASSERT(c);
c->findVisibleParts(visibleParts, camera, frust, cullSettings, enableMask);
}
if (m_partList.notNull())
{
m_partList->doFindVisibleParts(visibleParts, camera, frust, cullSettings, enableMask);
}
}
//--------------------------------------------------------------------------------------------------
/// Get all parts in this node and all child nodes (recursive)
//--------------------------------------------------------------------------------------------------
void ModelBasicTreeNode::allParts(Collection<Part>* partCollection)
{
uint numChildren = childCount();
uint i;
for (i = 0; i < numChildren; i++)
{
ModelBasicTreeNode* c = child(i);
CVF_ASSERT(c);
c->allParts(partCollection);
}
if (m_partList.notNull())
{
m_partList->allParts(partCollection);
}
}
//--------------------------------------------------------------------------------------------------
/// Compute a ray intersection with all parts in this node and all child nodes (recursive)
//--------------------------------------------------------------------------------------------------
bool ModelBasicTreeNode::rayIntersect(const RayIntersectSpec& rayIntersectSpec, HitItemCollection* hitItemCollection)
{
bool hit = false;
if (!m_boundingBox.isValid())
{
return false;
}
// Early reject: Check if bounding box is hit
if (!rayIntersectSpec.ray()->boxIntersect(m_boundingBox))
{
return false;
}
uint numChildren = childCount();
uint i;
for (i = 0; i < numChildren; i++)
{
ModelBasicTreeNode* c = child(i);
CVF_ASSERT(c);
hit |= c->rayIntersect(rayIntersectSpec, hitItemCollection);
}
if (m_partList.notNull())
{
hit |= m_partList->rayIntersect(rayIntersectSpec, hitItemCollection);
}
return hit;
}
//--------------------------------------------------------------------------------------------------
/// Get the bounding box of this node
//--------------------------------------------------------------------------------------------------
const BoundingBox& ModelBasicTreeNode::boundingBox() const
{
return m_boundingBox;
}
//--------------------------------------------------------------------------------------------------
/// Returns the first part found with the given ID. NULL if not found.
//--------------------------------------------------------------------------------------------------
Part* ModelBasicTreeNode::findPartByID(int id)
{
if (m_partList.notNull())
{
uint numParts = partCount();
uint i;
for (i = 0; i < numParts; i++)
{
Part* p = m_partList->part(i);
CVF_ASSERT(p);
if (p->id() == id)
{
return p;
}
}
}
uint numChildren = childCount();
uint i;
for (i = 0; i < numChildren; i++)
{
ModelBasicTreeNode* c = child(i);
CVF_ASSERT(c);
Part* p = c->findPartByID(id);
if (p)
{
return p;
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
/// Returns the first part found with the given name. NULL if not found.
//--------------------------------------------------------------------------------------------------
Part* ModelBasicTreeNode::findPartByName(String name)
{
if (m_partList.notNull())
{
uint numParts = partCount();
uint i;
for (i = 0; i < numParts; i++)
{
Part* p = m_partList->part(i);
CVF_ASSERT(p);
if (p->name() == name)
{
return p;
}
}
}
uint numChildren = childCount();
uint i;
for (i = 0; i < numChildren; i++)
{
ModelBasicTreeNode* c = child(i);
CVF_ASSERT(c);
Part* p = c->findPartByName(name);
if (p)
{
return p;
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicTreeNode::mergeParts(double maxExtent, unsigned int minimumPrimitiveCount)
{
uint numChildren = childCount();
std::vector<ModelBasicTreeNode*> childrenToBeRemoved;
uint i;
for (i = 0; i < numChildren; i++)
{
ModelBasicTreeNode* c = child(i);
CVF_ASSERT(c);
c->mergeParts(maxExtent, minimumPrimitiveCount);
// Devour any child node being too small.
// Any candidate child node for being devoured is a leaf node because we have already recursed downwards.
// Check if this is a leaf node
if (c->childCount() == 0)
{
size_t primCount = c->primitiveCount();
if (primCount < minimumPrimitiveCount)
{
size_t numChildParts = 0;
if (c->m_partList.notNull())
{
numChildParts = c->m_partList->partCount();
}
size_t j;
for (j = 0; j < numChildParts; j++)
{
addPart(c->m_partList->part(j));
}
childrenToBeRemoved.push_back(c);
}
}
}
if (childrenToBeRemoved.size() > 0)
{
// Remove children from last to first index to make sure the indices are valid
std::vector<ModelBasicTreeNode*>::iterator it;
for (it = childrenToBeRemoved.begin(); it != childrenToBeRemoved.end(); it++)
{
removeChild(*it);
}
}
// Merge too small parts in own list of parts. Any child node being devoured by the above code is
// in own list of parts. They are too small, but will be merged also by the statement below.
m_partList->mergeParts(maxExtent, minimumPrimitiveCount);
}
//--------------------------------------------------------------------------------------------------
/// Count primitives of part in this node - do not recurse
//--------------------------------------------------------------------------------------------------
size_t ModelBasicTreeNode::primitiveCount()
{
size_t totalPrimitiveCount = 0;
size_t j;
for (j = 0; j < m_partList->partCount(); j++)
{
Part* part = m_partList->part(j);
DrawableGeo* drawable = dynamic_cast<DrawableGeo*>(part->drawable());
if (drawable)
{
totalPrimitiveCount += drawable->faceCount();
}
}
return totalPrimitiveCount;
}
//==================================================================================================
///
/// \class cvf::ModelBasicTree
/// \ingroup Viewing
///
/// A simple model implementation using a tree.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
ModelBasicTree::ModelBasicTree()
{
m_root = NULL;
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
ModelBasicTree::~ModelBasicTree()
{
delete m_root;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String ModelBasicTree::name() const
{
return m_modelName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicTree::setName(const String& name)
{
m_modelName = name;
}
//--------------------------------------------------------------------------------------------------
/// Set the root node of the tree.
///
/// If set to NULL, all current nodes will be deleted.
//--------------------------------------------------------------------------------------------------
void ModelBasicTree::setRoot(ModelBasicTreeNode* root)
{
if (m_root != root)
{
delete m_root;
m_root = root;
}
}
//--------------------------------------------------------------------------------------------------
/// Returns a pointer to the root node.
//--------------------------------------------------------------------------------------------------
ModelBasicTreeNode* ModelBasicTree::root()
{
return m_root;
}
//--------------------------------------------------------------------------------------------------
/// Returns a const pointer to the root node
//--------------------------------------------------------------------------------------------------
const ModelBasicTreeNode* ModelBasicTree::root() const
{
return m_root;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicTree::removePart(Part* part)
{
if (m_root)
{
m_root->removePart(part);
}
}
//--------------------------------------------------------------------------------------------------
/// Update the bounding boxes in the entire tree
//--------------------------------------------------------------------------------------------------
void ModelBasicTree::updateBoundingBoxesRecursive()
{
m_boundingBox.reset();
if (m_root)
{
m_root->updateBoundingBoxesRecursive();
m_boundingBox.add(m_root->boundingBox());
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the bounding box of all parts in the tree
//--------------------------------------------------------------------------------------------------
BoundingBox ModelBasicTree::boundingBox() const
{
return m_boundingBox;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicTree::findVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const CullSettings& cullSettings, unsigned int enableMask)
{
// Add in the model's enable mask before delegating to root node
unsigned int combinedEnableMask = (partEnableMask() & enableMask);
if (m_root)
{
m_root->findVisibleParts(visibleParts, camera, camera.frustum(), cullSettings, combinedEnableMask);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicTree::allParts(Collection<Part>* partCollection)
{
if (m_root)
{
m_root->allParts(partCollection);
}
}
//--------------------------------------------------------------------------------------------------
/// Intersect all parts in the model with the given ray.
//--------------------------------------------------------------------------------------------------
bool ModelBasicTree::rayIntersect(const RayIntersectSpec& rayIntersectSpec, HitItemCollection* hitItemCollection)
{
if (!m_root)
{
return false;
}
return m_root->rayIntersect(rayIntersectSpec, hitItemCollection);
}
//--------------------------------------------------------------------------------------------------
/// Returns the first part found with the given ID. NULL if not found.
//--------------------------------------------------------------------------------------------------
Part* ModelBasicTree::findPartByID(int id)
{
if (!m_root)
{
return NULL;
}
return m_root->findPartByID(id);
}
//--------------------------------------------------------------------------------------------------
/// Returns the first part found with the given name. NULL if not found.
//--------------------------------------------------------------------------------------------------
Part* ModelBasicTree::findPartByName(String name)
{
if (!m_root)
{
return NULL;
}
return m_root->findPartByName(name);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void ModelBasicTree::mergeParts(double maxExtent, unsigned int minimumPrimitiveCount)
{
if (m_root)
{
m_root->mergeParts(maxExtent, minimumPrimitiveCount);
}
}
} // namespace cvf
@@ -0,0 +1,110 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfModelBasicList.h"
namespace cvf {
//==================================================================================================
//
// A node in a ModelBasicTree model
//
//==================================================================================================
class ModelBasicTreeNode
{
public:
ModelBasicTreeNode();
virtual ~ModelBasicTreeNode();
void addPart(Part* part);
Part* part(uint index);
uint partCount() const;
void removePart(Part* part);
void addChild(ModelBasicTreeNode* child);
ModelBasicTreeNode* child(uint index);
const ModelBasicTreeNode* child(uint index) const;
uint childCount() const;
void removeChild(ModelBasicTreeNode* child);
void findVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const Frustum& frustum, const CullSettings& cullSettings, unsigned int enableMask);
void allParts(Collection<Part>* partCollection);
virtual void mergeParts(double maxExtent, unsigned int minimumPrimitiveCount);
void updateBoundingBoxesRecursive();
const BoundingBox& boundingBox() const;
bool rayIntersect(const RayIntersectSpec& rayIntersectSpec, HitItemCollection* hitItemCollection);
Part* findPartByID(int id);
Part* findPartByName(String name);
private:
size_t primitiveCount();
private:
ref<ModelBasicList> m_partList; // Reference to list of parts contained in this node. Null if no parts are present
std::vector<ModelBasicTreeNode*> m_children; // Array of child nodes
BoundingBox m_boundingBox; // This node's aggregated bounding box
};
//==================================================================================================
//
// A simple model implementation using a tree of parts.
//
//==================================================================================================
class ModelBasicTree : public Model
{
public:
ModelBasicTree();
~ModelBasicTree();
virtual String name() const;
void setName(const String& name);
void setRoot(ModelBasicTreeNode* root);
ModelBasicTreeNode* root();
const ModelBasicTreeNode* root() const;
void removePart(Part* part);
virtual void findVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const CullSettings& cullSettings, unsigned int enableMask);
virtual void allParts(Collection<Part>* partCollection);
virtual void mergeParts(double maxExtent, unsigned int minimumPrimitiveCount);
virtual void updateBoundingBoxesRecursive();
virtual BoundingBox boundingBox() const;
virtual bool rayIntersect(const RayIntersectSpec& rayIntersectSpec, HitItemCollection* hitItemCollection);
Part* findPartByID(int id);
Part* findPartByName(String name);
protected:
String m_modelName;
ModelBasicTreeNode* m_root;
BoundingBox m_boundingBox;
};
}
+445
View File
@@ -0,0 +1,445 @@
//##################################################################################################
//
// 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 "cvfPart.h"
#include "cvfDrawable.h"
#include "cvfTransform.h"
#include "cvfEffect.h"
#include "cvfRay.h"
#include "cvfHitDetail.h"
#include "cvfHitItemCollection.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Part
/// \ingroup Viewing
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Part::Part()
: m_name(),
m_id(-1),
m_enableMask(0xffffffff),
m_priority(0)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Part::Part(int64 id, String name)
: m_name(name),
m_id(id),
m_enableMask(0xffffffff),
m_priority(0)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Part::~Part()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<Part> Part::shallowCopy() const
{
ref<Part> newPart = new Part;
newPart->m_id = m_id;
newPart->m_name = m_name;
newPart->m_enableMask = m_enableMask;
newPart->m_transform = m_transform;
newPart->m_boundingBox = m_boundingBox;
uint i;
for (i = 0; i < MAX_NUM_LOD_LEVELS; i++)
{
newPart->m_drawables[i] = m_drawables[i];
newPart->m_effects[i] = m_effects[i];
}
return newPart;
}
//--------------------------------------------------------------------------------------------------
/// Set a name to identify the part.
///
/// It's up to the developer to decide if the name should be unique or not.
///
/// \sa name
//--------------------------------------------------------------------------------------------------
void Part::setName(const String& name)
{
m_name = name;
}
//--------------------------------------------------------------------------------------------------
/// Set an ID to identify the part
///
/// It's up to the developer to decide if the value should be unique or not.
///
/// \sa id()
//--------------------------------------------------------------------------------------------------
void Part::setId(int64 id)
{
m_id = id;
}
//--------------------------------------------------------------------------------------------------
/// Get the name of the part
///
/// Default is an empty String.
///
/// \sa setName
//--------------------------------------------------------------------------------------------------
const String& Part::name() const
{
return m_name;
}
//--------------------------------------------------------------------------------------------------
/// Get the ID of the part
///
/// Default is -1.
///
/// \sa setId
//--------------------------------------------------------------------------------------------------
int64 Part::id() const
{
return m_id;
}
//--------------------------------------------------------------------------------------------------
/// Sets the enable mask for this part
///
/// The enable mask determines if the part should be visible and/or rendered depending on the
/// masks set in its containing Model and/or the Rendering where the part participates.
/// The default enable mask if 0xffffffff
///
/// \sa Model::setPartEnableMask()
//--------------------------------------------------------------------------------------------------
void Part::setEnableMask(uint mask)
{
m_enableMask = mask;
}
//--------------------------------------------------------------------------------------------------
/// Gets the enable mask for this part
///
/// \sa setEnableMask()
//--------------------------------------------------------------------------------------------------
uint Part::enableMask() const
{
return m_enableMask;
}
//--------------------------------------------------------------------------------------------------
/// Set render priority for this part
///
/// The render priority determines the order in which parts get rendered. Parts with lower priorities
/// get rendered first. The default priority is 0.
//--------------------------------------------------------------------------------------------------
void Part::setPriority(int priority)
{
m_priority = priority;
}
//--------------------------------------------------------------------------------------------------
/// Get render priority
//--------------------------------------------------------------------------------------------------
int Part::priority() const
{
return m_priority;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Part::setDrawable(Drawable* drawable)
{
m_drawables[0] = drawable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Part::setDrawable(uint lodLevel, Drawable* drawable)
{
CVF_ASSERT(lodLevel < MAX_NUM_LOD_LEVELS);
m_drawables[lodLevel] = drawable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Drawable* Part::drawable()
{
return m_drawables[0].p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Drawable* Part::drawable() const
{
return m_drawables[0].p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Drawable* Part::drawable(uint lodLevel)
{
CVF_ASSERT(lodLevel < MAX_NUM_LOD_LEVELS);
return m_drawables[lodLevel].p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Part::setEffect(Effect* effect)
{
m_effects[0] = effect;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Part::setEffect(uint lodLevel, Effect* effect)
{
CVF_ASSERT(lodLevel < MAX_NUM_LOD_LEVELS);
m_effects[lodLevel] = effect;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Effect* Part::effect()
{
return m_effects[0].p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Effect* Part::effect(uint lodLevel)
{
CVF_ASSERT(lodLevel < MAX_NUM_LOD_LEVELS);
return m_effects[lodLevel].p();
}
//--------------------------------------------------------------------------------------------------
/// Returns the current transform (matrix) of the part. NULL if none.
//--------------------------------------------------------------------------------------------------
Transform* Part::transform()
{
return m_transform.p();
}
//--------------------------------------------------------------------------------------------------
/// Returns the current transform (matrix) of the part. NULL if none.
//--------------------------------------------------------------------------------------------------
const Transform* Part::transform() const
{
return m_transform.p();
}
//--------------------------------------------------------------------------------------------------
/// Set the transform (matrix) to use for this part. NULL for none.
//--------------------------------------------------------------------------------------------------
void Part::setTransform(Transform* transform)
{
m_transform = transform;
}
//--------------------------------------------------------------------------------------------------
/// Updates Part's bounding box using LOD level 0. Will result in an invalid bounding box if no drawable exists.
//--------------------------------------------------------------------------------------------------
void Part::updateBoundingBox()
{
Drawable* drawable = m_drawables[0].p();
if (drawable)
{
m_boundingBox = drawable->boundingBox();
if (m_transform.notNull())
{
m_boundingBox.transform(m_transform->worldTransform());
}
}
else
{
m_boundingBox.reset();
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the currently computed bounding box. May be invalid.
//--------------------------------------------------------------------------------------------------
const BoundingBox& Part::boundingBox() const
{
return m_boundingBox;
}
//--------------------------------------------------------------------------------------------------
/// Intersect the drawable (at lod level 0) in the part with the specified ray
///
/// Returns true if any intersections were added to the hit item collection.
/// Checks first against the bounding box of the part, so it must be up to date.
//--------------------------------------------------------------------------------------------------
bool Part::rayIntersect(const Ray& ray, HitItemCollection* hitItemCollection) const
{
const Drawable* myDrawable = m_drawables[0].p();
if (!myDrawable)
{
return false;
}
// Early reject: Check if bounding box is hit
if (!ray.boxIntersect(m_boundingBox))
{
return false;
}
// Inverse transform ray to be able to do picking in local coordinates
Ray tranformedRay(ray);
if (m_transform.notNull())
{
tranformedRay.transform(m_transform->worldTransform().getInverted());
}
Vec3d intersectionPoint;
ref<HitDetail> hitDetail;
if (myDrawable->rayIntersectCreateDetail(tranformedRay, &intersectionPoint, &hitDetail))
{
if (m_transform.notNull())
{
intersectionPoint.transformPoint(m_transform->worldTransform());
}
double dist = (intersectionPoint - ray.origin()).length();
ref<HitItem> hitItem = new HitItem(dist, intersectionPoint);
hitItem->setPart(this);
hitItem->setDetail(hitDetail.p());
hitItemCollection->add(hitItem.p());
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Delete or release all OpenGL resources held by the part
///
/// \warning The OpenGL context in which the resources were created or a context that is being
/// shared must be current in the calling thread.
/// \warning Some resources are just released (by unreferencing the object) so in order to assure
/// that the actual OpenGL resources get deleted, you may have to do cleanup through the
/// OpenGLResourceManager as afterwards (eg. deleteOrphanedManagedBufferObjects())
//--------------------------------------------------------------------------------------------------
void Part::deleteOrReleaseOpenGLResources(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
uint lod;
for (lod = 0; lod < MAX_NUM_LOD_LEVELS; lod++)
{
Effect* theEffect = effect(lod);
if (theEffect)
{
theEffect->deleteOrReleaseOpenGLResources(oglContext);
}
Drawable* theDrawable = drawable(lod);
if (theDrawable)
{
theDrawable->releaseBufferObjectsGPU();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Part::setSourceInfo(Object* sourceInfo)
{
m_sourceInfo = sourceInfo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Object* Part::sourceInfo() const
{
return m_sourceInfo.p();
}
} // namespace cvf
+106
View File
@@ -0,0 +1,106 @@
//##################################################################################################
//
// 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 "cvfString.h"
#include "cvfBoundingBox.h"
namespace cvf {
class Drawable;
class Transform;
class Effect;
class Ray;
class HitItemCollection;
class OpenGLContext;
//==================================================================================================
//
// Part
//
//==================================================================================================
class Part : public Object
{
public:
static const uint MAX_NUM_LOD_LEVELS = 2;
public:
Part();
Part(int64 id, String name);
virtual ~Part();
void setName(const String& name);
void setId(int64 id);
const String& name() const;
int64 id() const;
void setEnableMask(uint mask);
uint enableMask() const;
void setPriority(int priority);
int priority() const;
virtual ref<Part> shallowCopy() const;
void setDrawable(Drawable* drawable);
void setDrawable(uint lodLevel, Drawable* drawable);
Drawable* drawable();
const Drawable* drawable() const;
Drawable* drawable(uint lodLevel);
Effect* effect();
Effect* effect(uint lodLevel);
void setEffect(Effect* effect);
void setEffect(uint lodLevel, Effect* effect);
Transform* transform();
const Transform* transform() const;
void setTransform(Transform* transform);
void updateBoundingBox();
const BoundingBox& boundingBox() const;
bool rayIntersect(const Ray& ray, HitItemCollection* hitItemCollection) const;
void deleteOrReleaseOpenGLResources(OpenGLContext* oglContext);
void setSourceInfo(Object* sourceInfo);
const Object* sourceInfo() const;
protected:
String m_name;
int64 m_id;
uint m_enableMask; // The enable mask determines if the part should be visible and/or rendered depending on masks set in Model and/or Rendering
int m_priority; // The part's render priority. Parts with the highest priority (highest value) are drawn last. The default priority is 0.
ref<Transform> m_transform;
ref<Drawable> m_drawables[MAX_NUM_LOD_LEVELS];
ref<Effect> m_effects[MAX_NUM_LOD_LEVELS];
BoundingBox m_boundingBox;
ref<Object> m_sourceInfo; // Source info object used to identify the origin of a given geometry entity. This usually needed during picking operations,
// and the application needs to identify the domain specific entity from which the selected geometry entity was created
};
}
@@ -0,0 +1,200 @@
//##################################################################################################
//
// 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 "cvfPartRenderHintCollection.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::PartRenderHint
/// \ingroup Viewing
///
/// Render hints for parts
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PartRenderHint::PartRenderHint()
: m_projectedAreaPixels(-1.0),
m_centerDistance(-1.0)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PartRenderHint::set(float projectedAreaPixels, float centerDistance)
{
m_projectedAreaPixels = projectedAreaPixels;
m_centerDistance = centerDistance;
}
//==================================================================================================
///
/// \class cvf::PartRenderHintCollection
/// \ingroup Viewing
///
/// A collection of parts with optional render hints
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PartRenderHintCollection::PartRenderHintCollection()
{
m_itemCount = 0;
}
//--------------------------------------------------------------------------------------------------
/// Add a part a and optionally a render hint to the part collection
//--------------------------------------------------------------------------------------------------
void PartRenderHintCollection::add(Part* part, float projectedAreaPixels, float distance)
{
CVF_TIGHT_ASSERT(part);
size_t arrSize = m_parts.size();
CVF_TIGHT_ASSERT(arrSize == m_renderHints.size());
PartRenderHint* hint = NULL;
if (arrSize > m_itemCount)
{
m_parts[m_itemCount] = part;
hint = m_renderHints[m_itemCount].p();
if (!hint)
{
hint = new PartRenderHint();
m_renderHints[m_itemCount] = hint;
}
}
else
{
m_parts.push_back(part);
hint = new PartRenderHint();
m_renderHints.push_back(hint);
}
hint->set(projectedAreaPixels, distance);
m_itemCount++;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PartRenderHintCollection::add(Part* part)
{
CVF_TIGHT_ASSERT(part);
size_t arrSize = m_parts.size();
CVF_TIGHT_ASSERT(arrSize == m_renderHints.size());
if (arrSize > m_itemCount)
{
m_parts[m_itemCount] = part;
m_renderHints[m_itemCount] = NULL;
}
else
{
m_parts.push_back(part);
m_renderHints.push_back(NULL);
}
m_itemCount++;
}
//--------------------------------------------------------------------------------------------------
/// Get the number of parts in the collection
//--------------------------------------------------------------------------------------------------
size_t PartRenderHintCollection::count() const
{
CVF_TIGHT_ASSERT(m_itemCount <= m_parts.size());
CVF_TIGHT_ASSERT(m_itemCount <= m_renderHints.size());
return m_itemCount;
}
//--------------------------------------------------------------------------------------------------
/// Sets the count to zero, but does not necessarily delete the actual contained items
//--------------------------------------------------------------------------------------------------
void PartRenderHintCollection::setCountZero()
{
m_itemCount = 0;
}
//--------------------------------------------------------------------------------------------------
/// Removes all entries and releases all memory
//--------------------------------------------------------------------------------------------------
void PartRenderHintCollection::removeAll()
{
m_parts.clear();
m_renderHints.clear();
m_itemCount = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Part* PartRenderHintCollection::part(size_t index)
{
CVF_TIGHT_ASSERT(index < m_itemCount);
CVF_TIGHT_ASSERT(index < m_parts.size());
return m_parts[index];
}
//--------------------------------------------------------------------------------------------------
/// Get the render hint for the part (if available)
///
/// \param index The index to use in this function.
///
/// \return The render hint for the part.
///
/// Use this method to get the render hint for the part with the given index
//--------------------------------------------------------------------------------------------------
PartRenderHint* PartRenderHintCollection::renderHint(size_t index)
{
CVF_TIGHT_ASSERT(index < m_itemCount);
CVF_TIGHT_ASSERT(index < m_renderHints.size());
return m_renderHints[index].p();
}
} // namespace cvf
@@ -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.
//
//##################################################################################################
#pragma once
#include "cvfCollection.h"
namespace cvf {
class Part;
//==================================================================================================
//
// Render hints for parts
//
//==================================================================================================
class PartRenderHint : public Object
{
public:
PartRenderHint();
void set(float projectedAreaPixels, float centerDistance);
float projectedAreaPixels() const { return m_projectedAreaPixels; }
float centerDistance() const { return m_centerDistance; }
private:
float m_projectedAreaPixels; // Default -1, which means not set
float m_centerDistance; // Default -1, which means not set
};
//==================================================================================================
//
// Collection of parts with optional render hints
//
//==================================================================================================
class PartRenderHintCollection : public Object
{
public:
PartRenderHintCollection();
void add(Part* part);
void add(Part* part, float projectedAreaPixels, float distance);
size_t count() const;
void setCountZero();
void removeAll();
Part* part(size_t index);
PartRenderHint* renderHint(size_t index);
private:
size_t m_itemCount; // We keep our own item count in order to avoid resizing our contained collections
std::vector<Part*> m_parts;
Collection<PartRenderHint> m_renderHints;
};
}
@@ -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.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfPerformanceInfo.h"
#include "cvfMath.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::PerformanceInfo
/// \ingroup Viewing
///
/// A class for storing performance info related to rendering of the contents of a view
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Clear all data
//--------------------------------------------------------------------------------------------------
PerformanceInfo::PerformanceInfo()
{
clear();
}
//--------------------------------------------------------------------------------------------------
/// Clear all data
//--------------------------------------------------------------------------------------------------
void PerformanceInfo::clear()
{
resetCurrentTimers();
int i;
for (i = 0; i < NUM_PERFORMANCE_HISTORY_ITEMS; i++)
{
m_totalDrawTimeHistory[i] = UNDEFINED_DOUBLE;
}
m_nextHistoryItem = 0;
}
//--------------------------------------------------------------------------------------------------
/// Clear all data
//--------------------------------------------------------------------------------------------------
void PerformanceInfo::resetCurrentTimers()
{
totalDrawTime = 0.0;
computeVisiblePartsTime = 0.0;
buildRenderQueueTime = 0.0;
sortRenderQueueTime = 0.0;
renderEngineTime = 0.0;
visiblePartsCount = 0;
renderedPartsCount = 0;
vertexCount = 0;
triangleCount = 0;
openGLPrimitiveCount = 0;
applyRenderStateCount = 0;
shaderProgramChangesCount = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PerformanceInfo::update(const PerformanceInfo& perf)
{
totalDrawTime += perf.totalDrawTime;
computeVisiblePartsTime += perf.computeVisiblePartsTime;
buildRenderQueueTime += perf.buildRenderQueueTime;
sortRenderQueueTime += perf.sortRenderQueueTime;
renderEngineTime += perf.renderEngineTime;
visiblePartsCount += perf.visiblePartsCount;
renderedPartsCount += perf.renderedPartsCount;
vertexCount += perf.vertexCount;
triangleCount += perf.triangleCount;
openGLPrimitiveCount += perf.openGLPrimitiveCount;
applyRenderStateCount += perf.applyRenderStateCount;
shaderProgramChangesCount += perf.shaderProgramChangesCount;
CVF_ASSERT(m_nextHistoryItem >= 0 && m_nextHistoryItem < NUM_PERFORMANCE_HISTORY_ITEMS);
m_totalDrawTimeHistory[m_nextHistoryItem] = totalDrawTime;
m_nextHistoryItem++;
if (m_nextHistoryItem >= NUM_PERFORMANCE_HISTORY_ITEMS) m_nextHistoryItem = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double PerformanceInfo::averageTotalDrawTime() const
{
double sum = 0.0;
int count = 0;
int i;
for (i = 0; i < NUM_PERFORMANCE_HISTORY_ITEMS; i++)
{
if (m_totalDrawTimeHistory[i] != UNDEFINED_DOUBLE)
{
sum += m_totalDrawTimeHistory[i];
count++;
}
}
if (count < 1)
{
return 0.0;
}
return sum/count;
}
} // namespace cvf
@@ -0,0 +1,64 @@
//##################################################################################################
//
// 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 {
//==================================================================================================
//
// PerformanceInfo
//
//==================================================================================================
class PerformanceInfo
{
public:
double totalDrawTime; ///< Total amount of time (in seconds) used to draw the last frame
double computeVisiblePartsTime; ///< Time (in seconds) used to create the visible part collection
double buildRenderQueueTime; ///< Time (in seconds) used to build the rendering queue
double sortRenderQueueTime; ///< Time (in seconds) used to sort the render queue
double renderEngineTime; ///< Time (in seconds) used to render the pre-processed rendering queue
size_t visiblePartsCount; ///< Number of visible parts
size_t renderedPartsCount; ///< Number of parts that was drawn
size_t vertexCount; ///< Number of vertices (nodes, points) used to draw.
size_t triangleCount; ///< Number of triangles (GL_TRIANGELS)
size_t openGLPrimitiveCount; ///< Total number of GL primitives drawn (lines, points, polygons, etc). For strips the number of resulting triangles.
size_t applyRenderStateCount; ///< Number of render state changes
size_t shaderProgramChangesCount; ///< Number of shader program changes
public:
PerformanceInfo();
double averageTotalDrawTime() const;
void clear();
void resetCurrentTimers();
void update(const PerformanceInfo& perf);
private:
static const int NUM_PERFORMANCE_HISTORY_ITEMS = 10;
double m_totalDrawTimeHistory[NUM_PERFORMANCE_HISTORY_ITEMS];
int m_nextHistoryItem;
};
}
@@ -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.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfRayIntersectSpec.h"
#include "cvfRay.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RayIntersectSpec
/// \ingroup Viewing
///
/// Class is used for picking on Model and Rendering. If contains the Ray to use for picking and
/// any other filtering settings (eg. Camera or enableMask)
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RayIntersectSpec::RayIntersectSpec(const Ray* ray)
: m_ray(ray)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RayIntersectSpec::~RayIntersectSpec()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Ray* RayIntersectSpec::ray() const
{
return m_ray.p();
}
} // 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 "cvfObject.h"
namespace cvf {
class Ray;
//==================================================================================================
//
//
//
//==================================================================================================
class RayIntersectSpec : public Object
{
public:
RayIntersectSpec(const Ray* ray);
~RayIntersectSpec();
const Ray* ray() const;
private:
cref<Ray> m_ray;
};
}
@@ -0,0 +1,424 @@
//##################################################################################################
//
// 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 "cvfRenderEngine.h"
#include "cvfRenderQueue.h"
#include "cvfPart.h"
#include "cvfDrawable.h"
#include "cvfTransform.h"
#include "cvfEffect.h"
#include "cvfRenderStateSet.h"
#include "cvfShaderProgram.h"
#include "cvfTrace.h"
#include "cvfOpenGL.h"
#include "cvfBufferObjectManaged.h"
#include "cvfMatrixState.h"
#include "cvfCamera.h"
#include <memory.h>
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderEngine
/// \ingroup Viewing
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderEngine::RenderEngine()
: m_renderedPartCount(0),
m_renderedVertexCount(0),
m_renderedTriangleCount(0),
m_renderedOpenGLPrimitiveCount(0),
m_disableDrawableRender(false),
m_disableApplyEffects(false),
m_forceImmediateMode(false),
m_enableItemCountUpdate(false)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderEngine::render(OpenGLContext* oglContext, RenderQueue* renderQueue, size_t maxNumPartsToDraw, const Camera& camera, const UniformSet* globalUniformSet)
{
CVF_ASSERT(oglContext);
CVF_ASSERT(renderQueue);
m_renderedPartCount = 0;
m_renderedVertexCount = 0;
m_renderedTriangleCount = 0;
m_renderedOpenGLPrimitiveCount = 0;
m_applyRenderStateCount = 0;
m_shaderProgramChangesCount = 0;
m_renderStateTracker.resetAndApplyDefaultRenderStates(oglContext);
// Use immediate mode either if forced or if buffer objects are not supported (OpenGL 1.5 and below)
// This is because the current fixed function rendering relies on the buffer object binding points being present
const bool renderUsingImmediateMode = (m_forceImmediateMode || !BufferObjectManaged::supportedOpenGL(oglContext));
// Does the current OpenGL context support OpenGL shaders
const bool contextSupportsShaders = ShaderProgram::supportedOpenGL(oglContext);
// Init matrix state tracker
MatrixState matrixState(camera);
uint lastAppliedMatrixStateVersionTick = matrixState.versionTick() - 1;
const Effect* prevEffect = NULL;
const RenderStateSet* prevRenderStateSet = NULL;
const ShaderProgram* prevShaderProgram = NULL;
// Track the current shader program being used.
// Will be NULL when effect has no shader program or if usage of shader program fails
ShaderProgram* shaderProgramInUse = NULL;
if (contextSupportsShaders)
{
// Start out with fixed function
ShaderProgram::useNoProgram(oglContext);
}
// Determine number of parts we'll draw
size_t numPartsInQueue = renderQueue->count();
size_t numPartsToDraw = std::min(numPartsInQueue, maxNumPartsToDraw);
bool debugLogging = CVF_SHOULD_LOG_RENDER_DEBUG(oglContext);
if (debugLogging)
{
CVF_LOG_RENDER_DEBUG(oglContext, "RenderEngine::render(), numParts=" + String(static_cast<uint>(numPartsInQueue)));
}
size_t i;
for (i = 0; i < numPartsToDraw; i++)
{
RenderItem* item = renderQueue->item(i);
CVF_ASSERT(item);
Drawable* drawable = item->drawable();
Effect* effect = item->effect();
Part* part = item->part();
CVF_ASSERT(drawable);
CVF_ASSERT(effect);
CVF_ASSERT(part);
if (debugLogging)
{
CVF_LOG_RENDER_DEBUG(oglContext, String("part#=%1, partName='%2'").arg(static_cast<uint>(i)).arg(part->name()));
}
// Update matrix state to reflect any part transformations
if (part->transform())
{
matrixState.setModelMatrix(part->transform()->worldTransform());
}
else
{
matrixState.clearModelMatrix();
}
if (effect != prevEffect && !m_disableApplyEffects)
{
const RenderStateSet* const renderStateSet = effect->renderStateSet();
if (renderStateSet != prevRenderStateSet)
{
// This apply function is designed to work with NULL pointers
m_renderStateTracker.applyRenderStates(oglContext, renderStateSet, prevRenderStateSet);
prevRenderStateSet = renderStateSet;
m_applyRenderStateCount++;
}
if (contextSupportsShaders)
{
ShaderProgram* shaderProgThisEffect = effect->shaderProgram();
if (shaderProgThisEffect != prevShaderProgram)
{
// Reset the 'in use' pointer, and only set it if we have a shader program AND we manage to use it
shaderProgramInUse = NULL;
if (shaderProgThisEffect)
{
// Will fail if program hasn't been linked
if (shaderProgThisEffect->useProgram(oglContext))
{
shaderProgramInUse = shaderProgThisEffect;
}
}
if (!shaderProgramInUse)
{
ShaderProgram::useNoProgram(oglContext);
}
prevShaderProgram = shaderProgThisEffect;
m_shaderProgramChangesCount++;
}
if (shaderProgramInUse)
{
// Apply uniforms for this shader program
// Note order of application here.
// - shader program default uniforms
// - global dynamic uniforms
// - (texture binding uniforms)
// - effect uniforms
// - fixed uniforms
// We would really like the effect's uniforms to be at the very end, but that would give inconsistent
// behavior since the fixed uniforms may get applied also when the effect does NOT change.
shaderProgramInUse->clearUniformApplyTracking();
shaderProgramInUse->applyDefaultUniforms(oglContext);
if (globalUniformSet)
{
shaderProgramInUse->applyActiveUniformsOnly(oglContext, *globalUniformSet);
}
const TextureBindings* textureBindings = static_cast<const TextureBindings*>(effect->renderStateOfType(RenderState::TEXTURE_BINDINGS));
if (textureBindings)
{
textureBindings->applySamplerTextureUnitUniforms(oglContext, shaderProgramInUse);
}
// Apply the effect's uniform last so that they win in case of clashes
const UniformSet* uniformSet = effect->uniformSet();
if (uniformSet)
{
shaderProgramInUse->applyUniforms(oglContext, *uniformSet);
}
// Still, the fixed ones have to go at the end for consistency
shaderProgramInUse->applyFixedUniforms(oglContext, matrixState);
lastAppliedMatrixStateVersionTick = matrixState.versionTick();
}
}
prevEffect = effect;
}
if (shaderProgramInUse)
{
if (lastAppliedMatrixStateVersionTick != matrixState.versionTick())
{
shaderProgramInUse->applyFixedUniforms(oglContext, matrixState);
lastAppliedMatrixStateVersionTick = matrixState.versionTick();
}
// Will check that all active uniforms in shader program have been set since last call to >clearUniformApplyTracking()
// Reports error to log if any uniforms are missing.
shaderProgramInUse->checkReportAllUniformsApplied(oglContext);
}
else
{
#ifndef CVF_OPENGL_ES
if (lastAppliedMatrixStateVersionTick != matrixState.versionTick())
{
glLoadMatrixf(matrixState.modelViewMatrix().ptr());
lastAppliedMatrixStateVersionTick = matrixState.versionTick();
}
#endif // CVF_OPENGL_ES
}
// Do actual rendering
if (!m_disableDrawableRender)
{
if (renderUsingImmediateMode)
{
drawable->renderImmediateMode(oglContext, matrixState);
}
else
{
if (shaderProgramInUse)
{
drawable->render(oglContext, shaderProgramInUse, matrixState);
}
else
{
drawable->renderFixedFunction(oglContext, matrixState);
}
}
m_renderedPartCount++;
}
// Update counters
if (m_enableItemCountUpdate)
{
m_renderedVertexCount += drawable->vertexCount();
m_renderedTriangleCount += drawable->triangleCount();
m_renderedOpenGLPrimitiveCount += drawable->faceCount();
}
}
// Do an apply with an empty new render state set to get defaults back before leaving
// This really isn't the optimal place to do this, but until we expose application of render states it's the only place
m_renderStateTracker.applyRenderStates(oglContext, NULL, prevRenderStateSet);
// For now, set back to fixed function
if (contextSupportsShaders)
{
ShaderProgram::useNoProgram(oglContext);
}
// Set back VBO settings (do we need this?)
if (BufferObjectManaged::supportedOpenGL(oglContext))
{
BufferObjectManaged::unbindAllBuffers(oglContext);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RenderEngine::renderedPartCount() const
{
return m_renderedPartCount;
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of vertices used for the last rendering
//--------------------------------------------------------------------------------------------------
size_t RenderEngine::renderedVertexCount() const
{
return m_renderedVertexCount;
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of triangles (GL_TRIANGLE) rendered in the last rendering
//--------------------------------------------------------------------------------------------------
size_t RenderEngine::renderedTriangleCount() const
{
return m_renderedTriangleCount;
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of OpenGL primitives (triangles, points, lines, etc) rendered in the last rendering
//--------------------------------------------------------------------------------------------------
size_t RenderEngine::renderedOpenGLPrimitiveCount() const
{
return m_renderedOpenGLPrimitiveCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RenderEngine::applyRenderStateCount() const
{
return m_applyRenderStateCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RenderEngine::shaderProgramChangesCount() const
{
return m_shaderProgramChangesCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderEngine::enableForcedImmediateMode(bool enable)
{
m_forceImmediateMode = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderEngine::disableRenderDrawables(bool disable)
{
m_disableDrawableRender = disable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderEngine::disableApplyEffects(bool disable)
{
m_disableApplyEffects = disable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderEngine::isForcedImmediateModeEnabled() const
{
return m_forceImmediateMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderEngine::isRenderDrawableDisabled() const
{
return m_disableDrawableRender;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderEngine::isApplyEffectsDisabled() const
{
return m_disableApplyEffects;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderEngine::enableItemCountUpdate(bool enable)
{
m_enableItemCountUpdate = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderEngine::isItemCountUpdateEnabled() const
{
return m_enableItemCountUpdate;
}
} // namespace cvf
@@ -0,0 +1,78 @@
//##################################################################################################
//
// 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"
#include "cvfRenderStateTracker.h"
namespace cvf {
class RenderQueue;
class UniformSet;
class Camera;
class OpenGLContext;
//==================================================================================================
//
// RenderEngine
//
//==================================================================================================
class RenderEngine
{
public:
RenderEngine();
void render(OpenGLContext* oglContext, RenderQueue* renderQueue, size_t maxNumPartsToDraw, const Camera& camera, const UniformSet* globalUniformSet);
size_t renderedPartCount() const;
size_t renderedVertexCount() const;
size_t renderedTriangleCount() const;
size_t renderedOpenGLPrimitiveCount() const;
size_t applyRenderStateCount() const;
size_t shaderProgramChangesCount() const;
void enableForcedImmediateMode(bool enable);
void disableRenderDrawables(bool disable);
void disableApplyEffects(bool disable);
bool isForcedImmediateModeEnabled() const;
bool isRenderDrawableDisabled() const;
bool isApplyEffectsDisabled() const;
void enableItemCountUpdate(bool enable);
bool isItemCountUpdateEnabled() const;
private:
RenderStateTracker m_renderStateTracker;
size_t m_renderedPartCount;
size_t m_renderedVertexCount;
size_t m_renderedTriangleCount;
size_t m_renderedOpenGLPrimitiveCount;
size_t m_applyRenderStateCount;
size_t m_shaderProgramChangesCount;
bool m_disableDrawableRender;
bool m_disableApplyEffects;
bool m_forceImmediateMode; // Can be used to force immediate mode drawing for debugging purposes (good old glBegin()/glEnd())
bool m_enableItemCountUpdate;
};
}
@@ -0,0 +1,142 @@
//##################################################################################################
//
// 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 "cvfRenderQueue.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderItem
/// \ingroup Viewing
///
/// Represents one item in the RenderQueue
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderItem::RenderItem()
: m_part(NULL),
m_drawable(NULL),
m_effect(NULL),
m_projectedAreaPixels(0.0f),
m_distance(0.0f)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderItem::set(Part* part, Drawable* drawable, Effect* effect, float projectedAreaPixels, float distance)
{
m_part = part;
m_drawable = drawable;
m_effect = effect;
m_projectedAreaPixels = projectedAreaPixels;
m_distance = distance;
}
//==================================================================================================
///
/// \class cvf::RenderQueue
/// \ingroup Viewing
///
/// A class for storing a queue of render items.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderQueue::hintNumEntriesToAdd(size_t numNewEntries)
{
m_renderItemsRefCounted.reserve(numNewEntries);
m_renderItemsRaw.reserve(numNewEntries);
}
//--------------------------------------------------------------------------------------------------
/// Add a RenderItem to the queue
//--------------------------------------------------------------------------------------------------
void RenderQueue::add(Part* part, Drawable* drawable, Effect* effect, float projectedAreaPixels, float distance)
{
RenderItem* item = new RenderItem;
item->set(part, drawable, effect, projectedAreaPixels, distance);
m_renderItemsRefCounted.push_back(item);
m_renderItemsRaw.push_back(item);
}
//--------------------------------------------------------------------------------------------------
/// Get the number of items in the render queue
//--------------------------------------------------------------------------------------------------
size_t RenderQueue::count() const
{
return m_renderItemsRaw.size();
}
//--------------------------------------------------------------------------------------------------
/// Sets the count to zero, but does not necessarily delete the actual contained items
//--------------------------------------------------------------------------------------------------
void RenderQueue::setCountZero()
{
removeAll();
}
//--------------------------------------------------------------------------------------------------
/// Removes all entries and releases all memory
//--------------------------------------------------------------------------------------------------
void RenderQueue::removeAll()
{
m_renderItemsRefCounted.clear();
m_renderItemsRaw.clear();
}
//--------------------------------------------------------------------------------------------------
/// Get the RenderItem at the given index
//--------------------------------------------------------------------------------------------------
RenderItem* RenderQueue::item(size_t index)
{
CVF_ASSERT(index < count());
return m_renderItemsRaw[index];
}
//--------------------------------------------------------------------------------------------------
/// Get the native rendering queue
//--------------------------------------------------------------------------------------------------
std::vector<RenderItem*>* RenderQueue::renderItemsForSorting()
{
return &m_renderItemsRaw;
}
} // namespace cvf
@@ -0,0 +1,87 @@
//##################################################################################################
//
// 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 <vector>
namespace cvf {
class Part;
class Drawable;
class Effect;
//==================================================================================================
//
// Represents one item in the RenderQueue
//
//==================================================================================================
class RenderItem : public Object
{
public:
RenderItem();
void set(Part* part, Drawable* drawable, Effect* effect, float projectedAreaPixels, float distance);
Part* part() { return m_part; }
const Part* part() const { return m_part; }
Drawable* drawable() { return m_drawable; }
const Drawable* drawable() const { return m_drawable; }
Effect* effect() { return m_effect; }
const Effect* effect() const { return m_effect; }
float projectedAreaPixels() const { return m_projectedAreaPixels; }
float distance() const { return m_distance; }
private:
Part* m_part;
Drawable* m_drawable; // The drawable for the LOD level that should be used for rendering
Effect* m_effect; // Effect for the relevant LOD level
float m_projectedAreaPixels; //
float m_distance; //
};
//==================================================================================================
//
// RenderQueue
//
//==================================================================================================
class RenderQueue : public Object
{
public:
void hintNumEntriesToAdd(size_t numNewEntries);
void add(Part* part, Drawable* drawable, Effect* effect, float projectedAreaPixels, float distance);
size_t count() const;
RenderItem* item(size_t index);
void setCountZero();
void removeAll();
std::vector<RenderItem*>* renderItemsForSorting();
private:
std::vector<ref<RenderItem> > m_renderItemsRefCounted;
std::vector<RenderItem*> m_renderItemsRaw;
};
}
@@ -0,0 +1,224 @@
//##################################################################################################
//
// 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 "cvfRenderQueueBuilder.h"
#include "cvfRenderQueue.h"
#include "cvfPartRenderHintCollection.h"
#include "cvfPart.h"
#include "cvfDrawable.h"
#include "cvfEffect.h"
#include "cvfShaderProgram.h"
#include "cvfOpenGLContext.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfBufferObjectManaged.h"
#include "cvfCamera.h"
#ifndef CVF_OPENGL_ES
#include "cvfRenderState_FF.h"
#endif
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderQueueBuilder
/// \ingroup Viewing
///
/// Populates a render queue based on a part collection. All items in the part collection will
/// result in a corresponding RenderItem.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor. Sets up the object with the part collection to use in populateRenderQueue()
//--------------------------------------------------------------------------------------------------
RenderQueueBuilder::RenderQueueBuilder(PartRenderHintCollection* srcPartCollection, OpenGLContext* oglContext, const Camera* camera)
{
CVF_ASSERT(srcPartCollection);
CVF_ASSERT(oglContext);
CVF_ASSERT(camera);
m_srcPartCollection = srcPartCollection;
m_oglContext = oglContext;
m_camera = camera;
m_requireDistance = false;
m_requirePixelArea = false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderQueueBuilder::setFixedEffect(Effect* effect)
{
m_fixedEffect = effect;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderQueueBuilder::setRequireDistance(bool requireDistance)
{
m_requireDistance = requireDistance;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderQueueBuilder::setRequirePixelArea(bool requirePixelArea)
{
m_requirePixelArea = requirePixelArea;
}
//--------------------------------------------------------------------------------------------------
/// Populate the render queue based on the input parts
///
/// \param renderQueue The render queue that should be populated
///
/// Currently this function will:
/// - Populate the RenderQueue with RenderItem objects
/// - Link all referenced GLShaderProgram objects
///
/// Future tasks (?):
/// - Do LOD evaluation to determine LOD level for drawables and effects
/// - Perform VBO and display list setup
///
/// To be determined:
/// - What should happen to parts that end up having no effect or no drawable?
/// - Currently, parts ending up with \b no drawable are \b not added to the queue.
/// - Parts with a drawable, but without any effect or with illegal effects (shader program
/// that fails to link) will get added to the queue
//--------------------------------------------------------------------------------------------------
void RenderQueueBuilder::populateRenderQueue(RenderQueue* renderQueue)
{
CVF_ASSERT(renderQueue);
size_t srcPartCount = m_srcPartCollection->count();
renderQueue->removeAll();
renderQueue->hintNumEntriesToAdd(srcPartCount);
// Extract raw pointer to any fixed effect
Effect* fixedEffect = m_fixedEffect.p();
OpenGLResourceManager* resourceManager = m_oglContext->resourceManager();
resourceManager->evictOrphanedOpenGLResources(m_oglContext.p());
// Does OpenGL support buffer objects?
const bool oglSupportsBufferObjects = BufferObjectManaged::supportedOpenGL(m_oglContext.p());
size_t i;
for (i = 0; i < srcPartCount; i++)
{
Part* part = m_srcPartCollection->part(i);
CVF_ASSERT(part);
// TODO Must do LOD evaluation for geometry lod
const int drawableLod = 0;
Drawable* drawable = part->drawable(drawableLod);
CVF_ASSERT(drawable);
Effect* effect = fixedEffect;
if (!effect)
{
// TODO Must do LOD evaluation for effect lod
const int effectLod = 0;
effect = part->effect(effectLod);
}
CVF_ASSERT(effect);
bool canAddToQueue = true;
// TODO rework this when we get uniforms in place
ShaderProgram* shaderProg = effect->shaderProgram();
if (shaderProg)
{
// For now, don't add parts where program fails to compile
if (!shaderProg->linkProgram(m_oglContext.p()))
{
// TODO Should we do any error reporting here?
// For now we just don't add the effect to the render queue
canAddToQueue = false;
}
}
// Create and upload data to buffer objects (VBOs)
// Whether anything actually gets uploaded is controlled by the drawable itself
if (oglSupportsBufferObjects)
{
drawable->createUploadBufferObjectsGPU(m_oglContext.p());
}
// Create/Setup the textures
TextureBindings* textureBindings = static_cast<TextureBindings*>(effect->renderStateOfType(RenderState::TEXTURE_BINDINGS));
if (textureBindings && canAddToQueue)
{
textureBindings->setupTextures(m_oglContext.p());
}
#ifndef CVF_OPENGL_ES
TextureMapping_FF* textureMapping = static_cast<TextureMapping_FF*>(effect->renderStateOfType(RenderState::TEXTURE_MAPPING_FF));
if (textureMapping && canAddToQueue)
{
textureMapping->setupTexture(m_oglContext.p());
}
#endif
if (canAddToQueue)
{
float distance = -1.0f;
float pixelArea = -1.0f;
// Check if we need distance and pixel area. If it is provided by the PartRenderHint we use that.
// If not, we compute it here if it is required
PartRenderHint* hint = m_srcPartCollection->renderHint(i);
if (hint)
{
distance = hint->centerDistance();
pixelArea = hint->projectedAreaPixels();
}
if (m_requireDistance && (distance == -1.0f))
{
const BoundingBox& bb = part->boundingBox();
CVF_ASSERT(bb.isValid());
distance = static_cast<float>((m_camera->position() - bb.center()).length());
}
if (m_requirePixelArea && (pixelArea == -1.0f))
{
const BoundingBox& bb = part->boundingBox();
CVF_ASSERT(bb.isValid());
pixelArea = static_cast<float>(m_camera->computeProjectedBoundingSpherePixelArea(bb.center(), bb.radius()));
}
renderQueue->add(part, drawable, effect, pixelArea, distance);
}
}
}
} // 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 "cvfObject.h"
namespace cvf {
class PartRenderHintCollection;
class RenderQueue;
class Effect;
class Camera;
class OpenGLContext;
//==================================================================================================
//
// Populates a render queue based on a part collection
//
//==================================================================================================
class RenderQueueBuilder
{
public:
RenderQueueBuilder(PartRenderHintCollection* srcPartCollection, OpenGLContext* oglContext, const Camera* camera);
void setFixedEffect(Effect* effect);
void setRequireDistance(bool requireDistance);
void setRequirePixelArea(bool requirePixelArea);
void populateRenderQueue(RenderQueue* renderQueue);
private:
ref<PartRenderHintCollection> m_srcPartCollection; // The source part collection
ref<OpenGLContext> m_oglContext; // OpenGLContext to use. This responsibility should be removed from the render queue builder
cref<Camera> m_camera; // Camera used when there is a need for computing distance and/or pixel area
ref<Effect> m_fixedEffect; // If specified, all render items in the queue will have this effect
bool m_requireDistance;
bool m_requirePixelArea;
};
}
@@ -0,0 +1,428 @@
//##################################################################################################
//
// 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 "cvfRenderQueueSorter.h"
#include "cvfRenderQueue.h"
#include "cvfEffect.h"
#include "cvfPart.h"
#include "cvfMath.h"
#include "cvfTBBControl.h"
#include <algorithm>
#ifdef CVF_USE_TBB
#ifdef WIN32
#pragma warning (push)
#pragma warning (disable: 4668 4365)
#include "tbb/parallel_sort.h"
#pragma warning (pop)
#endif
#endif
namespace cvf {
//==================================================================================================
//
// Helper class that wraps the sorting algorithms and chooses between std and TBB impl
//
//==================================================================================================
class SortAlgorithms
{
public:
/// Constructor, configures usage of TBB or not
// -----------------------------------------------------
SortAlgorithms(bool useTBB)
{
m_useTBB = useTBB;
#ifndef CVF_USE_TBB
m_useTBB = false;
#endif
}
/// Wrapper for std::sort() and tbb::parallell_sort()
// -----------------------------------------------------
template<typename RandomAccessIterator, typename Compare>
void sort(RandomAccessIterator begin, RandomAccessIterator end, const Compare& comp)
{
#ifdef CVF_USE_TBB
if (m_useTBB)
{
tbb::parallel_sort(begin, end, comp);
}
else
#endif
{
std::sort(begin, end, comp);
}
}
/// Wrapper for std::partial_sort(), no corresponding TBB
// -----------------------------------------------------
template<typename RandomAccessIterator, typename Compare>
void partial_sort(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end, const Compare& comp)
{
std::partial_sort(begin, middle, end, comp);
}
private:
bool m_useTBB;
};
//==================================================================================================
//
// Class with compare function used by MINIMAL strategy
//
//==================================================================================================
class ComparatorMinimal
{
public:
bool operator()(const RenderItem* a, const RenderItem* b) const
{
CVF_TIGHT_ASSERT(a && b);
CVF_TIGHT_ASSERT(a->part());
CVF_TIGHT_ASSERT(b->part());
// Currently, only priority
return (a->part()->priority() < b->part()->priority());
}
};
//==================================================================================================
//
// Class with compare function used by EFFECT_ONLY strategy
//
//==================================================================================================
class ComparatorEffectOnly
{
public:
bool operator()(const RenderItem* a, const RenderItem* b) const
{
CVF_TIGHT_ASSERT(a && b);
CVF_TIGHT_ASSERT(a->part());
CVF_TIGHT_ASSERT(b->part());
// Always do priority first
if (a->part()->priority() != b->part()->priority())
{
return (a->part()->priority() < b->part()->priority());
}
else
{
return (a->effect() < b->effect());
}
}
};
//==================================================================================================
//
// Class with compare function used by STANDARD strategy
//
//==================================================================================================
class ComparatorStandard
{
public:
bool operator()(const RenderItem* a, const RenderItem* b) const
{
CVF_TIGHT_ASSERT(a && b);
CVF_TIGHT_ASSERT(a->effect());
CVF_TIGHT_ASSERT(b->effect());
// This sorter is currently experimental!!
// Sort order is:
// - priority
// - shader program
// - state set
// - effect
// - drawable
if (a->part()->priority() != b->part()->priority())
{
return (a->part()->priority() < b->part()->priority());
}
else if (a->effect()->shaderProgram() != b->effect()->shaderProgram())
{
return (a->effect()->shaderProgram() < b->effect()->shaderProgram());
}
else if (a->effect()->renderStateSet() != b->effect()->renderStateSet())
{
return (a->effect()->renderStateSet() < b->effect()->renderStateSet());
}
else if (a->effect() != b->effect())
{
return (a->effect() < b->effect());
}
else
{
return (a->drawable() < b->drawable());
}
}
};
//==================================================================================================
//
// Class with compare function used by BACK_TO_FRONT strategy
//
//==================================================================================================
class ComparatorBackToFront
{
public:
bool operator()(const RenderItem* a, const RenderItem* b) const
{
CVF_TIGHT_ASSERT(a && b);
return (a->distance() > b->distance());
}
};
//==================================================================================================
//
// Comparator class for comparing distance
//
//==================================================================================================
class ComparatorDistance
{
public:
bool operator()(const RenderItem* a, const RenderItem* b) const
{
CVF_TIGHT_ASSERT(a && b);
return (a->distance() < b->distance());
}
};
//==================================================================================================
//
// Comparator class for comparing distance
//
//==================================================================================================
class ComparatorArea
{
public:
bool operator()(const RenderItem* a, const RenderItem* b) const
{
CVF_TIGHT_ASSERT(a && b);
return (a->projectedAreaPixels() > b->projectedAreaPixels());
}
};
//==================================================================================================
///
/// \class cvf::RenderQueueSorter
/// \ingroup Viewing
///
/// Base class for all classes that sorts the render queue
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderQueueSorter::RenderQueueSorter()
{
}
//==================================================================================================
///
/// \class cvf::RenderQueueSorterBasic
/// \ingroup Viewing
///
/// Basic render queue sorter with an enumerated strategy.
///
/// Does a single sorting pass with the specified strategy.
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderQueueSorterBasic::RenderQueueSorterBasic(SortStrategy strategy)
: RenderQueueSorter()
{
m_strategy = strategy;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderQueueSorterBasic::requireDistance() const
{
if (m_strategy == BACK_TO_FRONT)
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderQueueSorterBasic::requirePixelArea() const
{
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderQueueSorterBasic::SortStrategy RenderQueueSorterBasic::strategy() const
{
return m_strategy;
}
//--------------------------------------------------------------------------------------------------
/// Sort the render queue using the configured strategy
//--------------------------------------------------------------------------------------------------
void RenderQueueSorterBasic::sort(RenderQueue* renderQueue) const
{
std::vector<RenderItem*>* renderItems = renderQueue->renderItemsForSorting();
CVF_TIGHT_ASSERT(renderItems);
bool useTBB = TBBControl::isEnabled();
SortAlgorithms sa(useTBB);
if (m_strategy == MINIMAL)
{
sa.sort(renderItems->begin(), renderItems->end(), ComparatorMinimal());
}
else if (m_strategy == EFFECT_ONLY)
{
sa.sort(renderItems->begin(), renderItems->end(), ComparatorEffectOnly());
}
else if (m_strategy == STANDARD)
{
sa.sort(renderItems->begin(), renderItems->end(), ComparatorStandard());
}
else if (m_strategy == BACK_TO_FRONT)
{
sa.sort(renderItems->begin(), renderItems->end(), ComparatorBackToFront());
}
else
{
CVF_FAIL_MSG("Unsupported sort strategy");
}
}
//==================================================================================================
///
/// \class cvf::RenderQueueSorterTargetFramerate
/// \ingroup Viewing
///
///
///
//==================================================================================================
RenderQueueSorterTargetFramerate::RenderQueueSorterTargetFramerate()
: RenderQueueSorter()
{
m_maxNumPartsToDraw = std::numeric_limits<size_t>::max();
m_numPartsToDistanceSort = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderQueueSorterTargetFramerate::requireDistance() const
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RenderQueueSorterTargetFramerate::requirePixelArea() const
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderQueueSorterTargetFramerate::setMaxNumPartsToDraw(size_t maxNumPartsToDraw)
{
m_maxNumPartsToDraw = maxNumPartsToDraw;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderQueueSorterTargetFramerate::clearMaxNumPartsToDraw()
{
m_maxNumPartsToDraw = std::numeric_limits<size_t>::max();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderQueueSorterTargetFramerate::setNumPartsToDistanceSort(size_t numPartsToDistanceSort)
{
m_numPartsToDistanceSort = numPartsToDistanceSort;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderQueueSorterTargetFramerate::sort(RenderQueue* renderQueue) const
{
std::vector<RenderItem*>* renderItems = renderQueue->renderItemsForSorting();
CVF_TIGHT_ASSERT(renderItems);
std::vector<RenderItem*>::difference_type numItemsToDraw = static_cast<std::vector<RenderItem*>::difference_type>(std::min(m_maxNumPartsToDraw, renderItems->size()));
std::vector<RenderItem*>::difference_type numItemsToDistSort = static_cast<std::vector<RenderItem*>::difference_type>(std::min(m_numPartsToDistanceSort, renderItems->size()));
bool useTBB = TBBControl::isEnabled();
SortAlgorithms sa(useTBB);
sa.partial_sort(renderItems->begin(), renderItems->begin() + numItemsToDistSort, renderItems->end(), ComparatorDistance());
sa.sort(renderItems->begin(), renderItems->begin() + numItemsToDistSort, ComparatorEffectOnly());
sa.sort(renderItems->begin() + numItemsToDistSort, renderItems->end(), ComparatorArea());
sa.sort(renderItems->begin() + numItemsToDistSort, renderItems->begin() + static_cast<int>(numItemsToDraw), ComparatorEffectOnly());
sa.sort(renderItems->begin() + numItemsToDraw, renderItems->end(), ComparatorEffectOnly());
}
} // namespace cvf
@@ -0,0 +1,104 @@
//##################################################################################################
//
// 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 RenderQueue;
class RenderItem;
//==================================================================================================
//
//
//
//==================================================================================================
class RenderQueueSorter : public Object
{
public:
RenderQueueSorter();
virtual void sort(RenderQueue* renderQueue) const = 0;
virtual bool requireDistance() const = 0;
virtual bool requirePixelArea() const = 0;
};
//==================================================================================================
//
//
//
//==================================================================================================
class RenderQueueSorterBasic : public RenderQueueSorter
{
public:
enum SortStrategy
{
MINIMAL, // Does a minimum of sorting, currently only sorts on priority
EFFECT_ONLY, // A simple render queue sorter ordering the items by effect object (and priority)
STANDARD, // Currently experimental, but should eventually become the default sorter
BACK_TO_FRONT // Sorts parts in a back to front order (useful for e.g. transparency)
};
public:
RenderQueueSorterBasic(SortStrategy strategy);
SortStrategy strategy() const;
virtual void sort(RenderQueue* renderQueue) const;
virtual bool requireDistance() const;
virtual bool requirePixelArea() const;
private:
SortStrategy m_strategy;
};
//==================================================================================================
//
//
//
//==================================================================================================
class RenderQueueSorterTargetFramerate : public RenderQueueSorter
{
public:
RenderQueueSorterTargetFramerate();
void setMaxNumPartsToDraw(size_t maxNumPartsToDraw);
void clearMaxNumPartsToDraw();
void setNumPartsToDistanceSort(size_t numPartsToDistanceSort);
virtual void sort(RenderQueue* renderQueue) const;
virtual bool requireDistance() const;
virtual bool requirePixelArea() const;
private:
size_t m_maxNumPartsToDraw; // The maximum number of parts we will draw. Will do as little work as possible for the remaining parts.
size_t m_numPartsToDistanceSort; // The number of parts that will be sorted according to distance.
};
}
@@ -0,0 +1,325 @@
//##################################################################################################
//
// 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 "cvfRenderSequence.h"
#include "cvfRendering.h"
#include "cvfScene.h"
#include "cvfModel.h"
#include "cvfColor4.h"
#include "cvfOpenGL.h"
#include "cvfOpenGLCapabilities.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::RenderSequence
/// \ingroup Viewing
///
///
//==================================================================================================
//------------------------------------------------------------------------------------------------
///
//------------------------------------------------------------------------------------------------
RenderSequence::RenderSequence()
{
}
//------------------------------------------------------------------------------------------------
/// Get the number of render passes in the sequence
//------------------------------------------------------------------------------------------------
uint RenderSequence::renderingCount() const
{
return static_cast<uint>(m_renderings.size());
}
//------------------------------------------------------------------------------------------------
/// Add a rendering pass
//------------------------------------------------------------------------------------------------
void RenderSequence::addRendering(Rendering* rendering)
{
CVF_ASSERT(rendering);
m_renderings.push_back(rendering);
}
//------------------------------------------------------------------------------------------------
/// Get a rendering pass by index
//------------------------------------------------------------------------------------------------
Rendering* RenderSequence::rendering(uint index)
{
CVF_ASSERT(index < renderingCount());
return m_renderings[index].p();
}
//------------------------------------------------------------------------------------------------
/// Get a rendering pass by index
//------------------------------------------------------------------------------------------------
const Rendering* RenderSequence::rendering(uint index) const
{
CVF_ASSERT(index < renderingCount());
return m_renderings[index].p();
}
//--------------------------------------------------------------------------------------------------
/// Get pointer to the first rendering pass if any.
///
/// This function is safe to call even if there are no renderings. In this case NULL will be returned
//--------------------------------------------------------------------------------------------------
Rendering* RenderSequence::firstRendering()
{
if (m_renderings.empty())
{
return NULL;
}
else
{
return m_renderings[0].p();
}
}
//--------------------------------------------------------------------------------------------------
/// Get pointer to the first rendering pass if any.
///
/// This function is safe to call even if there are no renderings. In this case NULL will be returned
//--------------------------------------------------------------------------------------------------
const Rendering* RenderSequence::firstRendering() const
{
if (m_renderings.empty())
{
return NULL;
}
else
{
return m_renderings[0].p();
}
}
//------------------------------------------------------------------------------------------------
/// Remove all rendering passes
//------------------------------------------------------------------------------------------------
void RenderSequence::removeAllRenderings()
{
m_renderings.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RenderSequence::removeRendering(const Rendering* rendering)
{
CVF_ASSERT(rendering);
m_renderings.erase(rendering);
}
//------------------------------------------------------------------------------------------------
/// Draw all the rendering passes in the sequence
//------------------------------------------------------------------------------------------------
void RenderSequence::render(OpenGLContext* oglContext)
{
m_performanceInfo.resetCurrentTimers();
uint numPasses = renderingCount();
preRenderApplyExpectedOpenGLState(oglContext);
uint i;
for (i = 0; i < numPasses; i++)
{
Rendering* rendering = m_renderings[i].p();
CVF_ASSERT(rendering);
rendering->render(oglContext);
m_performanceInfo.update(rendering->performanceInfo());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
BoundingBox RenderSequence::boundingBox() const
{
BoundingBox bb;
uint numPasses = renderingCount();
uint i;
for (i = 0; i < numPasses; i++)
{
const Rendering* rendering = m_renderings[i].p();
CVF_ASSERT(rendering);
bb.add(rendering->boundingBox());
}
return bb;
}
//--------------------------------------------------------------------------------------------------
/// Get the performance info for the last rendering (last call to render()).
//--------------------------------------------------------------------------------------------------
const PerformanceInfo&RenderSequence::performanceInfo() const
{
return m_performanceInfo;
}
//--------------------------------------------------------------------------------------------------
/// Delete or release all OpenGL resources used by all parts in all renderings.
///
/// Will iterate over all the contents of the rendering sequence and delete or release any OpenGL
/// resources that are being held.
///
/// \warning The OpenGL context in which the resources were created or a context that is being
/// shared must be current in the calling thread.
/// \warning Some resources are merely released (by unreferencing the object) so in order to assure
/// that the actual OpenGL resources get deleted, you may have to do cleanup through the
/// OpenGLResourceManager as afterwards (eg. deleteOrphanedManagedBufferObjects())
//--------------------------------------------------------------------------------------------------
void RenderSequence::deleteOrReleaseOpenGLResources(OpenGLContext* oglContext)
{
CVF_ASSERT(oglContext);
uint numRenderings = renderingCount();
uint i;
for (i = 0; i < numRenderings; i++)
{
Rendering* rendering = m_renderings.at(i);
CVF_ASSERT(rendering);
Scene* scene = rendering->scene();
if (scene)
{
uint numModels = scene->modelCount();
uint j;
for (j = 0; j < numModels; j++)
{
Model* model = scene->model(j);
model->deleteOrReleaseOpenGLResources(oglContext);
}
}
}
}
//--------------------------------------------------------------------------------------------------
/// Apply the OpenGL states we expect before rendering
///
/// The OpenGL states we set here will be a moving target. The main focus is on states that are
/// not captured through our RenderState objects. We do try and set all possible OpenGL states
/// in this function, but rather the ones that are likely to have been set by our caller and that
/// are likely to affect our rendering.
//--------------------------------------------------------------------------------------------------
void RenderSequence::preRenderApplyExpectedOpenGLState(OpenGLContext* oglContext)
{
CVF_CALLSITE_OPENGL(oglContext);
CVF_CHECK_OGL(oglContext);
const OpenGLCapabilities* oglCaps = oglContext->capabilities();
// The following settings match the OpenGL defaults
// ------------------------------------------------
if (oglCaps->supportsOpenGL2())
{
glActiveTexture(GL_TEXTURE0);
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glDisable(GL_SCISSOR_TEST);
CVF_CHECK_OGL(oglContext);
#ifndef CVF_OPENGL_ES
if (oglCaps->supportsFixedFunction())
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glShadeModel(GL_SMOOTH);
glDisable(GL_NORMALIZE);
glClearDepth(1);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
CVF_CHECK_OGL(oglContext);
// These settings differ from OpenGL defaults,
// but form a suitable starting point for rendering with CeeViz
// ------------------------------------------------
// TODO Work out a proper solution for this
// Should probably add some RenderState that encapsulates a light source
const Vec4f lightPosition(0.5f, 5.0f, 7.0f, 1.0f);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition.ptr());
const Vec3f spotDirection(0.0f, 0.0f, -1.0f);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotDirection.ptr());
glLightf( GL_LIGHT0, GL_SPOT_EXPONENT, 0.0f);
glLightf( GL_LIGHT0, GL_SPOT_CUTOFF, 180.0f);
const Color4f amb (0.0f, 0.0f, 0.0f, 1.0f);
const Color4f diff(1.0f, 1.0f, 1.0f, 1.0f);
const Color4f spec(1.0f, 1.0f, 1.0f, 1.0f);
glLightfv(GL_LIGHT0, GL_AMBIENT, amb.ptr());
glLightfv(GL_LIGHT0, GL_DIFFUSE, diff.ptr());
glLightfv(GL_LIGHT0, GL_SPECULAR, spec.ptr());
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.0f);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f);
glEnable(GL_LIGHT0);
CVF_CHECK_OGL(oglContext);
}
#endif
}
} // namespace cvf
@@ -0,0 +1,67 @@
//##################################################################################################
//
// 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 "cvfBoundingBox.h"
#include "cvfPerformanceInfo.h"
namespace cvf {
class Rendering;
class OpenGLContext;
//==================================================================================================
//
// RenderSequence
//
//==================================================================================================
class RenderSequence : public Object
{
public:
RenderSequence();
uint renderingCount() const;
void addRendering(Rendering* rendering);
Rendering* firstRendering();
const Rendering* firstRendering() const;
Rendering* rendering(uint index);
const Rendering* rendering(uint index) const;
void removeAllRenderings();
void removeRendering(const Rendering* rendering);
BoundingBox boundingBox() const;
void render(OpenGLContext* oglContext);
const PerformanceInfo& performanceInfo() const;
void deleteOrReleaseOpenGLResources(OpenGLContext* oglContext);
private:
static void preRenderApplyExpectedOpenGLState(OpenGLContext* oglContext);
private:
Collection<Rendering> m_renderings; // One rendering per render pass
PerformanceInfo m_performanceInfo; // Performance summary for this view
};
}
@@ -0,0 +1,930 @@
//##################################################################################################
//
// 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 "cvfRendering.h"
#include "cvfScene.h"
#include "cvfModel.h"
#include "cvfCamera.h"
#include "cvfPartRenderHintCollection.h"
#include "cvfRenderQueue.h"
#include "cvfRenderQueueBuilder.h"
#include "cvfRenderQueueSorter.h"
#include "cvfEffect.h"
#include "cvfTimer.h"
#include "cvfOpenGL.h"
#include "cvfFramebufferObject.h"
#include "cvfOverlayItem.h"
#include "cvfDynamicUniformSet.h"
#include "cvfUniformSet.h"
#include "cvfRay.h"
#include "cvfTrace.h"
#include "cvfShaderProgram.h"
#include "cvfRayIntersectSpec.h"
#include "cvfHitItemCollection.h"
namespace cvf {
// Internal
struct OverlayItemLayout
{
ref<OverlayItem> overlayItem;
OverlayItem::LayoutCorner corner;
OverlayItem::LayoutDirection direction;
};
//==================================================================================================
///
/// \class cvf::Rendering
/// \ingroup Viewing
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
Rendering::Rendering(const String& renderingName)
: m_renderingName(renderingName),
m_enableMask(0xffffffff),
m_clearMode(Viewport::CLEAR_COLOR_DEPTH),
m_maxNumPartsToDraw(std::numeric_limits<size_t>::max()),
m_enablePerformanceTiming(true)
{
m_camera = new Camera;
m_visibleParts = new PartRenderHintCollection;
// Initialize with minimal sorting (just priorities)
m_renderQueueSorter = new RenderQueueSorterBasic(RenderQueueSorterBasic::MINIMAL);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Rendering::~Rendering()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::setRenderingName(const String& renderingName)
{
m_renderingName = renderingName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String Rendering::renderingName() const
{
return m_renderingName;
}
//--------------------------------------------------------------------------------------------------
/// Set the scene to be rendered
///
/// The specified scene can be shared among many renderings.
//--------------------------------------------------------------------------------------------------
void Rendering::setScene(Scene* scene)
{
m_scene = scene;
m_visibleParts->removeAll();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Scene* Rendering::scene()
{
return m_scene.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Scene* Rendering::scene() const
{
return m_scene.p();
}
//--------------------------------------------------------------------------------------------------
/// Render the configured scene using the current Camera
//--------------------------------------------------------------------------------------------------
void Rendering::render(OpenGLContext* oglContext)
{
CVF_ASSERT(m_camera.notNull() && m_camera->viewport());
bool debugLogging = CVF_SHOULD_LOG_RENDER_DEBUG(oglContext);
if (debugLogging)
{
CVF_LOG_RENDER_DEBUG(oglContext, String("Entering Rendering::render(), renderingName='%1'").arg(m_renderingName));
}
m_performanceInfo.clear();
ref<Timer> renderTimer;
if (m_enablePerformanceTiming)
{
renderTimer = new Timer;
}
// Compute visible parts
// -------------------------------------------------------------------------
m_visibleParts->setCountZero();
if (m_scene.notNull())
{
m_scene->findVisibleParts(m_visibleParts.p(), *m_camera.p(), m_cullSettings, m_enableMask);
}
if (renderTimer.notNull())
{
m_performanceInfo.computeVisiblePartsTime = renderTimer->lapTime();
}
m_performanceInfo.visiblePartsCount = m_visibleParts->count();
// Setup FBO
// -------------------------------------------------------------------------
if (m_targetFrameBuffer.notNull())
{
// Option to sync FBO size to viewport size
m_targetFrameBuffer->applyOpenGL(oglContext);
String failReason;
if (!m_targetFrameBuffer->isFramebufferComplete(oglContext, &failReason))
{
Trace::show(failReason);
return;
}
}
else
{
#ifndef CVF_OPENGL_ES
if (FramebufferObject::supportedOpenGL(oglContext))
{
FramebufferObject::useDefaultWindowFramebuffer(oglContext);
}
#endif
}
// Setup camera and view
// -------------------------------------------------------------------------
m_camera->viewport()->applyOpenGL(oglContext, m_clearMode);
m_camera->applyOpenGL();
// Update dynamic uniforms and dynamic uniform sets
// -------------------------------------------------------------------------
updateDynamicUniformSets();
updateAndCombineGlobalDynamicUniformSets();
// Build the render queue
// -------------------------------------------------------------------------
RenderQueueBuilder builder(m_visibleParts.p(), oglContext, m_camera.p());
builder.setFixedEffect(m_effectOverride.p());
if (m_renderQueueSorter.notNull())
{
builder.setRequireDistance(m_renderQueueSorter->requireDistance());
builder.setRequirePixelArea(m_renderQueueSorter->requirePixelArea());
}
RenderQueue renderQueue;
builder.populateRenderQueue(&renderQueue);
if (renderTimer.notNull())
{
m_performanceInfo.buildRenderQueueTime = renderTimer->lapTime();
}
// Sort the render queue
// -------------------------------------------------------------------------
if (m_renderQueueSorter.notNull())
{
m_renderQueueSorter->sort(&renderQueue);
if (renderTimer.notNull())
{
m_performanceInfo.sortRenderQueueTime = renderTimer->lapTime();
}
}
// Render the scene
// -------------------------------------------------------------------------
const UniformSet* globalUniformSet = m_combinedGlobalUniformSet.p();
size_t numPartsToDraw = std::min(m_maxNumPartsToDraw, renderQueue.count());
m_renderEngine.render(oglContext, &renderQueue, numPartsToDraw, *m_camera, globalUniformSet);
if (renderTimer.notNull())
{
m_performanceInfo.renderEngineTime = renderTimer->lapTime();
}
// Render the overlay items
// Use software rendering if forced or if no support for Shader Programs
bool useSoftwareRendering = m_renderEngine.isForcedImmediateModeEnabled() || !ShaderProgram::supportedOpenGL(oglContext);
renderOverlayItems(oglContext, useSoftwareRendering);
// Update counters
m_performanceInfo.renderedPartsCount = m_renderEngine.renderedPartCount();
m_performanceInfo.vertexCount = m_renderEngine.renderedVertexCount();
m_performanceInfo.triangleCount = m_renderEngine.renderedTriangleCount();
m_performanceInfo.openGLPrimitiveCount = m_renderEngine.renderedOpenGLPrimitiveCount();
m_performanceInfo.applyRenderStateCount = m_renderEngine.applyRenderStateCount();
m_performanceInfo.shaderProgramChangesCount = m_renderEngine.shaderProgramChangesCount();
// Last update before we exit, total render time for this rendering
if (renderTimer.notNull())
{
m_performanceInfo.totalDrawTime = renderTimer->time();
}
if (debugLogging)
{
CVF_LOG_RENDER_DEBUG(oglContext, String("Exiting Rendering::render(), renderingName='%1'").arg(m_renderingName));
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::renderOverlayItems(OpenGLContext* oglContext, bool useSoftwareRendering)
{
OverlayItemRectMap itemRectMap;
calculateOverlayItemLayout(&itemRectMap);
OverlayItemRectMap::iterator it;
for (it = itemRectMap.begin(); it != itemRectMap.end(); ++it)
{
OverlayItem* item = it->first;
Rectui rect = it->second;
if (useSoftwareRendering)
{
item->renderSoftware(oglContext, rect.min(), Vec2ui(rect.width(), rect.height()));
}
else
{
item->render(oglContext, rect.min(), Vec2ui(rect.width(), rect.height()));
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::calculateOverlayItemLayout(OverlayItemRectMap* itemRectMap)
{
calculateOverlayItemLayout(itemRectMap, OverlayItem::TOP_LEFT, OverlayItem::HORIZONTAL);
calculateOverlayItemLayout(itemRectMap, OverlayItem::TOP_LEFT, OverlayItem::VERTICAL);
calculateOverlayItemLayout(itemRectMap, OverlayItem::TOP_RIGHT, OverlayItem::HORIZONTAL);
calculateOverlayItemLayout(itemRectMap, OverlayItem::TOP_RIGHT, OverlayItem::VERTICAL);
calculateOverlayItemLayout(itemRectMap, OverlayItem::BOTTOM_LEFT, OverlayItem::HORIZONTAL);
calculateOverlayItemLayout(itemRectMap, OverlayItem::BOTTOM_LEFT, OverlayItem::VERTICAL);
calculateOverlayItemLayout(itemRectMap, OverlayItem::BOTTOM_RIGHT, OverlayItem::HORIZONTAL);
calculateOverlayItemLayout(itemRectMap, OverlayItem::BOTTOM_RIGHT, OverlayItem::VERTICAL);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::calculateOverlayItemLayout(OverlayItemRectMap* itemRectMap, OverlayItem::LayoutCorner corner, OverlayItem::LayoutDirection direction)
{
const uint border = 3;
const Vec2ui vpSize = Vec2ui(m_camera->viewport()->width(), m_camera->viewport()->height());
Vec2ui cursor(0,0);
switch (corner)
{
case OverlayItem::TOP_LEFT: cursor.set(border, vpSize.y() - border); break;
case OverlayItem::TOP_RIGHT: cursor.set(vpSize.x() - border, vpSize.y() - border); break;
case OverlayItem::BOTTOM_LEFT: cursor.set(border, border); break;
case OverlayItem::BOTTOM_RIGHT: cursor.set(vpSize.x() - border, border); break;
default: cursor.set(border,border);
}
size_t numOverlayItems = m_overlayItems.size();
size_t i;
for (i = 0; i < numOverlayItems; i++)
{
OverlayItemLayout item = m_overlayItems.at(i);
if ((item.corner == corner) && (item.direction == direction))
{
CVF_ASSERT(item.overlayItem.notNull());
// Find this position and size
Vec2ui position = cursor;
Vec2ui size = item.overlayItem->sizeHint();
if ((corner == OverlayItem::TOP_RIGHT) || (corner == OverlayItem::BOTTOM_RIGHT))
{
position.x() -= size.x();
}
if ((corner == OverlayItem::TOP_LEFT) || (corner == OverlayItem::TOP_RIGHT))
{
position.y() -= size.y();
}
// Store the position in the map
Rectui rect(position.x(), position.y(), size.x(), size.y());
(*itemRectMap)[item.overlayItem.p()] = rect;
// Find next position, moving the cursor
if (direction == OverlayItem::HORIZONTAL)
{
if ((corner == OverlayItem::TOP_LEFT) || (corner == OverlayItem::BOTTOM_LEFT))
{
cursor.x() += (size.x() + border);
}
else
{
cursor.x() -= (size.x() + border);
}
}
else if (direction == OverlayItem::VERTICAL)
{
if ((corner == OverlayItem::BOTTOM_LEFT) || (corner == OverlayItem::BOTTOM_RIGHT))
{
cursor.y() += (size.y() + border);
}
else
{
cursor.y() -= (size.y() + border);
}
}
else
{
CVF_FAIL_MSG("Unhandled OverlayItem::LayoutDirection");
}
}
}
}
//--------------------------------------------------------------------------------------------------
/// Set the camera used in this rendering. Can be shared with other renderings etc.
//--------------------------------------------------------------------------------------------------
void Rendering::setCamera(Camera* camera)
{
m_camera = camera;
}
//--------------------------------------------------------------------------------------------------
/// Get the camera used in this rendering
//--------------------------------------------------------------------------------------------------
Camera* Rendering::camera()
{
return m_camera.p();
}
//--------------------------------------------------------------------------------------------------
/// Get the camera used in this rendering
//--------------------------------------------------------------------------------------------------
const Camera* Rendering::camera() const
{
return m_camera.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderEngine* Rendering::renderEngine()
{
return &m_renderEngine;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RenderEngine* Rendering::renderEngine() const
{
return &m_renderEngine;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::setTargetFrameBuffer(FramebufferObject* frameBuffer)
{
m_targetFrameBuffer = frameBuffer;
}
//--------------------------------------------------------------------------------------------------
/// Set the sorter to use when sorting the render queue.
///
/// Can specify NULL for no sorting.
//--------------------------------------------------------------------------------------------------
void Rendering::setRenderQueueSorter(RenderQueueSorter* sorter)
{
m_renderQueueSorter = sorter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RenderQueueSorter* Rendering::renderQueueSorter()
{
return m_renderQueueSorter.p();
}
//--------------------------------------------------------------------------------------------------
/// Create a new RayIntersectSpec object based on this rendering and the specified coordinates
///
/// The coordinates (\a winCoordX & \a winCoordY) are assumed to be in the window coordinate system
/// where <0,0> if in the top left corner.
//--------------------------------------------------------------------------------------------------
ref<RayIntersectSpec> Rendering::createRayIntersectSpec(int winCoordX, int winCoordY) const
{
if (m_scene.isNull() || m_camera.isNull())
{
return NULL;
}
ref<Ray> ray = m_camera->rayFromWinCoord(winCoordX, winCoordY);
if (ray.isNull())
{
return NULL;
}
ref<RayIntersectSpec> rayIntersectSpec = new RayIntersectSpec(ray.p());
return rayIntersectSpec;
}
//--------------------------------------------------------------------------------------------------
/// Intersect all parts in this rendering and return resulting hits
///
/// The HitItemCollection will contain a list of hits in all parts intersected by the ray.
/// The list will be sorted based on distance, so the closest item to the eye will be first in the list.
//--------------------------------------------------------------------------------------------------
bool Rendering::rayIntersect(RayIntersectSpec& rayIntersectSpec, HitItemCollection* hitItemCollection)
{
if (m_scene.isNull()) return false;
bool anyHits = false;
uint numModels = m_scene->modelCount();
uint i;
for (i = 0; i < numModels; i++)
{
Model* model = m_scene->model(i);
CVF_ASSERT(model);
anyHits |= model->rayIntersect(rayIntersectSpec, hitItemCollection);
}
// Finally, sort the item collection so the first item is the closest one to the eye
if (hitItemCollection)
{
hitItemCollection->sort();
}
return anyHits;
}
//--------------------------------------------------------------------------------------------------
/// Get the bounding box of the Rendering
//--------------------------------------------------------------------------------------------------
BoundingBox Rendering::boundingBox() const
{
if (m_scene.notNull())
{
return m_scene->boundingBox();
}
else
{
return BoundingBox();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::setEnableMask(unsigned int mask)
{
m_enableMask = mask;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
unsigned int Rendering::enableMask() const
{
return m_enableMask;
}
//--------------------------------------------------------------------------------------------------
/// Specify what (if any) should be cleared when the viewport is applied to OpenGL
//--------------------------------------------------------------------------------------------------
void Rendering::setClearMode(Viewport::ClearMode clearMode)
{
m_clearMode = clearMode;
}
//--------------------------------------------------------------------------------------------------
/// Returns the current clear mode specifying what to clear when the viewport is applied to OpenGL
//--------------------------------------------------------------------------------------------------
Viewport::ClearMode Rendering::clearMode() const
{
return m_clearMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::setEffectOverride(Effect* effect)
{
m_effectOverride = effect;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Effect* Rendering::effectOverride()
{
return m_effectOverride.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::addDynamicUniformSet(DynamicUniformSet* dynUniformSet)
{
CVF_ASSERT(dynUniformSet);
m_dynamicUniformSets.push_back(dynUniformSet);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::removeDynamicUniformSet(DynamicUniformSet* dynUniformSet)
{
CVF_ASSERT(dynUniformSet);
m_dynamicUniformSets.erase(dynUniformSet);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::removeAllDynamicUniformSets()
{
m_dynamicUniformSets.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::addGlobalDynamicUniformSet(DynamicUniformSet* dynUniformSet)
{
CVF_ASSERT(dynUniformSet);
m_globalDynamicUniformSets.push_back(dynUniformSet);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::removeAllGlobalUniformSets()
{
m_globalDynamicUniformSets.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::updateDynamicUniformSets()
{
size_t numSets = m_dynamicUniformSets.size();
if (numSets == 0)
{
return;
}
size_t i;
for (i = 0; i < numSets; i++)
{
ref<DynamicUniformSet> dynUniformSet = m_dynamicUniformSets[i];
dynUniformSet->update(this);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::updateAndCombineGlobalDynamicUniformSets()
{
m_combinedGlobalUniformSet = NULL;
size_t numSets = m_globalDynamicUniformSets.size();
if (numSets == 0)
{
return;
}
m_combinedGlobalUniformSet = new UniformSet;
size_t idus;
for (idus = 0; idus < numSets; idus++)
{
ref<DynamicUniformSet> dynUniformSet = m_globalDynamicUniformSets[idus];
dynUniformSet->update(this);
ref<UniformSet> uniformSet = dynUniformSet->uniformSet();
if (uniformSet.notNull())
{
size_t numUniforms = uniformSet->count();
size_t iu;
for (iu = 0; iu < numUniforms; iu++)
{
Uniform* u = uniformSet->uniform(iu);
m_combinedGlobalUniformSet->setUniform(u);
}
}
}
}
//--------------------------------------------------------------------------------------------------
/// Get the performance info of the last render() call
//--------------------------------------------------------------------------------------------------
const PerformanceInfo& Rendering::performanceInfo() const
{
return m_performanceInfo;
}
//--------------------------------------------------------------------------------------------------
/// Turn performance timing on or off (to possibly increase performance)
//--------------------------------------------------------------------------------------------------
void Rendering::enablePerformanceTiming(bool enable)
{
m_enablePerformanceTiming = enable;
}
//--------------------------------------------------------------------------------------------------
/// Check if performance timing is enabled or not
//--------------------------------------------------------------------------------------------------
bool Rendering::isPerformanceTimingEnabled() const
{
return m_enablePerformanceTiming;
}
//--------------------------------------------------------------------------------------------------
/// Returns a ptr to the cull settings.
///
/// These settings are used when building the visible part queue.
//--------------------------------------------------------------------------------------------------
CullSettings* Rendering::cullSettings()
{
return &m_cullSettings;
}
//--------------------------------------------------------------------------------------------------
/// Returns a const ref to the cull settings.
///
/// These settings are used when building the visible part queue.
//--------------------------------------------------------------------------------------------------
const CullSettings* Rendering::cullSettings() const
{
return &m_cullSettings;
}
//--------------------------------------------------------------------------------------------------
/// Limit the maximum number of parts that will be drawn
///
/// Typically used to achieve a target frame rate. \sa clearMaxNumPartsToDraw()
//--------------------------------------------------------------------------------------------------
void Rendering::setMaxNumPartsToDraw(size_t maxNumPartsToDraw)
{
m_maxNumPartsToDraw = maxNumPartsToDraw;
}
//--------------------------------------------------------------------------------------------------
/// Clear current limit on the maximum number of parts to draw
///
/// \sa setMaxNumPartsToDraw()
//--------------------------------------------------------------------------------------------------
void Rendering::clearMaxNumPartsToDraw()
{
m_maxNumPartsToDraw = std::numeric_limits<size_t>::max();
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of overlay items in this rendering
//--------------------------------------------------------------------------------------------------
size_t Rendering::overlayItemCount() const
{
return m_overlayItems.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::addOverlayItem(OverlayItem* overlayItem, OverlayItem::LayoutCorner corner, OverlayItem::LayoutDirection direction)
{
CVF_ASSERT(overlayItem);
OverlayItemLayout item;
item.corner = corner;
item.direction = direction;
item.overlayItem = overlayItem;
m_overlayItems.push_back(item);
}
//--------------------------------------------------------------------------------------------------
/// Returns the overlay item at the given index.
///
/// corner and direction are optional parameters to receive the layout attachment of the overlay item
//--------------------------------------------------------------------------------------------------
OverlayItem* Rendering::overlayItem(size_t index, OverlayItem::LayoutCorner* corner, OverlayItem::LayoutDirection* direction)
{
CVF_ASSERT(index < overlayItemCount());
if (corner)
{
*corner = m_overlayItems[index].corner;
}
if (direction)
{
*direction = m_overlayItems[index].direction;
}
return m_overlayItems[index].overlayItem.p();
}
//--------------------------------------------------------------------------------------------------
/// Returns the overlay item at the given index.
///
/// corner and direction are optional parameters to receive the layout attachment of the overlay item
//--------------------------------------------------------------------------------------------------
const OverlayItem* Rendering::overlayItem(size_t index, OverlayItem::LayoutCorner* corner, OverlayItem::LayoutDirection* direction) const
{
CVF_ASSERT(index < overlayItemCount());
if (corner)
{
*corner = m_overlayItems[index].corner;
}
if (direction)
{
*direction = m_overlayItems[index].direction;
}
return m_overlayItems[index].overlayItem.p();
}
//--------------------------------------------------------------------------------------------------
/// Get the the overlay item (if any) at the given cursor position
//--------------------------------------------------------------------------------------------------
OverlayItem* Rendering::overlayItemFromWinCoord(uint winCoordX, uint winCoordY)
{
// Overlay items are stored OpenGL coord system with (0,0) in lower left corner, so flip the y-coordinate
winCoordY = static_cast<int>(m_camera->viewport()->height()) - winCoordY;
OverlayItemRectMap itemRectMap;
calculateOverlayItemLayout(&itemRectMap);
OverlayItemRectMap::iterator it;
for (it = itemRectMap.begin(); it != itemRectMap.end(); ++it)
{
OverlayItem* item = it->first;
Rectui rect = it->second;
if ((winCoordX > rect.min().x()) && (winCoordX < rect.max().x()) &&
(winCoordY > rect.min().y()) && (winCoordY < rect.max().y()))
{
return item;
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::removeOverlayItem(const OverlayItem* overlayItem)
{
CVF_UNUSED(overlayItem);
std::vector<OverlayItemLayout>::iterator it;
for (it = m_overlayItems.begin(); it != m_overlayItems.end(); it++)
{
if (it->overlayItem == overlayItem)
{
m_overlayItems.erase(it);
break;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Rendering::removeAllOverlayItems()
{
m_overlayItems.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
String Rendering::toString() const
{
String str = "Rendering: ";
str += m_renderingName;
str += "\n Clearmode: ";
switch (m_clearMode)
{
case Viewport::DO_NOT_CLEAR: str += "DO_NOT_CLEAR"; break;
case Viewport::CLEAR_COLOR: str += "CLEAR_COLOR"; break;
case Viewport::CLEAR_DEPTH: str += "CLEAR_DEPTH"; break;
case Viewport::CLEAR_STENCIL: str += "CLEAR_STENCIL"; break;
case Viewport::CLEAR_COLOR_DEPTH: str += "CLEAR_COLOR_DEPTH"; break;
case Viewport::CLEAR_COLOR_STENCIL: str += "CLEAR_COLOR_STENCIL"; break;
case Viewport::CLEAR_DEPTH_STENCIL: str += "CLEAR_DEPTH_STENCIL"; break;
case Viewport::CLEAR_COLOR_DEPTH_STENCIL: str += "CLEAR_COLOR_DEPTH_STENCIL"; break;
}
str += "\n enableMask: " + String(m_enableMask);
str += "\n m_maxNumPartsToDraw: " + String(m_enableMask);
str += "\n m_viewFrustumCulling: " + String(m_cullSettings.isViewFrustumCullingEnabled());
str += "\n m_pixelSizeCulling: " + String(m_cullSettings.isPixelSizeCullingEnabled());
str += "\n m_pixelSizeCullingAreaThreshold: " + String(m_cullSettings.pixelSizeCullingAreaThreshold());
return str;
}
} // namespace cvf
@@ -0,0 +1,158 @@
//##################################################################################################
//
// 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 "cvfRenderEngine.h"
#include "cvfViewport.h"
#include "cvfCullSettings.h"
#include "cvfPerformanceInfo.h"
#include "cvfBoundingBox.h"
#include "cvfCollection.h"
#include "cvfOverlayItem.h"
#include "cvfRect.h"
#include <map>
namespace cvf {
class Scene;
class Camera;
class PartRenderHintCollection;
class RenderQueueSorter;
class Effect;
class FramebufferObject;
class DynamicUniformSet;
class UniformSet;
class RayIntersectSpec;
class HitItemCollection;
class OpenGLContext;
struct OverlayItemLayout;
//==================================================================================================
//
// Rendering
//
//==================================================================================================
class Rendering : public Object
{
public:
Rendering(const String& renderingName = String());
~Rendering();
void setRenderingName(const String& renderingName);
String renderingName() const;
void setScene(Scene* scene);
Scene* scene();
const Scene* scene() const;
void setCamera(Camera* camera);
Camera* camera();
const Camera* camera() const;
void render(OpenGLContext* oglContext);
void setRenderQueueSorter(RenderQueueSorter* sorter);
RenderQueueSorter* renderQueueSorter();
RenderEngine* renderEngine();
const RenderEngine* renderEngine() const;
void setTargetFrameBuffer(FramebufferObject* frameBuffer);
ref<RayIntersectSpec> createRayIntersectSpec(int winCoordX, int winCoordY) const;
bool rayIntersect(RayIntersectSpec& rayIntersectSpec, HitItemCollection* hitItemCollection);
BoundingBox boundingBox() const;
void setEnableMask(unsigned int mask);
unsigned int enableMask() const;
void setClearMode(Viewport::ClearMode clearMode);
Viewport::ClearMode clearMode() const;
void setEffectOverride(Effect* effect);
Effect* effectOverride();
void addDynamicUniformSet(DynamicUniformSet* dynUniformSet);
void removeDynamicUniformSet(DynamicUniformSet* dynUniformSet);
void removeAllDynamicUniformSets();
void addGlobalDynamicUniformSet(DynamicUniformSet* dynUniformSet);
void removeAllGlobalUniformSets();
const PerformanceInfo& performanceInfo() const;
void enablePerformanceTiming(bool enable);
bool isPerformanceTimingEnabled() const;
CullSettings* cullSettings();
const CullSettings* cullSettings() const;
void setMaxNumPartsToDraw(size_t maxNumPartsToDraw);
void clearMaxNumPartsToDraw();
size_t overlayItemCount() const;
void addOverlayItem(OverlayItem* overlayItem, OverlayItem::LayoutCorner corner, OverlayItem::LayoutDirection direction);
OverlayItem* overlayItem(size_t index, OverlayItem::LayoutCorner* corner, OverlayItem::LayoutDirection* direction);
const OverlayItem* overlayItem(size_t index, OverlayItem::LayoutCorner* corner, OverlayItem::LayoutDirection* direction) const;
OverlayItem* overlayItemFromWinCoord(uint winCoordX, uint winCoordY);
void removeOverlayItem(const OverlayItem* overlayItem);
void removeAllOverlayItems();
String toString() const;
private:
void renderOverlayItems(OpenGLContext* oglContext, bool useSoftwareRendering);
typedef std::map<cvf::OverlayItem*, cvf::Rectui> OverlayItemRectMap;
void calculateOverlayItemLayout(OverlayItemRectMap* itemRectMap);
void calculateOverlayItemLayout(OverlayItemRectMap* itemRectMap, OverlayItem::LayoutCorner corner, OverlayItem::LayoutDirection direction);
void updateDynamicUniformSets();
void updateAndCombineGlobalDynamicUniformSets();
private:
String m_renderingName;
ref<Scene> m_scene;
ref<Camera> m_camera;
ref<FramebufferObject> m_targetFrameBuffer;
std::vector<OverlayItemLayout> m_overlayItems;
ref<PartRenderHintCollection> m_visibleParts; // The collection of visible parts for one pass. The collection class is reused between passes
ref<RenderQueueSorter> m_renderQueueSorter; // Render queue sorter, initialized to a basic sorter with minimal sorting strategy
RenderEngine m_renderEngine; //
unsigned int m_enableMask; // Mask will be compared against the contained scene's models and the model's parts when determining visible parts
Viewport::ClearMode m_clearMode;
ref<Effect> m_effectOverride; // Can hold an overriding effect. All parts drawn by this rendering will use this effect
Collection<DynamicUniformSet> m_dynamicUniformSets; // Collection of user added dynamic uniform sets
Collection<DynamicUniformSet> m_globalDynamicUniformSets; // Collection of global user added dynamic uniform sets
ref<UniformSet> m_combinedGlobalUniformSet; // Global uniform set, this is the combination of the uniform sets from all the dynamic uniform sets
CullSettings m_cullSettings; // Cull settings used when extracting visible parts from the scene
size_t m_maxNumPartsToDraw; // The maximum number of parts to draw during render pass
PerformanceInfo m_performanceInfo;
bool m_enablePerformanceTiming;
};
}
@@ -0,0 +1,171 @@
//##################################################################################################
//
// 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 "cvfScene.h"
#include "cvfModel.h"
#include "cvfPartRenderHintCollection.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Scene
/// \ingroup Viewing
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Compute the visible parts of all models in the scene
//--------------------------------------------------------------------------------------------------
void Scene::findVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const CullSettings& cullSettings, unsigned int enableMask)
{
visibleParts->setCountZero();
uint i;
for (i = 0; i < modelCount(); i++)
{
Model* model = m_models[i].p();
if (model)
{
if ((enableMask & model->partEnableMask()) != 0)
{
model->findVisibleParts(visibleParts, camera, cullSettings, enableMask);
}
}
}
}
//--------------------------------------------------------------------------------------------------
/// Get all pars in all models in the scene
//--------------------------------------------------------------------------------------------------
void Scene::allParts(Collection<Part>* partCollection)
{
uint numModels = modelCount();
uint i;
for (i = 0; i < numModels; i++)
{
Model* model = m_models.at(i);
CVF_ASSERT(model);
model->allParts(partCollection);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Scene::addModel(Model* model)
{
CVF_ASSERT(model);
m_models.push_back(model);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
uint Scene::modelCount() const
{
return static_cast<uint>(m_models.size());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Model* Scene::model(uint index)
{
return m_models[index].p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Model* Scene::model(uint index) const
{
return m_models[index].p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Scene::removeAllModels()
{
m_models.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Scene::removeModel(const Model* model)
{
CVF_ASSERT(model);
m_models.erase(model);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Scene::updateBoundingBoxesRecursive()
{
size_t numModels = m_models.size();
size_t i;
for (i = 0; i < numModels; i++)
{
Model* model = m_models.at(i);
CVF_ASSERT(model);
model->updateBoundingBoxesRecursive();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
BoundingBox Scene::boundingBox() const
{
BoundingBox bb;
size_t numModels = m_models.size();
size_t i;
for (i = 0; i < numModels; i++)
{
const Model* model = m_models.at(i);
CVF_ASSERT(model);
bb.add(model->boundingBox());
}
return bb;
}
} // namespace cvf
@@ -0,0 +1,60 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfObject.h"
#include "cvfCollection.h"
#include "cvfBoundingBox.h"
namespace cvf {
class Model;
class Part;
class Camera;
class PartRenderHintCollection;
class CullSettings;
//==================================================================================================
//
// Scene
//
//==================================================================================================
class Scene : public Object
{
public:
void findVisibleParts(PartRenderHintCollection* visibleParts, const Camera& camera, const CullSettings& cullSettings, unsigned int enableMask);
void allParts(Collection<Part>* partCollection);
void addModel(Model* model);
uint modelCount() const;
Model* model(uint index);
const Model* model(uint index) const;
void removeAllModels();
void removeModel(const Model* model);
void updateBoundingBoxesRecursive();
BoundingBox boundingBox() const;
protected:
Collection<Model> m_models;
};
}
@@ -0,0 +1,190 @@
//##################################################################################################
//
// 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 "cvfSingleQuadRenderingGenerator.h"
#include "cvfPrimitiveSetIndexedUShort.h"
#include "cvfDrawableGeo.h"
#include "cvfEffect.h"
#include "cvfModelBasicList.h"
#include "cvfScene.h"
#include "cvfCamera.h"
#include "cvfShaderSourceProvider.h"
#include "cvfShaderProgram.h"
#include "cvfShaderProgramGenerator.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::SingleQuadRenderingGenerator
/// \ingroup Viewing
///
/// Utility class for generating renderings with a single full screen quad
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
SingleQuadRenderingGenerator::SingleQuadRenderingGenerator()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SingleQuadRenderingGenerator::addTexture(Texture* texture, Sampler* sampler, String samplerUniformName)
{
m_textures.push_back(texture);
m_samplers.push_back(sampler);
m_samplerNames.push_back(samplerUniformName);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SingleQuadRenderingGenerator::addFragmentShaderCode(String fragShaderCode)
{
m_fragShadersCode.push_back(fragShaderCode);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SingleQuadRenderingGenerator::setRenderState(RenderState* renderState)
{
m_renderStateSet.setRenderState(renderState);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SingleQuadRenderingGenerator::setUniform(Uniform* uniform)
{
m_uniformSet.setUniform(uniform);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ref<Rendering> SingleQuadRenderingGenerator::generate()
{
ref<PrimitiveSetIndexedUShort> quad = new PrimitiveSetIndexedUShort(PT_TRIANGLES);
ref<UShortArray> triIndices = new UShortArray;
triIndices->reserve(6);
triIndices->add(0);
triIndices->add(1);
triIndices->add(2);
triIndices->add(0);
triIndices->add(2);
triIndices->add(3);
quad->setIndices(triIndices.p());
ref<Vec3fArray> quadVerts = new Vec3fArray;
quadVerts->reserve(4);
// Must set a z value that is within the default camera's clipping volume in order for the texture to be shown
float z = -1.0f;
quadVerts->add(Vec3f(0, 0, z));
quadVerts->add(Vec3f(1, 0, z));
quadVerts->add(Vec3f(1, 1, z));
quadVerts->add(Vec3f(0, 1, z));
ref<DrawableGeo> geo1 = new DrawableGeo;
geo1->addPrimitiveSet(quad.p());
geo1->setVertexArray(quadVerts.p());
geo1->computeNormals();
ref<Part> part = new Part;
part->setDrawable(geo1.p());
ref<Effect> eff = new Effect;
part->setEffect(eff.p());
// ref<Sampler> sampler = new Sampler;
// sampler->setWrapMode(Sampler::CLAMP_TO_EDGE);
// sampler->setMinFilter(Sampler::NEAREST);
// sampler->setMagFilter(Sampler::NEAREST);
if (m_textures.size() > 0)
{
// Setup the texture binding render state
ref<TextureBindings> textureBindings = new TextureBindings;
eff->setRenderState(textureBindings.p());
CVF_ASSERT((m_textures.size() == m_samplers.size()) && (m_textures.size() == m_samplerNames.size()));
size_t i;
for (i = 0; i < m_textures.size(); i++)
{
textureBindings->addBinding(m_textures[i].p(), m_samplers[i].p(), m_samplerNames[i].toAscii().ptr());
}
}
// Shader program
cvf::ShaderProgramGenerator gen("SingleQuadRendering", cvf::ShaderSourceProvider::instance());
gen.addVertexCode(cvf::ShaderSourceRepository::vs_FullScreenQuad);
// Add custom fragment shaders
size_t i;
for (i = 0; i < m_fragShadersCode.size(); i++)
{
gen.addFragmentCode(m_fragShadersCode[i]);
}
ref<ShaderProgram> shaderProg = gen.generate();
eff->setShaderProgram(shaderProg.p());
uint rs;
for (rs = 0; rs < m_renderStateSet.count(); rs++)
{
eff->setRenderState(m_renderStateSet.renderState(rs));
}
uint uf;
for (uf = 0; uf < m_uniformSet.count(); uf++)
{
eff->setUniform(m_uniformSet.uniform(uf));
}
ref<Rendering> quadRendering = new Rendering;
ref<ModelBasicList> quadModel = new ModelBasicList;
ref<Scene> scene = new Scene;
quadModel->addPart(part.p());
quadModel->updateBoundingBoxesRecursive();
scene->addModel(quadModel.p());
quadRendering->setScene(scene.p());
return quadRendering;
}
} // namespace cvf
@@ -0,0 +1,60 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfCollection.h"
#include "cvfPart.h"
#include "cvfShader.h"
#include "cvfUniformSet.h"
#include "cvfTexture.h"
#include "cvfSampler.h"
#include "cvfRendering.h"
#include "cvfRenderStateSet.h"
namespace cvf
{
//==================================================================================================
//
// SingleQuadRenderingGenerator
//
//==================================================================================================
class SingleQuadRenderingGenerator
{
public:
SingleQuadRenderingGenerator();
void addTexture(Texture* texture, Sampler* sampler, String samplerUniformName);
void addFragmentShaderCode(String shaderCode);
void setRenderState(RenderState* renderState);
void setUniform(Uniform* uniform);
ref<Rendering> generate();
private:
Collection<Texture> m_textures;
Collection<Sampler> m_samplers;
std::vector<String> m_samplerNames;
std::vector<String> m_fragShadersCode;
RenderStateSet m_renderStateSet;
UniformSet m_uniformSet;
};
} // cvf
@@ -0,0 +1,64 @@
//##################################################################################################
//
// 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 "cvfTransform.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Transform
/// \ingroup Viewing
///
/// Transformation for use with a Part
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Transform::Transform()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Transform::setWorldTransform(const Mat4d& transform)
{
m_worldMatrix = transform;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const Mat4d& Transform::worldTransform() const
{
return m_worldMatrix;
}
} // namespace cvf
@@ -0,0 +1,47 @@
//##################################################################################################
//
// 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"
#include "cvfCollection.h"
namespace cvf {
//==================================================================================================
//
// Transformation for use in a Part
//
//==================================================================================================
class Transform : public Object
{
public:
Transform();
void setWorldTransform(const Mat4d& transform);
const Mat4d& worldTransform() const;
private:
Collection<Transform> m_childern;
Mat4d m_localMatrix;
Mat4d m_worldMatrix;
};
}