/* ----------------------------------------------------------------------------- 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_OctreeNode_H__ #define __Ogre_Volume_OctreeNode_H__ #include "OgreVolumePrerequisites.h" #include "OgreVector.h" namespace Ogre { namespace Volume { /** \addtogroup Optional * @{ */ /** \addtogroup Volume * @{ */ class OctreeNodeSplitPolicy; class Source; /** A node in the volume octree. */ class _OgreVolumeExport OctreeNode : public UtilityAlloc { protected: /// Factor to the diagonal of the cell to decide whether this cell is near the isosurface or not. static const Real NEAR_FACTOR; /// To count some indices while creating the debug view and recursing through the instances. static uint32 mGridPositionCount; /// To give the debug manual object an unique name. static size_t mNodeI; /// The back lower left corner of the cell. Vector3 mFrom; /// The front upper right corner of the cell. Vector3 mTo; /// The children of this node. OctreeNode **mChildren; /// Holds the debug visualization of the octree. Just set in the root. Entity* mOctreeGrid; /// Density and gradient of the center. Vector4 mCenterValue; /** Method to actually add the lines of the octree cells to the debug visualization. @param manual The manual object to add the lines to if this is a leaf in the octree. */ void buildOctreeGridLines(ManualObject *manual) const; public: /// Even in an OCtree, the amount of children should not be hardcoded. static const size_t OCTREE_CHILDREN_COUNT; /** Gets the center and width / height / depth vector of the children of a node. @param from The back lower left corner of the cell. @param to The front upper right corner of the cell. @param center Out parameter of the calculated center. @param width Out parameter of the width vector (width in x, rest zero). @param height Out parameter of the height vector (height in y, rest zero). @param depth Out parameter of the depth vector (depth in z, rest zero). */ static inline void getChildrenDimensions(const Vector3 &from, const Vector3 &to, Vector3 ¢er, Vector3 &width, Vector3 &height, Vector3 &depth) { center = (to - from) / (Real)2.0; width.x = center.x; width.y = (Real)0.0; width.z = (Real)0.0; height.x = (Real)0.0; height.y = center.y; height.z = (Real)0.0; depth.x = (Real)0.0; depth.y = (Real)0.0; depth.z = center.z; center += from; } /** Constructor. @param from The back lower left corner of the cell. @param to The front upper right corner of the cell. */ OctreeNode(const Vector3 &from = Vector3::ZERO, const Vector3 &to = Vector3::ZERO); /** Destructor. */ virtual ~OctreeNode(void); /** Factory method to create octree nodes. @param from The back lower left corner of the cell. @param to The front upper right corner of the cell. @return The created entity. Make sure to destroy it when you don't need it anymore. */ virtual OctreeNode* createInstance(const Vector3& from, const Vector3& to); /** Splits this cell if the split policy says so. @param splitPolicy Defines the policy deciding whether to split this node or not. @param src The volume source. @param geometricError The accepted geometric error. */ void split(const OctreeNodeSplitPolicy *splitPolicy, const Source *src, const Real geometricError); /** Getter for the octree debug visualization of the octree starting with this node. @param sceneManager The scenemanager creating the actual entity. @return The lazily created debug visualization. */ Entity* getOctreeGrid(SceneManager *sceneManager); /** Setter for the from-part of this cell. @param from The back lower left corner of the cell. */ inline void setFrom(Vector3 from) { mFrom = from; } /** Setter for the to-part of this cell. @param to The front upper right corner of the cell. */ inline void setTo(Vector3 to) { mTo = to; } /** Gets whether this cell has any children. @return True if so. */ inline bool isSubdivided(void) const { return mChildren != 0; } /** Gets an octree child. Enumeration: 4 5 7 6 0 1 3 2 @param i The child index. @return The child. */ inline const OctreeNode* getChild(const size_t i) const { return mChildren[i]; } /** Gets the center of this cell. @return The center. */ inline const Vector3 getCenter(void) const { return (mFrom + mTo) / (Real)2.0; } /** Gets the back lower left corner of the cell. @return The back lower left corner of the cell. */ inline const Vector3& getFrom(void) const { return mFrom; } /** Gets the front upper right corner of the cell. @return The front upper right corner of the cell. */ inline const Vector3& getTo(void) const { return mTo; } /** Gets whether this cell is at the left of the given root cell. @param root The octree root node to test against. @return true if so. */ inline bool isBorderLeft(const OctreeNode &root) const { return mFrom.x == root.mFrom.x; } /** Gets whether this cell is at the right of the given root cell. @param root The octree root node to test against. @return true if so. */ inline bool isBorderRight(const OctreeNode &root) const { return mTo.x == root.mTo.x; } /** Gets whether this cell is at the bottom of the given root cell. @param root The octree root node to test against. @return true if so. */ inline bool isBorderBottom(const OctreeNode &root) const { return mFrom.y == root.mFrom.y; } /** Gets whether this cell is at the top of the given root cell. @param root The octree root node to test against. @return true if so. */ inline bool isBorderTop(const OctreeNode &root) const { return mTo.y == root.mTo.y; } /** Gets whether this cell is at the back of the given root cell. @param root The octree root node to test against. @return true if so. */ inline bool isBorderBack(const OctreeNode &root) const { return mFrom.z == root.mFrom.z; } /** Gets whether this cell is at the front of the given root cell. @param root The octree root node to test against. @return true if so. */ inline bool isBorderFront(const OctreeNode &root) const { return mTo.z == root.mTo.z; } /** Gets the center of the corners 0, 1, 4, 5. @return The center. */ inline const Vector3 getCenterBack(void) const { return Vector3(mFrom.x + (mTo.x - mFrom.x) / (Real)2.0, mFrom.y + (mTo.y - mFrom.y) / (Real)2.0, mFrom.z); } /** Gets the center of the corners 2, 3, 6, 7. @return The center. */ inline const Vector3 getCenterFront(void) const { return Vector3(mFrom.x + (mTo.x - mFrom.x) / (Real)2.0, mFrom.y + (mTo.y - mFrom.y) / (Real)2.0, mTo.z); } /** Gets the center of the corners 0, 3, 4, 6. @return The center. */ inline const Vector3 getCenterLeft(void) const { return Vector3(mFrom.x, mFrom.y + (mTo.y - mFrom.y) / (Real)2.0, mFrom.z + (mTo.z - mFrom.z) / (Real)2.0); } /** Gets the center of the corners 1, 2, 5, 6. @return The center. */ inline const Vector3 getCenterRight(void) const { return Vector3(mTo.x, mFrom.y + (mTo.y - mFrom.y) / (Real)2.0, mFrom.z + (mTo.z - mFrom.z) / (Real)2.0); } /** Gets the center of the corners 4, 5, 6, 7. @return The center. */ inline const Vector3 getCenterTop(void) const { return Vector3(mFrom.x + (mTo.x - mFrom.x) / (Real)2.0, mTo.y, mFrom.z + (mTo.z - mFrom.z) / (Real)2.0); } /** Gets the center of the corners 0, 1, 2, 3. @return The center. */ inline const Vector3 getCenterBottom(void) const { return Vector3(mFrom.x + (mTo.x - mFrom.x) / (Real)2.0, mFrom.y, mFrom.z + (mTo.z - mFrom.z) / (Real)2.0); } /** Gets the center of the corners 4, 5. @return The center. */ inline const Vector3 getCenterBackTop(void) const { return Vector3(mFrom.x + (mTo.x - mFrom.x) / (Real)2.0, mTo.y, mFrom.z); } /** Gets the center of the corners 0, 1. @return The center. */ inline const Vector3 getCenterBackBottom(void) const { return Vector3(mFrom.x + (mTo.x - mFrom.x) / (Real)2.0, mFrom.y, mFrom.z); } /** Gets the center of the corners 6, 7. @return The center. */ inline const Vector3 getCenterFrontTop(void) const { return Vector3(mFrom.x + (mTo.x - mFrom.x) / (Real)2.0, mTo.y, mTo.z); } /** Gets the center of the corners 2, 3. @return The center. */ inline const Vector3 getCenterFrontBottom(void) const { return Vector3(mFrom.x + (mTo.x - mFrom.x) / (Real)2.0, mFrom.y, mTo.z); } /** Gets the center of the corners 4, 7. @return The center. */ inline const Vector3 getCenterLeftTop(void) const { return Vector3(mFrom.x, mTo.y, mFrom.z + (mTo.z - mFrom.z) / (Real)2.0); } /** Gets the center of the corners 0, 3. @return The center. */ inline const Vector3 getCenterLeftBottom(void) const { return Vector3(mFrom.x, mFrom.y, mFrom.z + (mTo.z - mFrom.z) / (Real)2.0); } /** Gets the center of the corners 5, 6. @return The center. */ inline const Vector3 getCenterRightTop(void) const { return Vector3(mTo.x, mTo.y, mFrom.z + (mTo.z - mFrom.z) / (Real)2.0); } /** Gets the center of the corners 1, 2. @return The center. */ inline const Vector3 getCenterRightBottom(void) const { return Vector3(mTo.x, mFrom.y, mFrom.z + (mTo.z - mFrom.z) / (Real)2.0); } /** Gets the center of the corners 0, 4. @return The center. */ inline const Vector3 getCenterBackLeft(void) const { return Vector3(mFrom.x, mFrom.y + (mTo.y - mFrom.y) / (Real)2.0, mFrom.z); } /** Gets the center of the corners 3, 7. @return The center. */ inline const Vector3 getCenterFrontLeft(void) const { return Vector3(mFrom.x, mFrom.y + (mTo.y - mFrom.y) / (Real)2.0, mTo.z); } /** Gets the center of the corners 1, 5. @return The center. */ inline const Vector3 getCenterBackRight(void) const { return Vector3(mTo.x, mFrom.y + (mTo.y - mFrom.y) / (Real)2.0, mFrom.z); } /** Gets the center of the corners 2, 6. @return The center. */ inline const Vector3 getCenterFrontRight(void) const { return Vector3(mTo.x, mFrom.y + (mTo.y - mFrom.y) / (Real)2.0, mTo.z); } /** Gets the coordinate of corner 1. @return The corner. */ inline const Vector3 getCorner1(void) const { return Vector3(mTo.x, mFrom.y, mFrom.z); } /** Gets the coordinate of corner 2. @return The corner. */ inline const Vector3 getCorner2(void) const { return Vector3(mTo.x, mFrom.y, mTo.z); } /** Gets the coordinate of corner 3. @return The corner. */ inline const Vector3 getCorner3(void) const { return Vector3(mFrom.x, mFrom.y, mTo.z); } /** Gets the coordinate of corner 4. @return The corner. */ inline const Vector3 getCorner4(void) const { return Vector3(mFrom.x, mTo.y, mFrom.z); } /** Gets the coordinate of corner 5. @return The corner. */ inline const Vector3 getCorner5(void) const { return Vector3(mTo.x, mTo.y, mFrom.z); } /** Gets the coordinate of corner 7. @return The corner. */ inline const Vector3 getCorner7(void) const { return Vector3(mFrom.x, mTo.y, mTo.z); } /** Raw setter for the center value. @param value The density value. */ inline void setCenterValue(Vector4 value) { mCenterValue = value; } /** Gets the center value. @return The center value, one Vector4 consisting of gradient (x, y, z) and density (w). */ inline const Vector4 getCenterValue(void) const { return mCenterValue; } /** Gets whether the isosurface is somewhat near to this node. @return true if somewhat near. */ inline bool isIsoSurfaceNear(void) const { if (mCenterValue.w == (Real)0.0) { return true; } return Math::Abs(mCenterValue.w) < (mFrom - mTo).length() * NEAR_FACTOR; } }; /** @} */ /** @} */ } } #endif