00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __GEO_PrimVolume__
00020 #define __GEO_PrimVolume__
00021
00022 #include <UT/UT_VoxelArray.h>
00023
00024 #include "GEO_API.h"
00025 #include "GEO_Vertex.h"
00026 #include "GEO_Primitive.h"
00027
00028 class UT_JSONWriter;
00029 class UT_JSONParser;
00030 class GA_SaveMap;
00031 class GA_LoadMap;
00032
00033 enum GEO_VolumeBorder
00034 {
00035 GEO_VOLUMEBORDER_CONSTANT,
00036 GEO_VOLUMEBORDER_REPEAT,
00037 GEO_VOLUMEBORDER_STREAK,
00038 GEO_VOLUMEBORDER_SDF,
00039 NUM_GEO_VOLUMEBORDERS
00040 };
00041
00042 enum GEO_VolumeVis
00043 {
00044 GEO_VOLUMEVIS_SMOKE,
00045 GEO_VOLUMEVIS_RAINBOW,
00046 GEO_VOLUMEVIS_ISO,
00047 GEO_VOLUMEVIS_INVISIBLE,
00048 NUM_GEO_VOLUMEVIS
00049 };
00050
00051
00052
00053
00054
00055
00056 class GEO_API GEO_PrimVolumeXform
00057 {
00058 public:
00059 inline UT_Vector3 toVoxelSpace(UT_Vector3 pos) const
00060 {
00061 pos -= myCenter;
00062 pos *= myInverseXform;
00063
00064
00065 if (myHasTaper)
00066 {
00067 fpreal zscale = (1 - pos.z()) * 0.5f;
00068 fpreal taperx = 1 + (-1 + myTaperX) * zscale;
00069 fpreal tapery = 1 + (-1 + myTaperY) * zscale;
00070
00071 if (taperx == 0.0f)
00072 pos.x() = 0.0;
00073 else
00074 pos.x() /= taperx;
00075 if (tapery == 0.0f)
00076 pos.y() = 0.0;
00077 else
00078 pos.y() /= tapery;
00079 }
00080
00081
00082
00083 pos.x() += 1;
00084 pos.y() += 1;
00085 pos.z() += 1;
00086 pos *= 0.5;
00087
00088 return pos;
00089 }
00090
00091 inline UT_Vector3 fromVoxelSpace(UT_Vector3 pos) const
00092 {
00093
00094 pos.x() -= 0.5;
00095 pos.y() -= 0.5;
00096 pos.z() -= 0.5;
00097 pos *= 2;
00098
00099
00100 if (myHasTaper)
00101 {
00102 fpreal zscale = (1 - pos.z()) * 0.5f;
00103 fpreal taperx = 1 + (-1 + myTaperX) * zscale;
00104 fpreal tapery = 1 + (-1 + myTaperY) * zscale;
00105
00106 pos.x() *= taperx;
00107 pos.y() *= tapery;
00108 }
00109
00110 pos *= myXform;
00111 pos += myCenter;
00112
00113 return pos;
00114 }
00115
00116 inline void toVoxelSpace(UT_BoundingBox &box) const
00117 {
00118 int i;
00119 UT_Vector3 v[8] = {
00120 UT_Vector3(box.xmin(), box.ymin(), box.zmin()),
00121 UT_Vector3(box.xmin(), box.ymin(), box.zmax()),
00122 UT_Vector3(box.xmin(), box.ymax(), box.zmin()),
00123 UT_Vector3(box.xmin(), box.ymax(), box.zmax()),
00124 UT_Vector3(box.xmax(), box.ymin(), box.zmin()),
00125 UT_Vector3(box.xmax(), box.ymin(), box.zmax()),
00126 UT_Vector3(box.xmax(), box.ymax(), box.zmin()),
00127 UT_Vector3(box.xmax(), box.ymax(), box.zmax()),
00128 };
00129
00130 box.initBounds();
00131 for (i = 0; i < 8; i++)
00132 {
00133 box.enlargeBounds(toVoxelSpace(v[i]));
00134 }
00135 }
00136
00137 inline void fromVoxelSpace(UT_BoundingBox &box) const
00138 {
00139 int i;
00140 UT_Vector3 v[8] = {
00141 UT_Vector3(box.xmin(), box.ymin(), box.zmin()),
00142 UT_Vector3(box.xmin(), box.ymin(), box.zmax()),
00143 UT_Vector3(box.xmin(), box.ymax(), box.zmin()),
00144 UT_Vector3(box.xmin(), box.ymax(), box.zmax()),
00145 UT_Vector3(box.xmax(), box.ymin(), box.zmin()),
00146 UT_Vector3(box.xmax(), box.ymin(), box.zmax()),
00147 UT_Vector3(box.xmax(), box.ymax(), box.zmin()),
00148 UT_Vector3(box.xmax(), box.ymax(), box.zmax()),
00149 };
00150
00151 box.initBounds();
00152 for (i = 0; i < 8; i++)
00153 {
00154 box.enlargeBounds(fromVoxelSpace(v[i]));
00155 }
00156 }
00157
00158 public:
00159 UT_Matrix3 myXform, myInverseXform;
00160 UT_Vector3 myCenter;
00161 bool myHasTaper;
00162 float myTaperX, myTaperY;
00163 };
00164
00165 class GEO_API GEO_PrimVolume : public GEO_Primitive
00166 {
00167 public:
00168 GEO_PrimVolume(GEO_Detail *d, GA_Offset offset = GA_INVALID_OFFSET);
00169 virtual ~GEO_PrimVolume();
00170
00171
00172
00173 virtual int getBBox(UT_BoundingBox *bbox) const;
00174 virtual void addToBSphere(UT_BoundingSphere *bsphere) const;
00175 virtual void enlargePointBounds(UT_BoundingBox &box) const;
00176
00177
00178
00179
00180
00181 virtual bool enlargeBoundingBox(UT_BoundingRect &b,
00182 const GA_Attribute *P) const;
00183 virtual bool enlargeBoundingBox(UT_BoundingBox &b,
00184 const GA_Attribute *P) const;
00185
00186
00187
00188
00189
00190 virtual bool enlargeBoundingSphere(UT_BoundingSphere &b,
00191 const GA_Attribute *P) const;
00192
00193 virtual UT_Vector3 baryCenter() const;
00194 virtual UT_Vector3 computeNormal() const;
00195 virtual bool saveH9(ostream &os, bool binary,
00196 const UT_RefArray<GA_AttribSaveDataH9> &prim_attribs,
00197 const UT_RefArray<GA_AttribSaveDataH9> &vtx_attribs)
00198 const;
00199 virtual bool loadH9(UT_IStream &is,
00200 const UT_RefArray<GA_AttribLoadDataH9> &prim_attribs,
00201 const UT_RefArray<GA_AttribLoadDataH9> &vtx_attribs);
00202
00203 bool saveVoxelArray(UT_JSONWriter &w,
00204 const GA_SaveMap &map) const;
00205 bool loadVoxelArray(UT_JSONParser &p,
00206 const GA_LoadMap &map);
00207
00208 bool loadRes(const UT_JSONValue &jval);
00209 bool saveBorder(UT_JSONWriter &w,
00210 const GA_SaveMap &map) const;
00211 bool loadBorder(UT_JSONParser &p,
00212 const GA_LoadMap &map);
00213 bool saveCompression(UT_JSONWriter &w,
00214 const GA_SaveMap &map) const;
00215 bool loadCompression(UT_JSONParser &p,
00216 const GA_LoadMap &map);
00217 bool saveVisualization(UT_JSONWriter &w,
00218 const GA_SaveMap &map) const;
00219 bool loadVisualization(UT_JSONParser &p,
00220 const GA_LoadMap &map);
00221
00222
00223
00224
00225
00226 virtual void transform(const UT_Matrix4 &mat);
00227
00228 virtual void untransform(void);
00229 virtual GEO_Primitive *copy(int preserve_shared_pts = 0) const;
00230 virtual void copyPrimitive(const GEO_Primitive *src,
00231 GEO_Point **ptredirect);
00232 virtual void copyUnwiredForMerge(const GA_Primitive *src,
00233 const GA_MergeMap &map);
00234 virtual void addPointRefToGroup(GA_PointGroup &grp) const;
00235
00236 virtual int vertexApply(int (*a)(GEO_Vertex, void *), void *);
00237 virtual int vertexApply(int (*a)(const GEO_Vertex &, void *),
00238 void *) const;
00239 virtual void reverse(void);
00240
00241 virtual GA_Size getVertexCount() const;
00242 virtual GA_Offset getVertexOffset(GA_Size index) const;
00243
00244
00245
00246
00247
00248
00249 virtual int detachPoints (GA_PointGroup &grp);
00250
00251
00252
00253
00254 virtual GA_DereferenceStatus dereferencePoint(GA_Offset point,
00255 bool dry_run=false);
00256 virtual GA_DereferenceStatus dereferencePoints(
00257 const GA_RangeMemberQuery &pt_q,
00258 bool dry_run=false);
00259
00260 virtual bool isDegenerate() const;
00261
00262
00263
00264 virtual void unitLengthToUnitPair(float ulength, float vlength,
00265 float &uparm, float &vparm)const;
00266
00267 virtual void unitToUnitLengthPair(float uparm, float vparm,
00268 float &ulength, float &vlength)
00269 const;
00270
00271 virtual fpreal calcVolume(const UT_Vector3 &refpt) const;
00272 virtual fpreal calcArea() const;
00273
00274
00275
00276
00277 void setVertex(GEO_Point *ppt)
00278 {
00279 wireVertex(myVertex,ppt ? ppt->getMapOffset()
00280 : GA_INVALID_OFFSET);
00281 }
00282 void setVertexPoint(GA_Offset pt)
00283 {
00284 wireVertex(myVertex, pt);
00285 }
00286
00287
00288
00289 void assignVertex(GA_Offset new_vtx, bool update_topology);
00290
00291
00292 virtual void stashed(int onoff,
00293 GA_Offset offset = GA_INVALID_OFFSET);
00294
00295 const UT_Matrix3 &getTransform(void) const { return myXform; }
00296 void setTransform(const UT_Matrix3 &m)
00297 { myXform = m;
00298 myInverseXform = m;
00299 myInverseXform.invert();
00300 }
00301
00302 void getTransform4( UT_Matrix4 &matx) const;
00303 void getTransform4( UT_DMatrix4 &matx) const;
00304 void setTransform4(const UT_Matrix4 &matx);
00305 void setTransform4(const UT_DMatrix4 &matx);
00306
00307
00308 const UT_Matrix3 &getInverseTransform() const { return myInverseXform; }
00309 void getInverseTransform4(UT_Matrix4 &matx) const;
00310
00311 float getTaperX(void) const { return myTaperX; }
00312 void setTaperX(float t) { myTaperX = t; }
00313 float getTaperY(void) const { return myTaperY; }
00314 void setTaperY(float t) { myTaperY = t; }
00315
00316
00317
00318 bool isAligned(const GEO_PrimVolume *vol) const;
00319
00320
00321
00322 GEO_PrimVolumeXform getSpaceTransform() const;
00323
00324
00325 UT_Vector3 toVoxelSpace(const UT_Vector3 &pos) const;
00326
00327 UT_Vector3 fromVoxelSpace(const UT_Vector3 &pos) const;
00328
00329
00330 void toVoxelSpace(UT_BoundingBox &box) const;
00331
00332 void fromVoxelSpace(UT_BoundingBox &box) const;
00333
00334
00335 void setVoxels(const UT_VoxelArrayF *vox);
00336 void setVoxels(UT_VoxelArrayHandleF handle);
00337
00338
00339
00340 void stealVoxels(UT_VoxelArrayF *vox);
00341
00342
00343
00344
00345
00346
00347 UT_VoxelArrayHandleF getVoxelHandle() const;
00348
00349
00350 UT_VoxelArrayWriteHandleF getVoxelWriteHandle();
00351
00352
00353
00354 bool indexToPos(int x, int y, int z, UT_Vector3 &pos) const;
00355 void findexToPos(UT_Vector3 index, UT_Vector3 &pos) const;
00356
00357
00358
00359 bool isInside(UT_Vector3 pos) const;
00360
00361
00362
00363
00364 bool isInsideStrict(UT_Vector3 pos) const;
00365
00366
00367
00368 bool posToIndex(UT_Vector3 pos, int &x, int &y, int &z) const;
00369
00370
00371 fpreal getValue(const UT_Vector3 &pos) const;
00372 UT_Vector3 getGradient(const UT_Vector3 &pos) const;
00373
00374
00375
00376 fpreal getValue(const UT_Vector3 &pos, const UT_VoxelArrayReadHandleF &handle) const;
00377
00378
00379 fpreal getValueAtIndex(int ix, int iy, int iz) const;
00380
00381 void getRes(int &rx, int &ry, int &rz) const;
00382
00383
00384 fpreal getVoxelDiameter() const;
00385
00386
00387 UT_Vector3 getVoxelSize() const;
00388
00389
00390
00391 fpreal calcPositiveDensity() const;
00392
00393
00394 fpreal calcMinimum() const;
00395 fpreal calcMaximum() const;
00396 fpreal calcAverage() const;
00397
00398
00399
00400
00401 bool isSDF() const { return myIsSDF; }
00402
00403
00404 static const char *getBorderToken(GEO_VolumeBorder border);
00405 static GEO_VolumeBorder getBorderEnum(const char *token,
00406 GEO_VolumeBorder def=GEO_VOLUMEBORDER_STREAK);
00407 void setBorder(GEO_VolumeBorder border, fpreal val);
00408 GEO_VolumeBorder getBorder() const;
00409 fpreal getBorderValue() const;
00410
00411
00412 fpreal getCompressionTolerance() const;
00413 void setCompressionTolerance(fpreal tol);
00414 void recompress();
00415
00416
00417 static const char *getVisualizationToken(GEO_VolumeVis vis);
00418 static GEO_VolumeVis getVisualizationEnum(const char *vis,
00419 GEO_VolumeVis def=GEO_VOLUMEVIS_SMOKE);
00420 void setVisualization(GEO_VolumeVis vis, fpreal iso, fpreal density);
00421 fpreal getVisIso() const { return myVisIso; }
00422 fpreal getVisDensity() const { return myVisDensity; }
00423 GEO_VolumeVis getVisualization() const { return myVisMode; }
00424
00425 virtual const GA_PrimitiveJSON *getJSON() const;
00426
00427
00428
00429 class serialize
00430 {
00431 public:
00432 serialize()
00433 : myVoxels()
00434 , myBorder(0)
00435 , myXres(0)
00436 , myYres(0)
00437 , myZres(0)
00438 , myEntries(0)
00439 , myCurr(0)
00440 {}
00441 serialize(const serialize &src)
00442 : myVoxels(src.myVoxels)
00443 , myBorder(src.myBorder)
00444 , myXres(src.myXres)
00445 , myYres(src.myYres)
00446 , myZres(src.myZres)
00447 , myEntries(src.myEntries)
00448 , myCurr(src.myCurr)
00449 {}
00450 serialize &operator=(const serialize &src)
00451 {
00452 myVoxels = src.myVoxels;
00453 myBorder = src.myBorder;
00454 myXres = src.myXres;
00455 myYres = src.myYres;
00456 myZres = src.myZres;
00457 myEntries = src.myEntries;
00458 myCurr = src.myCurr;
00459 return *this;
00460 }
00461
00462 fpreal getVoxel(exint index) const
00463 {
00464 if (index >= 0 && index < myEntries)
00465 {
00466 exint x, y, z;
00467 x = index % myXres;
00468 index = (index - x) / myXres;
00469 y = index % myYres;
00470 index = (index - y) / myYres;
00471 z = index % myZres;
00472 return (*myVoxels)(x, y, z);
00473 }
00474 return myBorder;
00475 }
00476
00477
00478
00479 bool atEnd() const { return myCurr >= myEntries; }
00480 void rewind() { myCurr = 0; }
00481 void advance() { myCurr++; }
00482 serialize &operator++() { advance(); return *this; }
00483
00484
00485
00486 exint entries() const { return myEntries; }
00487 exint index() const { return myCurr; }
00488 fpreal voxel() const { return getVoxel(myCurr); }
00489 private:
00490 serialize(const GEO_PrimVolume &prim)
00491 : myVoxels(prim.getVoxelHandle())
00492 , myCurr(0)
00493 {
00494 prim.getRes(myXres, myYres, myZres);
00495 myBorder = prim.getBorderValue();
00496 myEntries = myXres*myYres*myZres;
00497 }
00498 UT_VoxelArrayReadHandleF myVoxels;
00499 fpreal myBorder;
00500 exint myCurr, myEntries;
00501 int myXres, myYres, myZres;
00502 friend class GEO_PrimVolume;
00503 };
00504 serialize getSerialize() const { return serialize(*this); }
00505
00506 protected:
00507 GEO_PrimVolume(const GA_MergeMap &map,
00508 GEO_Detail &detail,
00509 GA_Offset offset,
00510 const GEO_PrimVolume &src);
00511 static GA_PrimitiveFamilyMask buildFamilyMask()
00512 { return GA_FAMILY_NONE; }
00513
00514
00515 virtual void swapVertexOffsets(const GA_Defragment &defrag);
00516
00517
00518
00519 static GA_IntrinsicManager::Registrar
00520 registerIntrinsics(GA_PrimitiveDefinition &defn);
00521
00522
00523 virtual int localIntrinsicTupleSize(
00524 const GA_IntrinsicEval &eval) const;
00525 virtual int localGetIntrinsicS(const GA_IntrinsicEval &eval,
00526 UT_String &value) const;
00527 virtual int localGetIntrinsicSA(const GA_IntrinsicEval &eval,
00528 UT_StringArray &value) const;
00529 virtual int localGetIntrinsicI(const GA_IntrinsicEval &eval,
00530 int64 *value, GA_Size size) const;
00531 virtual int localGetIntrinsicF(const GA_IntrinsicEval &eval,
00532 fpreal *value, GA_Size size) const;
00533 virtual int localSetIntrinsicSA(const GA_IntrinsicEval &eval,
00534 const UT_StringArray &value);
00535 virtual int localSetIntrinsicSS(const GA_IntrinsicEval &eval,
00536 const char **value, GA_Size size);
00537 virtual int localSetIntrinsicI(const GA_IntrinsicEval &eval,
00538 const int64 *value, GA_Size size);
00539 virtual int localSetIntrinsicF(const GA_IntrinsicEval &eval,
00540 const fpreal *value, GA_Size size);
00541
00542
00543
00544 virtual void copyOffsetPrimitive(const GEO_Primitive *src,
00545 int basept);
00546 virtual bool savePrivateH9(ostream &os, bool binary) const;
00547 virtual bool loadPrivateH9(UT_IStream &is);
00548 virtual int isPointUsed(GA_GBPoint *pt) const;
00549
00550
00551 bool loadVoxelDataH9(UT_IStream &is,
00552 UT_VoxelArrayWriteHandleF voxels,
00553 int version);
00554
00555 GA_Offset vertexPoint() const
00556 { return getDetail().vertexPoint(myVertex); }
00557
00558 UT_VoxelArrayHandleF myVoxelHandle;
00559
00560 virtual bool evaluatePointRefMap(GA_Offset result_vtx,
00561 GA_AttributeRefMap &hlist,
00562 fpreal u, fpreal v, uint du, uint dv) const;
00563 virtual int evaluatePointV4( UT_Vector4 &pos, float u, float v = 0,
00564 unsigned du=0, unsigned dv=0) const
00565 {
00566 return GEO_Primitive::evaluatePoint(pos, u, v,
00567 du, dv);
00568 }
00569 virtual bool evaluateBaryCenterRefMap(GA_Offset result_vertex,
00570 GA_AttributeRefMap &hlist) const;
00571
00572 virtual bool evaluateInteriorPointRefMap(GA_Offset result,
00573 GA_AttributeRefMap &map,
00574 fpreal u, fpreal v, fpreal w = 0) const;
00575 virtual int evaluateInteriorPointV4(UT_Vector4 &pos,
00576 fpreal u, fpreal v, fpreal w = 0) const;
00577
00578 private:
00579 GA_Offset myVertex;
00580 UT_Matrix3 myXform;
00581 UT_Matrix3 myInverseXform;
00582 bool myIsSDF : 1;
00583
00584 GEO_VolumeVis myVisMode;
00585 fpreal myVisIso;
00586 fpreal myVisDensity;
00587
00588
00589
00590
00591 fpreal myTaperX, myTaperY;
00592
00593 friend ostream &operator<<(ostream &os, const GEO_PrimVolume &d)
00594 {
00595 d.saveH9(os, 0,
00596 GEO_Primitive::theEmptySaveAttribs,
00597 GEO_Primitive::theEmptySaveAttribs);
00598 return os;
00599 }
00600
00601
00602
00603 bool myStashedState : 1;
00604 };
00605
00606 #endif