00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef MarchingCubes_INCLUDE_ONCE
00033 #define MarchingCubes_INCLUDE_ONCE
00034
00035 #include <vlVolume/link_config.hpp>
00036 #include <vlGraphics/Geometry.hpp>
00037
00038 namespace vl
00039 {
00040
00041
00042
00046 class VLVOLUME_EXPORT Volume: public Object
00047 {
00051 struct Cube
00052 {
00053 Cube(): mMin(0), mMax(0) {}
00054 float mMin, mMax;
00055 bool includes(float v) const { return v >= mMin && v <= mMax; }
00056 };
00057 public:
00058 virtual const char* className() { return "vl::Volume"; }
00059
00060 Volume();
00061
00067 void setup(float* data, bool use_directly, bool copy_data, const fvec3& bottom_left, const fvec3& top_right, const ivec3& slices);
00068
00069 void setup(const Volume&);
00070
00074 ref<Volume> downsample() const;
00075
00076 const float* values() const { return mValues; }
00077
00078 float* values() { return mValues; }
00079
00080 const float& value(int i) const { return mValues[i]; }
00081
00082 float& value(int i) { return mValues[i]; }
00083
00084 const float& value(int x, int y, int z) const { return mValues[x + mSlices.x()*y + mSlices.x()*mSlices.y()*z]; }
00085
00086 float& value(int x, int y, int z) { return mValues[x + mSlices.x()*y + mSlices.x()*mSlices.y()*z]; }
00087
00089 void normalHQ(fvec3& normal, const fvec3& v, float dx, float dy, float dz);
00090
00092 void normalLQ(fvec3& normal, const fvec3& v, float dx, float dy, float dz);
00093
00095 float sampleSmooth(float x, float y, float z) const;
00096
00098 float sampleNearest(float x, float y, float z) const;
00099
00100 fvec3 coordinate(int x, int y, int z) const { return mBottomLeft + fvec3(float(mCellSize.x()*x), float(mCellSize.y()*y), float(mCellSize.z()*z)); }
00101
00102 const fvec3& bottomLeft() const { return mBottomLeft; }
00103
00104 const fvec3& topRight() const { return mTopRight; }
00105
00106 const ivec3& slices() const { return mSlices; }
00107
00108 fvec3 size() const { return mSize; }
00109
00110 float computeMinimum() const;
00111
00112 float computeMaximum() const;
00113
00114 float computeAverage() const;
00115
00116 float minimum() const { return mMinimum; }
00117
00118 float maximum() const { return mMaximum; }
00119
00120 float average() const { return mAverage; }
00121
00122 const Volume::Cube& cube(int x, int y, int z) const
00123 {
00124 VL_CHECK(x<slices().x()-1)
00125 VL_CHECK(y<slices().y()-1)
00126 VL_CHECK(z<slices().z()-1)
00127 return mCubes[ x + y*(slices().x()-1) + z*(slices().x()-1)*(slices().y()-1) ];
00128 }
00129
00131 const fvec3& cellSize() const { return mCellSize; }
00132
00134 bool dataIsDirty() const { return mDataIsDirty; }
00135
00137 void setDataDirty() { mDataIsDirty = true; }
00138
00139 void setupInternalData();
00140
00141 protected:
00142 std::vector<float> mInternalValues;
00143 float* mValues;
00144 fvec3 mBottomLeft;
00145 fvec3 mTopRight;
00146 fvec3 mSize;
00147 ivec3 mSlices;
00148 fvec3 mCellSize;
00149 float mMinimum;
00150 float mMaximum;
00151 float mAverage;
00152 bool mDataIsDirty;
00153
00154 std::vector<Cube> mCubes;
00155 };
00156
00157
00158
00162 class VolumeInfo: public Object
00163 {
00164 public:
00165 virtual const char* className() { return "vl::VolumeInfo"; }
00166
00167 VolumeInfo(Volume* vol, float threshold, const fvec4& color)
00168 {
00169 VL_DEBUG_SET_OBJECT_NAME()
00170 mColor = color;
00171 mThreshold = threshold;
00172 mVolume = vol;
00173 mVert0 = -1;
00174 mVertC = -1;
00175 }
00176
00177 VolumeInfo(Volume* vol, float threshold)
00178 {
00179 VL_DEBUG_SET_OBJECT_NAME()
00180 mThreshold = threshold;
00181 mVolume = vol;
00182 mVert0 = -1;
00183 mVertC = -1;
00184 }
00185
00186 void setColor(const fvec4& col) { mColor = col; }
00187 const fvec4& color() const { return mColor; }
00188
00189 void setThreshold(float t) { mThreshold = t; }
00190 float threshold() const { return mThreshold; }
00191
00192 void setVolume(Volume* vol) { mVolume = vol; }
00193 Volume* volume() const { return mVolume.get(); }
00194
00195 void setVert0(int index) { mVert0 = index; }
00196 int vert0() const { return mVert0; }
00197
00198 void setVertC(int count) { mVertC = count; }
00199 int vertC() const { return mVertC; }
00200
00201 protected:
00202 fvec4 mColor;
00203 float mThreshold;
00204 ref<Volume> mVolume;
00205 int mVert0, mVertC;
00206 };
00207
00208
00209
00213 class VLVOLUME_EXPORT MarchingCubes
00214 {
00215 public:
00216 MarchingCubes();
00217
00218 void run(bool generate_colors);
00219
00220 void reset();
00221
00222 const Collection<VolumeInfo>* volumeInfo() const { return &mVolumeInfo; }
00223 Collection<VolumeInfo>* volumeInfo() { return &mVolumeInfo; }
00224
00225 void updateColor(const fvec3& color, int volume_index);
00226 void updateColor(const fvec4& color, int volume_index);
00227 void updateAlpha(float alpha, int volume_index);
00228
00230 void setHighQualityNormals(bool hq) { mHighQualityNormals = hq; }
00232 bool highQualityNormals() const { return mHighQualityNormals; }
00233
00234 public:
00235 ref<ArrayFloat3> mVertsArray;
00236 ref<ArrayFloat3> mNormsArray;
00237 ref<ArrayFloat4> mColorArray;
00238 ref<DrawElementsUInt> mDrawElements;
00239
00240 protected:
00241 void computeEdges(Volume*, float threshold);
00242 void processCube(int x, int y, int z, Volume* vol, float threshold);
00243
00244 private:
00245 std::vector<fvec3> mVerts;
00246 std::vector<fvec3> mNorms;
00247 std::vector<fvec4> mColors;
00248 std::vector<unsigned int> mIndices;
00249 struct Edge
00250 {
00251 Edge(): mX(-1), mY(-1), mZ(-1) {}
00252 int mX, mY, mZ;
00253 };
00254 std::vector<Edge> mEdges;
00255 std::vector<usvec3> mCubes;
00256 Collection<VolumeInfo> mVolumeInfo;
00257 bool mHighQualityNormals;
00258
00259 protected:
00260 static const int mTriangleConnectionTable[256][16];
00261 static const int mCubeEdgeFlags[256];
00262 };
00263
00264 }
00265
00266 #endif