mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-16 18:32:10 -05:00
Initial commit of ResInsight version 0.4.8
This commit is contained in:
1 parent
a680bf941e
commit
dfe97efb1b
657 files changed
+176690
No files matched your search
@@ -0,0 +1,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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user