[2936] | 1 | /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
---|
[835] | 2 | /* |
---|
| 3 | * ---------------------------------------------------------------------- |
---|
| 4 | * Volume.h: 3d volume class |
---|
| 5 | * |
---|
| 6 | * ====================================================================== |
---|
| 7 | * AUTHOR: Wei Qiao <qiaow@purdue.edu> |
---|
| 8 | * Purdue Rendering and Perceptualization Lab (PURPL) |
---|
| 9 | * |
---|
| 10 | * Copyright (c) 2004-2006 Purdue Research Foundation |
---|
| 11 | * |
---|
| 12 | * See the file "license.terms" for information on usage and |
---|
| 13 | * redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
| 14 | * ====================================================================== |
---|
| 15 | */ |
---|
[2936] | 16 | #ifndef VOLUME_H |
---|
| 17 | #define VOLUME_H |
---|
[835] | 18 | |
---|
| 19 | #include <string> |
---|
| 20 | #include <vector> |
---|
| 21 | |
---|
[2936] | 22 | #include <R2/R2Object.h> |
---|
| 23 | |
---|
[835] | 24 | #include "Color.h" |
---|
| 25 | #include "Texture3D.h" |
---|
| 26 | #include "Vector3.h" |
---|
[929] | 27 | #include "AxisRange.h" |
---|
[1478] | 28 | #include "TransferFunction.h" |
---|
[835] | 29 | |
---|
[2936] | 30 | struct CutPlane { |
---|
| 31 | /// orientation - 1: xy slice, 2: yz slice, 3: xz slice |
---|
| 32 | int orient; |
---|
| 33 | float offset; ///< normalized offset [0,1] in the volume |
---|
[835] | 34 | bool enabled; |
---|
| 35 | |
---|
[2936] | 36 | CutPlane(int _orient, float _offset) : |
---|
| 37 | orient(_orient), |
---|
| 38 | offset(_offset), |
---|
| 39 | enabled(true) |
---|
| 40 | { |
---|
[835] | 41 | } |
---|
| 42 | }; |
---|
| 43 | |
---|
[1478] | 44 | class VolumeInterpolator; |
---|
[835] | 45 | |
---|
[2936] | 46 | class Volume |
---|
| 47 | { |
---|
[1478] | 48 | public: |
---|
[2936] | 49 | enum VolumeType { |
---|
| 50 | CUBIC, |
---|
| 51 | VOLQD, |
---|
| 52 | ZINCBLENDE |
---|
| 53 | }; |
---|
[835] | 54 | |
---|
[2936] | 55 | /** |
---|
| 56 | * \brief Volume data constructor |
---|
| 57 | * |
---|
| 58 | * Represents a 3D regular grid with uniform spacing along |
---|
| 59 | * each axis. Sample spacing may differ between X, Y and Z |
---|
| 60 | * |
---|
| 61 | * \param x X location |
---|
| 62 | * \param y Y location |
---|
| 63 | * \param z Z location |
---|
| 64 | * \param width Number of samples in X |
---|
| 65 | * \param height Number of samples in Y |
---|
| 66 | * \param depth Number of samples in Z |
---|
| 67 | * \param size Scale factor |
---|
| 68 | * \param numComponents Number of components per sample |
---|
| 69 | * \param data width * height * depth * numComponent sample array |
---|
| 70 | * \param vmin Scalar value minimum |
---|
| 71 | * \param vmax Scalar value maximum |
---|
| 72 | * \param nonZeroMin Scalar minimum which is greater than zero |
---|
| 73 | */ |
---|
| 74 | Volume(float x, float y, float z, |
---|
| 75 | int width, int height, int depth, |
---|
| 76 | float size, int numComponents, |
---|
| 77 | float *data, |
---|
| 78 | double vmin, double vmax, |
---|
| 79 | double nonZeroMin); |
---|
[835] | 80 | |
---|
[2936] | 81 | virtual ~Volume(); |
---|
[870] | 82 | |
---|
[2936] | 83 | void visible(bool value) |
---|
| 84 | { |
---|
| 85 | _enabled = value; |
---|
| 86 | } |
---|
[1478] | 87 | |
---|
[2936] | 88 | bool visible() const |
---|
| 89 | { |
---|
| 90 | return _enabled; |
---|
[1474] | 91 | } |
---|
[2936] | 92 | |
---|
| 93 | void location(const Vector3& loc) |
---|
| 94 | { |
---|
| 95 | _location = loc; |
---|
[1474] | 96 | } |
---|
[2936] | 97 | |
---|
| 98 | Vector3 location() const |
---|
| 99 | { |
---|
| 100 | return _location; |
---|
[1474] | 101 | } |
---|
[2936] | 102 | |
---|
| 103 | int isosurface() const |
---|
| 104 | { |
---|
| 105 | return _isosurface; |
---|
[1478] | 106 | } |
---|
[2936] | 107 | |
---|
| 108 | void isosurface(int iso) |
---|
| 109 | { |
---|
| 110 | _isosurface = iso; |
---|
[1478] | 111 | } |
---|
[2936] | 112 | |
---|
| 113 | int numComponents() const |
---|
| 114 | { |
---|
| 115 | return _numComponents; |
---|
[1478] | 116 | } |
---|
[2936] | 117 | |
---|
| 118 | double nonZeroMin() const |
---|
| 119 | { |
---|
| 120 | return _nonZeroMin; |
---|
[1478] | 121 | } |
---|
[2936] | 122 | |
---|
| 123 | int volumeType() const |
---|
| 124 | { |
---|
| 125 | return _volumeType; |
---|
[1478] | 126 | } |
---|
[2936] | 127 | |
---|
| 128 | float *data() |
---|
| 129 | { |
---|
| 130 | return _data; |
---|
[1478] | 131 | } |
---|
[2936] | 132 | |
---|
| 133 | Texture3D *tex() |
---|
| 134 | { |
---|
| 135 | return _tex; |
---|
[1478] | 136 | } |
---|
[2936] | 137 | |
---|
| 138 | int numSlices() const |
---|
| 139 | { |
---|
| 140 | return _numSlices; |
---|
[1478] | 141 | } |
---|
[1474] | 142 | |
---|
[2936] | 143 | void numSlices(int n) |
---|
| 144 | { |
---|
| 145 | _numSlices = n; |
---|
[1478] | 146 | } |
---|
[870] | 147 | |
---|
[2936] | 148 | /// set the drawing size of volume |
---|
| 149 | void setSize(float s); |
---|
[835] | 150 | |
---|
[2936] | 151 | // methods related to cutplanes |
---|
| 152 | /// add a plane and returns its index |
---|
| 153 | int addCutplane(int orientation, float location); |
---|
[835] | 154 | |
---|
[2936] | 155 | void enableCutplane(int index); |
---|
| 156 | |
---|
| 157 | void disableCutplane(int index); |
---|
| 158 | |
---|
| 159 | void moveCutplane(int index, float location); |
---|
| 160 | |
---|
| 161 | CutPlane *getCutplane(int index); |
---|
| 162 | |
---|
| 163 | /// returns the number of cutplanes in the volume |
---|
| 164 | int getCutplaneCount(); |
---|
| 165 | |
---|
| 166 | /// check if a cutplane is enabled |
---|
| 167 | bool isCutplaneEnabled(int index) const; |
---|
| 168 | |
---|
| 169 | // methods related to shading. These parameters are per volume |
---|
| 170 | |
---|
| 171 | /// Get specular exponent |
---|
| 172 | float specular() const |
---|
| 173 | { |
---|
| 174 | return _specular; |
---|
[1474] | 175 | } |
---|
[2936] | 176 | |
---|
| 177 | /// Set specular exponent [0,128] |
---|
| 178 | void specular(float value) |
---|
| 179 | { |
---|
| 180 | if (value < 0.0f) value = 0.0f; |
---|
| 181 | if (value > 128.0f) value = 128.0f; |
---|
| 182 | _specular = value; |
---|
[1474] | 183 | } |
---|
[2936] | 184 | |
---|
| 185 | /// Get diffuse coefficient |
---|
| 186 | float diffuse() const |
---|
| 187 | { |
---|
| 188 | return _diffuse; |
---|
[1474] | 189 | } |
---|
[2936] | 190 | |
---|
| 191 | /// Set diffuse coefficient [0,1] |
---|
| 192 | void diffuse(float value) |
---|
| 193 | { |
---|
| 194 | if (value < 0.0f) value = 0.0f; |
---|
| 195 | if (value > 1.0f) value = 1.0f; |
---|
| 196 | _diffuse = value; |
---|
[1474] | 197 | } |
---|
[2936] | 198 | |
---|
| 199 | float opacityScale() const |
---|
| 200 | { |
---|
| 201 | return _opacityScale; |
---|
[1474] | 202 | } |
---|
[2936] | 203 | |
---|
| 204 | void opacityScale(float value) |
---|
| 205 | { |
---|
| 206 | _opacityScale = value; |
---|
[1474] | 207 | } |
---|
[2936] | 208 | |
---|
| 209 | void dataEnabled(bool value) |
---|
| 210 | { |
---|
| 211 | _dataEnabled = value; |
---|
[1474] | 212 | } |
---|
[2936] | 213 | |
---|
| 214 | bool dataEnabled() const |
---|
| 215 | { |
---|
| 216 | return _dataEnabled; |
---|
[1474] | 217 | } |
---|
[2936] | 218 | |
---|
| 219 | void outline(bool value) |
---|
| 220 | { |
---|
| 221 | _outlineEnabled = value; |
---|
[1474] | 222 | } |
---|
[2936] | 223 | |
---|
| 224 | bool outline() |
---|
| 225 | { |
---|
| 226 | return _outlineEnabled; |
---|
[1474] | 227 | } |
---|
[2936] | 228 | |
---|
| 229 | TransferFunction *transferFunction() |
---|
| 230 | { |
---|
| 231 | return _tfPtr; |
---|
[1478] | 232 | } |
---|
[2936] | 233 | |
---|
| 234 | void transferFunction(TransferFunction *tfPtr) |
---|
| 235 | { |
---|
| 236 | _tfPtr = tfPtr; |
---|
[1478] | 237 | } |
---|
[1370] | 238 | |
---|
[2936] | 239 | void setOutlineColor(float *rgb); |
---|
| 240 | |
---|
| 241 | void getOutlineColor(float *rgb); |
---|
| 242 | |
---|
| 243 | /// change the label displayed on an axis |
---|
| 244 | void setLabel(int axis, const char *txt); |
---|
| 245 | |
---|
[1370] | 246 | void setPhysicalBBox(const Vector3& min, const Vector3& max); |
---|
[1475] | 247 | |
---|
[2936] | 248 | const Vector3& getPhysicalBBoxMin() const; |
---|
| 249 | |
---|
| 250 | const Vector3& getPhysicalBBoxMax() const; |
---|
| 251 | |
---|
| 252 | const char *name() const |
---|
| 253 | { |
---|
| 254 | return _name; |
---|
[1478] | 255 | } |
---|
[2936] | 256 | |
---|
| 257 | void name(const char *name) |
---|
| 258 | { |
---|
| 259 | _name = name; |
---|
[1478] | 260 | } |
---|
[2936] | 261 | |
---|
| 262 | float aspectRatioWidth; |
---|
| 263 | float aspectRatioHeight; |
---|
| 264 | float aspectRatioDepth; |
---|
| 265 | |
---|
| 266 | GLuint id; ///< OpenGL textue identifier (==_tex->id) |
---|
| 267 | |
---|
| 268 | // Width, height and depth are point resolution, NOT physical |
---|
| 269 | // units |
---|
| 270 | /// The resolution of the data (how many points in X direction) |
---|
| 271 | int width; |
---|
| 272 | /// The resolution of the data (how many points in Y direction) |
---|
| 273 | int height; |
---|
| 274 | /// The resolution of the data (how many points in Z direction) |
---|
| 275 | int depth; |
---|
| 276 | /** |
---|
| 277 | * This is the scaling factor that will size the volume on screen. |
---|
| 278 | * A render program drawing different objects, always knows how |
---|
| 279 | * large an object is in relation to other objects. This size is |
---|
| 280 | * provided by the render engine. |
---|
| 281 | */ |
---|
| 282 | float size; |
---|
| 283 | |
---|
| 284 | int pointsetIndex; |
---|
| 285 | |
---|
| 286 | AxisRange xAxis, yAxis, zAxis, wAxis; |
---|
| 287 | std::string label[3]; ///< the labels along each axis 0:x, 1:y, 2:z |
---|
| 288 | |
---|
| 289 | static bool updatePending; |
---|
| 290 | static double valueMin, valueMax; |
---|
| 291 | |
---|
| 292 | protected: |
---|
| 293 | /** |
---|
| 294 | * This is the designated transfer function to use to |
---|
| 295 | * render this volume. |
---|
| 296 | */ |
---|
| 297 | TransferFunction *_tfPtr; |
---|
| 298 | |
---|
| 299 | float _specular; ///< Specular lighting parameter |
---|
| 300 | float _diffuse; ///< Diffuse lighting parameter |
---|
| 301 | /** |
---|
| 302 | * The scale multiplied to the opacity assigned by the |
---|
| 303 | * transfer function. Rule of thumb: higher opacity_scale |
---|
| 304 | * the object is to appear like plastic |
---|
| 305 | */ |
---|
| 306 | float _opacityScale; |
---|
| 307 | |
---|
| 308 | const char *_name; |
---|
| 309 | Vector3 _physicalMin; |
---|
| 310 | Vector3 _physicalMax; |
---|
| 311 | float *_data; |
---|
| 312 | |
---|
| 313 | int _numComponents; |
---|
| 314 | |
---|
| 315 | double _nonZeroMin; |
---|
| 316 | |
---|
| 317 | std::vector<CutPlane> _plane; ///< cut planes |
---|
| 318 | |
---|
| 319 | Texture3D *_tex; ///< OpenGL texture storing the volume |
---|
| 320 | |
---|
| 321 | Vector3 _location; |
---|
| 322 | |
---|
| 323 | /** |
---|
| 324 | * Number of slices when rendered. The greater |
---|
| 325 | * the better quality, lower speed. |
---|
| 326 | */ |
---|
| 327 | int _numSlices; |
---|
| 328 | bool _enabled; |
---|
| 329 | bool _dataEnabled; ///< show/hide cloud of volume data |
---|
| 330 | bool _outlineEnabled; ///< show/hide outline around volume |
---|
| 331 | Color _outlineColor; ///< color for outline around volume |
---|
| 332 | int _volumeType; ///< cubic or zincblende |
---|
| 333 | int _isosurface; |
---|
[835] | 334 | }; |
---|
| 335 | |
---|
[2936] | 336 | inline int |
---|
| 337 | Volume::addCutplane(int orientation, float location) |
---|
| 338 | { |
---|
| 339 | _plane.push_back(CutPlane(orientation, location)); |
---|
[1478] | 340 | return _plane.size() - 1; |
---|
[849] | 341 | } |
---|
| 342 | |
---|
[927] | 343 | inline void |
---|
[2936] | 344 | Volume::enableCutplane(int index) |
---|
[927] | 345 | { |
---|
[849] | 346 | //assert(index < plane.size()); |
---|
[1478] | 347 | _plane[index].enabled = true; |
---|
[849] | 348 | } |
---|
[927] | 349 | inline void |
---|
[2936] | 350 | Volume::disableCutplane(int index) |
---|
[927] | 351 | { |
---|
[849] | 352 | //assert(index < plane.size()); |
---|
[1478] | 353 | _plane[index].enabled = false; |
---|
[849] | 354 | } |
---|
| 355 | |
---|
[927] | 356 | inline void |
---|
[2936] | 357 | Volume::moveCutplane(int index, float location) |
---|
[927] | 358 | { |
---|
[849] | 359 | //assert(index < plane.size()); |
---|
[1478] | 360 | _plane[index].offset = location; |
---|
[849] | 361 | } |
---|
| 362 | |
---|
[2936] | 363 | inline CutPlane * |
---|
| 364 | Volume::getCutplane(int index) |
---|
[927] | 365 | { |
---|
[849] | 366 | //assert(index < plane.size()); |
---|
[1478] | 367 | return &_plane[index]; |
---|
[849] | 368 | } |
---|
| 369 | |
---|
[927] | 370 | inline int |
---|
[2936] | 371 | Volume::getCutplaneCount() |
---|
[927] | 372 | { |
---|
[1478] | 373 | return _plane.size(); |
---|
[849] | 374 | } |
---|
| 375 | |
---|
[927] | 376 | inline bool |
---|
[2936] | 377 | Volume::isCutplaneEnabled(int index) const |
---|
[927] | 378 | { |
---|
[849] | 379 | //assert(index < plane.size()); |
---|
[1478] | 380 | return _plane[index].enabled; |
---|
[849] | 381 | } |
---|
| 382 | |
---|
[927] | 383 | inline void |
---|
[2936] | 384 | Volume::setSize(float s) |
---|
[927] | 385 | { |
---|
[849] | 386 | size = s; |
---|
[2936] | 387 | aspectRatioWidth = s * _tex->aspectRatioWidth(); |
---|
| 388 | aspectRatioHeight = s * _tex->aspectRatioHeight(); |
---|
| 389 | aspectRatioDepth = s * _tex->aspectRatioDepth(); |
---|
[849] | 390 | } |
---|
| 391 | |
---|
[927] | 392 | inline void |
---|
[2936] | 393 | Volume::setOutlineColor(float *rgb) |
---|
[927] | 394 | { |
---|
[2936] | 395 | _outlineColor = Color(rgb[0], rgb[1], rgb[2]); |
---|
[849] | 396 | } |
---|
| 397 | |
---|
[927] | 398 | inline void |
---|
[2936] | 399 | Volume::getOutlineColor(float *rgb) |
---|
[927] | 400 | { |
---|
[2936] | 401 | _outlineColor.getRGB(rgb); |
---|
[849] | 402 | } |
---|
| 403 | |
---|
[927] | 404 | inline void |
---|
[2936] | 405 | Volume::setLabel(int axis, const char* txt) |
---|
[927] | 406 | { |
---|
[849] | 407 | label[axis] = txt; |
---|
| 408 | } |
---|
[870] | 409 | |
---|
[927] | 410 | inline void |
---|
[1370] | 411 | Volume::setPhysicalBBox(const Vector3& min, const Vector3& max) |
---|
| 412 | { |
---|
[2936] | 413 | _physicalMin = min; |
---|
| 414 | _physicalMax = max; |
---|
[1370] | 415 | |
---|
[2936] | 416 | /* |
---|
| 417 | aspectRatioWidth = size * 1; |
---|
| 418 | aspectRatioHeight = size * (max.y - min.y) / (max.x - min.x); |
---|
| 419 | aspectRatioDepth = size* (max.z - min.z) / (max.x - min.x); |
---|
[1370] | 420 | |
---|
[2936] | 421 | location.x = -0.5; |
---|
| 422 | location.y = -0.5* aspectRatioHeight; |
---|
| 423 | location.z = -0.5* aspectRatioDepth; |
---|
| 424 | */ |
---|
[1370] | 425 | } |
---|
| 426 | |
---|
[2936] | 427 | inline const Vector3& |
---|
| 428 | Volume::getPhysicalBBoxMin() const |
---|
[1370] | 429 | { |
---|
[2936] | 430 | return _physicalMin; |
---|
[1370] | 431 | } |
---|
| 432 | |
---|
[2936] | 433 | inline const Vector3& |
---|
| 434 | Volume::getPhysicalBBoxMax() const |
---|
[1370] | 435 | { |
---|
[2936] | 436 | return _physicalMax; |
---|
[1370] | 437 | } |
---|
| 438 | |
---|
[835] | 439 | #endif |
---|