/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2014 Torus Knot Software Ltd Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------------- */ #ifndef __Ogre_Volume_DualGridGenerator_H__ #define __Ogre_Volume_DualGridGenerator_H__ #include #include "OgreVolumeOctreeNode.h" #include "OgreVolumePrerequisites.h" #include "OgreVolumeIsoSurface.h" namespace Ogre { namespace Volume { /** \addtogroup Optional * @{ */ /** \addtogroup Volume * @{ */ /** To store the generated dual cells in a vector. */ typedef struct _OgreVolumeExport DualCell { public: Vector3 mC0; Vector3 mC1; Vector3 mC2; Vector3 mC3; Vector3 mC4; Vector3 mC5; Vector3 mC6; Vector3 mC7; DualCell(const Vector3 &c0, const Vector3 &c1, const Vector3 &c2, const Vector3 &c3, const Vector3 &c4, const Vector3 &c5, const Vector3 &c6, const Vector3 &c7) : mC0(c0), mC1(c1), mC2(c2), mC3(c3), mC4(c4), mC5(c5), mC6(c6), mC7(c7) { } } DualCell; /** To hold dual cells. */ typedef std::vector VecDualCell; /** Class for the generation of the DualGrid. */ class _OgreVolumeExport DualGridGenerator : public UtilityAlloc { protected: /// To give the debug manual object an unique name. static size_t mDualGridI; /// The entity for the debug visualization of the grid. Entity* mDualGrid; /// Starting node to generate the grid from. OctreeNode const* mRoot; /// Holds the generated dual cells of the grid. VecDualCell mDualCells; /// Whether to store the dualcells for later visualization. bool mSaveDualCells; /// To contour the dualcells. IsoSurface *mIs; /// To store the triangles of the contour. MeshBuilder *mMb; /// The maximum distance where to generate the skirts. Real mMaxMSDistance; /// The global from. Vector3 mTotalFrom; /// The total to. Vector3 mTotalTo; /** Adds a dualcell. @param c0 The first corner. @param c1 The second corner. @param c2 The third corner. @param c3 The fourth corner. @param c4 The fifth corner. @param c5 The sixth corner. @param c6 The seventh corner. */ inline void addDualCell(const Vector3 &c0, const Vector3 &c1, const Vector3 &c2, const Vector3 &c3, const Vector3 &c4, const Vector3 &c5, const Vector3 &c6, const Vector3 &c7) { addDualCell(c0, c1, c2, c3, c4, c5, c6, c7, 0); } /** Adds a dualcell with precalculated values. @param c0 The first corner. @param c1 The second corner. @param c2 The third corner. @param c3 The fourth corner. @param c4 The fifth corner. @param c5 The sixth corner. @param c6 The seventh corner. @param c7 The eighth corner. @param values The (possible) values at the corners. */ inline void addDualCell(const Vector3 &c0, const Vector3 &c1, const Vector3 &c2, const Vector3 &c3, const Vector3 &c4, const Vector3 &c5, const Vector3 &c6, const Vector3 &c7, Vector4 *values) { if (mSaveDualCells) { mDualCells.push_back(DualCell(c0, c1, c2, c3, c4, c5, c6, c7)); } Vector3 corners[8]; corners[0] = c0; corners[1] = c1; corners[2] = c2; corners[3] = c3; corners[4] = c4; corners[5] = c5; corners[6] = c6; corners[7] = c7; mIs->addMarchingCubesTriangles(corners, values, mMb); Vector3 from = mRoot->getFrom(); Vector3 to = mRoot->getTo(); if (corners[0].z == from.z && corners[0].z != mTotalFrom.z) { mIs->addMarchingSquaresTriangles(corners, values, IsoSurface::MS_CORNERS_BACK, mMaxMSDistance, mMb); } if (corners[2].z == to.z && corners[2].z != mTotalTo.z) { mIs->addMarchingSquaresTriangles(corners, values, IsoSurface::MS_CORNERS_FRONT, mMaxMSDistance, mMb); } if (corners[0].x == from.x && corners[0].x != mTotalFrom.x) { mIs->addMarchingSquaresTriangles(corners, values, IsoSurface::MS_CORNERS_LEFT, mMaxMSDistance, mMb); } if (corners[1].x == to.x && corners[1].x != mTotalTo.x) { mIs->addMarchingSquaresTriangles(corners, values, IsoSurface::MS_CORNERS_RIGHT, mMaxMSDistance, mMb); } if (corners[5].y == to.y && corners[5].y != mTotalTo.y) { mIs->addMarchingSquaresTriangles(corners, values, IsoSurface::MS_CORNERS_TOP, mMaxMSDistance, mMb); } if (corners[0].y == from.y && corners[0].y != mTotalFrom.y) { mIs->addMarchingSquaresTriangles(corners, values, IsoSurface::MS_CORNERS_BOTTOM, mMaxMSDistance, mMb); } } /* Startpoint for the creation recursion. @param n The node to start with. */ void nodeProc(const OctreeNode *n); /* faceProc with variing X and Y of the nodes, see the paper for faceProc(). Direction of parameters: Z+ (n0 and n3 for example of parent cell) @param n0 The first node. @param n1 The second node. */ void faceProcXY(const OctreeNode *n0, const OctreeNode *n1); /* faceProc with variing Z and Y of the nodes, see the paper for faceProc(). Direction of parameters: X+ (n0 and n1 for example of parent cell) @param n0 The first node. @param n1 The second node. */ void faceProcZY(const OctreeNode *n0, const OctreeNode *n1); /* faceProc with variing X and Z of the nodes, see the paper for faceProc(). Direction of parameters: Y- (n4 and n0 for example of parent cell) @param n0 The first node. @param n1 The second node. */ void faceProcXZ(const OctreeNode *n0, const OctreeNode *n1); /** edgeProc with variing X of the nodes, see the paper for edgeProc(). Direction of parameters: Z+, Y around the clock (n0, n3, n7, n4 for example of the parent cell) @param n0 The first node. @param n1 The second node. @param n2 The third node. @param n3 The fourth node. */ void edgeProcX(const OctreeNode *n0, const OctreeNode *n1, const OctreeNode *n2, const OctreeNode *n3); /** edgeProc with variing Y of the nodes, see the paper for edgeProc(). Direction of parameters: X+, Z around the clock (n0, n1, n2, n3 for example of the parent cell) @param n0 The first node. @param n1 The second node. @param n2 The third node. @param n3 The fourth node. */ void edgeProcY(const OctreeNode *n0, const OctreeNode *n1, const OctreeNode *n2, const OctreeNode *n3); /** edgeProc with variing Z of the nodes, see the paper for edgeProc(). Direction of parameters: X+, Y around the clock (n7, n6, n2, n3 for example of the parent cell) @param n0 The first node. @param n1 The second node. @param n2 The third node. @param n3 The fourth node. */ void edgeProcZ(const OctreeNode *n0, const OctreeNode *n1, const OctreeNode *n2, const OctreeNode *n3); /* vertProc of the nodes, see the paper for vertProc. Difference to the paper: The cells to the octree border are already created here and not with another traversion. @param n0 The first node. @param n1 The second node. @param n3 The third node. @param n4 The fourth node. @param n5 The fifth node. @param n6 The sixth node. @param n7 The seventh node. */ void vertProc(const OctreeNode *n0, const OctreeNode *n1, const OctreeNode *n2, const OctreeNode *n3, const OctreeNode *n4, const OctreeNode *n5, const OctreeNode *n6, const OctreeNode *n7); /* Creates the bordercells. @param n0 The first node. @param n1 The second node. @param n3 The third node. @param n4 The fourth node. @param n5 The fifth node. @param n6 The sixth node. @param n7 The seventh node. */ void createBorderCells(const OctreeNode *n0, const OctreeNode *n1, const OctreeNode *n2, const OctreeNode *n3, const OctreeNode *n4, const OctreeNode *n5, const OctreeNode *n6, const OctreeNode *n7); public: /** Constructor. */ DualGridGenerator(void); /** Generates the dualgrid of the given octree root node. @param root The octree root node. @param is To contour the dualcells. @param mb To store the triangles of the contour. @param maxMSDistance The maximum distance to the isosurface where to generate skirts. @param totalFrom The global from. @param totalTo The global to. @param saveDualCells Whether to save the generated dualcells of the generated dual cells. */ void generateDualGrid(const OctreeNode *root, IsoSurface *is, MeshBuilder *mb, Real maxMSDistance, const Vector3 &totalFrom, const Vector3 &totalTo, bool saveDualCells); /** Gets the lazily created entity of the dualgrid debug visualization. @param sceneManager The scenemanager creating the entity. @return The entity. Might be null if no dualcells are available. */ Entity* getDualGrid(SceneManager *sceneManager); /** Gets the amount of generated dual cells. @return The amount of generated dual cells. */ inline size_t getDualCellCount(void) const { return mDualCells.size(); } /** Gets a dual cell. @param i The index of the wanted dual cell. @return The dual cell. */ inline DualCell getDualCell(size_t i) const { return mDualCells[i]; } }; /** @} */ /** @} */ } } #endif