/**************************************************************************\
*
* This file is part of the SIM Voleon visualization library.
* Copyright (C) 2003-2004 by Systems in Motion. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* ("GPL") version 2 as published by the Free Software Foundation.
* See the file LICENSE.GPL at the root directory of this source
* distribution for additional information about the GNU GPL.
*
* For using SIM Voleon with software that can not be combined with
* the GNU GPL, and for taking advantage of the additional benefits
* of our support services, please contact Systems in Motion about
* acquiring a SIM Voleon Professional Edition License.
*
* See <URL:http://www.coin3d.org/> for more information.
*
* Systems in Motion, Postboks 1283, Pirsenteret, 7462 Trondheim, NORWAY.
* <URL:http://www.sim.no/>.
*
\**************************************************************************/
/*!
\class SoVolumeRender VolumeViz/nodes/SoVolumeRender.h
\brief Render the full volume.
Insert a node of this type after an SoVolumeData node in the scene
graph to render the full volume data set.
\sa SoOrthoSlice, SoObliqueSlice, SoVolumeFaceSet, SoVolumeIndexedFaceSet
\sa SoVolumeTriangleStripSet, SoVolumeIndexedTriangleStripSet
*/
// *************************************************************************
#include <VolumeViz/nodes/SoVolumeRender.h>
#include <string.h>
#include <limits.h> // UINT_MAX
#include <float.h> // DBL_MAX
#include <Inventor/C/glue/gl.h>
#include <Inventor/C/tidbits.h>
#include <Inventor/SbLine.h>
#include <Inventor/SbPlane.h>
#include <Inventor/SbRotation.h>
#include <Inventor/SbTime.h>
#include <Inventor/SoPickedPoint.h>
#include <Inventor/actions/SoGLRenderAction.h>
#include <Inventor/actions/SoGetBoundingBoxAction.h>
#include <Inventor/actions/SoRayPickAction.h>
#include <Inventor/bundles/SoMaterialBundle.h>
#include <Inventor/elements/SoGLTextureEnabledElement.h>
#include <Inventor/elements/SoLazyElement.h>
#include <Inventor/elements/SoModelMatrixElement.h>
#include <Inventor/elements/SoShapeStyleElement.h>
#include <Inventor/elements/SoCacheElement.h>
#include <Inventor/errors/SoDebugError.h>
#include <Inventor/system/gl.h>
#include <Inventor/nodes/SoDrawStyle.h>
#include <Inventor/nodes/SoCube.h>
#include <VolumeViz/nodes/SoVolumeData.h>
#include <VolumeViz/elements/CvrGLInterpolationElement.h>
#include <VolumeViz/elements/CvrVoxelBlockElement.h>
#include <VolumeViz/elements/CvrStorageHintElement.h>
#include <VolumeViz/elements/SoTransferFunctionElement.h>
#include <VolumeViz/render/2D/CvrPageHandler.h>
#include <VolumeViz/render/3D/CvrCubeHandler.h>
#include <VolumeViz/render/pointset/PointRendering.h>
#include <VolumeViz/details/SoVolumeRenderDetail.h>
#include <VolumeViz/misc/CvrVoxelChunk.h>
#include <VolumeViz/misc/CvrCLUT.h>
#include <VolumeViz/misc/CvrUtil.h>
#include <VolumeViz/misc/CvrGlobalRenderLock.h>
#include <VolumeViz/elements/CvrLightingElement.h>
//#include <VolumeViz/Coin/gl/CoinGLPerformance.h>
#include "volumeraypickintersection.h"
// *************************************************************************
// FIXME: not so sure the below whitelist and blacklist is such a good
// idea after all. There seems to be a realistic possibility for false
// positives or negatives.
//
// Should at least cut them down to these cards we have had hands-on
// experience with. Should also extend the driver identification
// strings to be more exacting, to minimize the potential for false
// positives and negatives.
//
// 20040708 mortene.
// Whitelist of GL_RENDERER substrings for cards which does 3D
// textures in hardware.
static const char * texture3d_in_hardware[] = {
#if 0 // tmp disabled, see above FIXME
"GeForce FX", // 5200 .. 5950
"GeForce3",
"GeForce4 Ti",
"Geforce4 4200 GO",
"Quadro FX",
"Quadro4",
"Quadro DCC", // Has the nFiniteFX engine, so we assume it has HW 3D textures.
"RADEON ", // 7000 .. 9000
"Radeon ",
"RV250", // A semi Radeon 8500
"MOBILITY RADEON ",
"Fire GL", // I persume these highend cards do 3D textures in HW
"Wildcat VP", // 560, 870, 970.
#endif // tmp disabled
NULL
};
// Blacklist of GL_RENDERER substrings for hardware which does 3D
// textures, but only in software (i.e. not feasible for volume
// rendering).
static const char * texture3d_in_software[] = {
#if 0 // tmp disabled, see above FIXME
"GeForce2",
"GeForce4 MX",
"Geforce4 440 GO",
"Geforce4 460 GO",
"Geforce4 420 GO",
"RAGE 128",
"Mesa Windows",
#endif // tmp disabled
NULL
};
// *************************************************************************
SO_NODE_SOURCE(SoVolumeRender);
// *************************************************************************
class SoVolumeRenderP {
public:
SoVolumeRenderP(SoVolumeRender * master)
{
this->master = master;
this->pagehandler = NULL;
this->cubehandler = NULL;
this->abortfunc = NULL;
this->abortfuncdata = NULL;
this->linestylevolumecube = NULL;
}
~SoVolumeRenderP()
{
if (this->linestylevolumecube) this->linestylevolumecube->unref();
if (this->pagehandler) delete this->pagehandler;
if (this->cubehandler) delete this->cubehandler;
}
unsigned int calculateNrOf2DSlices(SoGLRenderAction * action, const SbVec3s & dimensions);
unsigned int calculateNrOf3DSlices(SoGLRenderAction * action, const SbVec3s & dimensions);
SbBool use3DTexturing(const cc_glglue * glglue) const;
static void setupPerformanceTest(const cc_glglue * glglue, void *);
static void cleanupPerformanceTest(const cc_glglue * glglue, void *);
static void renderTexturedTriangles(GLenum type);
static void render2DTexturedTriangles(const cc_glglue *, void *);
static void render3DTexturedTriangles(const cc_glglue *, void *);
CvrPageHandler * pagehandler; // For 2D page rendering
CvrCubeHandler * cubehandler; // For 3D cube rendering
SoVolumeRender::SoVolumeRenderAbortCB * abortfunc;
void * abortfuncdata;
// A cube used as line-style rep. for the volume
SoCube * linestylevolumecube;
// debug
void rayPickDebug(SoGLRenderAction * action);
SbList<SbVec3f> raypicklines;
enum RenderingMethod { TEXTURE3D, TEXTURE2D, NOTIMPLEMENTED };
private:
SoVolumeRender * master;
static GLuint texture3dids[2];
static GLuint texture2dids[2];
};
GLuint SoVolumeRenderP::texture3dids[2];
GLuint SoVolumeRenderP::texture2dids[2];
#define PRIVATE(p) (p->pimpl)
#define PUBLIC(p) (p->master)
// *************************************************************************
/*!
\enum SoVolumeRender::Interpolation
Enumeration of available types of voxel colors interpolation.
*/
/*!
\var SoVolumeRender::Interpolation SoVolumeRender::NEAREST
For "in between" pixels of the screen rasterization, pick the color
of the nearest voxel. Will give sharp edges and a distinct blocky
look.
*/
/*!
\var SoVolumeRender::Interpolation SoVolumeRender::LINEAR
For "in between" pixels of the screen rasterization, interpolate by
averaging the colors of several of the nearest voxels. Will give a
smoother appearance, but sacrifies some "correctness" for
appearance.
*/
/*!
\var SoSFEnum SoVolumeRender::interpolation
How to interpolate color values when rendering "in between" voxels.
See SoVolumeRender::Interpolation.
Default value is SoVolumeRender::LINEAR.
*/
// *************************************************************************
/*!
\enum SoVolumeRender::NumSlicesControl
Enumeration of strategies for how to render the slices of the
volume.
*/
/*!
\var SoVolumeRender::NumSlicesControl SoVolumeRender::ALL
Always render as many slices as there are voxels in the depth
dimension. This is the default value.
Please note that SoVolumeRender::NumSlicesControl will always be
cons