diff --git a/library/PolyVoxCore/include/Raycast.h b/library/PolyVoxCore/include/Raycast.h index 09f74692..9f4e9764 100644 --- a/library/PolyVoxCore/include/Raycast.h +++ b/library/PolyVoxCore/include/Raycast.h @@ -26,26 +26,78 @@ freely, subject to the following restrictions: namespace PolyVox { + /// Stores the result of a raycast operation. + //////////////////////////////////////////////////////////////////////////////// + /// A instance of this structure is passed to a Raycast object, and is filled in + /// as the ray traverses the volume. The 'foundIntersection' field indicates whether + /// the ray hit any solid voxels, and if so the 'intersectionVoxel' field indicates + ///the voxel's position + //////////////////////////////////////////////////////////////////////////////// struct RaycastResult { + ///Indicates whether an intersection was found bool foundIntersection; + ///If an intersection was found then this field holds the intersecting voxel, otherwise it is undefined. Vector3DInt16 intersectionVoxel; }; + /// The Raycast class can be used to find the fist filled voxel along a given path. + //////////////////////////////////////////////////////////////////////////////// + /// The principle behind raycasting is to fire a 'ray' through the volume and determine + /// what (if anything) that ray hits. This simple test can be used for the purpose of + /// picking, visibility checks, lighting calculations, or numerous other applications. + /// + /// A ray is a stright line in space define by a start point and a direction vector. + /// The length of the direction vector represents the length of the ray. When you call a + /// Raycast object's execute() method it will iterate over each voxel which lies on the ray, + /// starting from the defined start point. It will examine each voxel and terminate + /// either when it encounters a solid voxel or when it reaches the end of the ray. If a + /// solid voxel is encountered then its position is stored in the intersectionVoxel field + /// of the RaycastResult structure and the intersectionFound flag is set to true, otherwise + /// the intersectionFound flag is set to false. + /// + /// The following code snippet shows how the class is used: + /// \code + /// Vector3DFloat start(rayOrigin.x(), rayOrigin.y(), rayOrigin.z()); + /// Vector3DFloat direction(rayDir.x(), rayDir.y(), rayDir.z()); + /// direction.normalise(); + /// direction *= 1000.0f; //Casts ray of length 1000 + /// + /// RaycastResult raycastResult; + /// Raycast raycast(m_pPolyVoxVolume, start, direction, raycastResult); + /// raycast.execute(); + /// + /// if(raycastResult.foundIntersection) + /// { + /// //... + /// } + /// \endcode + /// + /// Some further notes, the Raycast uses full 26-connectivity, which basically means it + /// will examine every voxel the ray touches, even if it just passes through the corner. + /// Also, it peforms a simple binary test against a voxel's threshold, rather than making + /// use of it's density. Therefore it will work best in conjunction with one of the 'cubic' + /// surace extractors. It's behaviour with the Marching Cubes surface extractor has not + /// been tested yet. + //////////////////////////////////////////////////////////////////////////////// template class Raycast { public: + ///Constructor Raycast(Volume* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, RaycastResult& result); + ///Sets the start position for the ray. void setStart(const Vector3DFloat& v3dStart); + ///Set the direction for the ray. void setDirection(const Vector3DFloat& v3dDirection); + ///Performs the raycast. void execute(); + private: RaycastResult& m_result; - private: void doRaycast(float x1, float y1, float z1, float x2, float y2, float z2); Volume* m_volData; diff --git a/library/PolyVoxCore/include/Raycast.inl b/library/PolyVoxCore/include/Raycast.inl index 8817b330..37b37397 100644 --- a/library/PolyVoxCore/include/Raycast.inl +++ b/library/PolyVoxCore/include/Raycast.inl @@ -22,6 +22,14 @@ freely, subject to the following restrictions: *******************************************************************************/ namespace PolyVox { + //////////////////////////////////////////////////////////////////////////////// + /// Builds a Raycast object. + /// \param volData A pointer to the volume through which the ray will be cast. + /// \param v3dStart The starting position of the ray. + /// \param v3dDirection The direction of the ray. The length of this vector also + /// represents the length of the ray. + /// \param result An instance of RaycastResult in which the result will be stored. + //////////////////////////////////////////////////////////////////////////////// template Raycast::Raycast(Volume* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirection, RaycastResult& result) :m_volData(volData) @@ -32,18 +40,28 @@ namespace PolyVox { } + //////////////////////////////////////////////////////////////////////////////// + /// \param v3dStart The starting position of the ray. + //////////////////////////////////////////////////////////////////////////////// template void Raycast::setStart(const Vector3DFloat& v3dStart) { m_v3dStart = v3dStart; } + //////////////////////////////////////////////////////////////////////////////// + /// \param v3dDirection The direction of the ray. The length of this vector also + /// represents the length of the ray. + //////////////////////////////////////////////////////////////////////////////// template void Raycast::setDirection(const Vector3DFloat& v3dDirection) { m_v3dDirection = v3dDirection; } + //////////////////////////////////////////////////////////////////////////////// + /// The result is stored in the RaycastResult instance which was passed to the constructor. + //////////////////////////////////////////////////////////////////////////////// template void Raycast::execute(void) {