From 9fa6460f22be5482239d0b903af985a519f77166 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Wed, 1 Jun 2011 19:28:24 +0200 Subject: Initial commit. --- noiseutils/noiseutils.h | 2540 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2540 insertions(+) create mode 100644 noiseutils/noiseutils.h (limited to 'noiseutils/noiseutils.h') diff --git a/noiseutils/noiseutils.h b/noiseutils/noiseutils.h new file mode 100644 index 0000000..d54f61d --- /dev/null +++ b/noiseutils/noiseutils.h @@ -0,0 +1,2540 @@ +// noiseutils.h +// +// Copyright (C) 2003-2005 Jason Bevins +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or (at +// your option) any later version. +// +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License (COPYING.txt) for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// The developer's email is jlbezigvins@gmzigail.com (for great email, take +// off every 'zig'.) +// + +#ifndef NOISEUTILS_H +#define NOISEUTILS_H + +#include +#include +#include + +#include + +using namespace noise; + +namespace noise +{ + + namespace utils + { + + /// @mainpage noiseutils + /// + /// @section intro Introduction + /// + /// This library contains useful classes for creating and rendering + /// two-dimensional noise maps containing coherent noise that was + /// generated from the libnoise library. These classes are used to create + /// procedural textures and terrain height maps. + /// + /// noiseutils is known to compile under Windows 2000 Service Pack 4 + /// (using Microsoft Visual C++ 5.0) and under Gentoo Linux 10.0 (using + /// gcc 3.3.4). It should be portable across all platforms that can + /// compile libnoise. + /// + /// @section classes Classes + /// + /// This library contains the following classes: + /// - A noise map class: This class implements a two-dimensional + /// array that stores floating-point values. It's designed to store + /// coherent-noise values generated by a noise module. + /// - Several noise-map builder classes: Each of these classes + /// fills a noise map with coherent-noise values generated by a noise + /// module. While filling a noise map, it iterates the coordinates of + /// the input value along the surface of a specific mathematical object. + /// Each of these classes implements a different mathematical object, + /// such as a plane, a cylinder, or a sphere. + /// - An image class: This class implements a two-dimensional array + /// that stores color values. + /// - Several image-renderer classes: these classes render images + /// given the contents of a noise map. Each of these classes renders an + /// image in a different way. + /// + /// @section contact Contact + /// + /// Contact jas for questions about noiseutils. The spam-resistant email + /// address is jlbezigvins@gmzigail.com (For great email, take off every + /// zig.) + + /// The maximum width of a raster. + const int RASTER_MAX_WIDTH = 32767; + + /// The maximum height of a raster. + const int RASTER_MAX_HEIGHT = 32767; + + #ifndef DOXYGEN_SHOULD_SKIP_THIS + // The raster's stride length must be a multiple of this constant. + const int RASTER_STRIDE_BOUNDARY = 4; + #endif + + /// A pointer to a callback function used by the NoiseMapBuilder class. + /// + /// The NoiseMapBuilder::Build() method calls this callback function each + /// time it fills a row of the noise map with coherent-noise values. + /// + /// This callback function has a single integer parameter that contains + /// a count of the rows that have been completed. It returns void. Pass + /// a function with this signature to the NoiseMapBuilder::SetCallback() + /// method. + typedef void(*NoiseMapCallback) (int row); + + /// Number of meters per point in a Terragen terrain (TER) file. + const double DEFAULT_METERS_PER_POINT = 30.0; + + /// Same as the DEFAULT_METERS_PER_POINT constant, but for us + /// canuckleheads. + const double DEFAULT_METRES_PER_POINT = DEFAULT_METERS_PER_POINT; + + /// Defines a color. + /// + /// A color object contains four 8-bit channels: red, green, blue, and an + /// alpha (transparency) channel. Channel values range from 0 to 255. + /// + /// The alpha channel defines the transparency of the color. If the alpha + /// channel has a value of 0, the color is completely transparent. If the + /// alpha channel has a value of 255, the color is completely opaque. + class Color + { + + public: + + /// Constructor. + Color () + { + } + + /// Constructor. + /// + /// @param r Value of the red channel. + /// @param g Value of the green channel. + /// @param b Value of the blue channel. + /// @param a Value of the alpha (transparency) channel. + Color (noise::uint8 r, noise::uint8 g, noise::uint8 b, + noise::uint8 a): + red (r), green (g), blue (b), alpha (a) + { + } + + /// Value of the red channel. + noise::uint8 red; + + /// Value of the green channel. + noise::uint8 green; + + /// Value of the blue channel. + noise::uint8 blue; + + /// Value of the alpha (transparency) channel. + noise::uint8 alpha; + + }; + + /// Defines a point used to build a color gradient. + /// + /// A color gradient is a list of gradually-changing colors. A color + /// gradient is defined by a list of gradient points. Each + /// gradient point has a position and a color. In a color gradient, the + /// colors between two adjacent gradient points are linearly interpolated. + /// + /// The ColorGradient class defines a color gradient by a list of these + /// objects. + struct GradientPoint + { + + /// The position of this gradient point. + double pos; + + /// The color of this gradient point. + Color color; + + }; + + /// Defines a color gradient. + /// + /// A color gradient is a list of gradually-changing colors. A color + /// gradient is defined by a list of gradient points. Each + /// gradient point has a position and a color. In a color gradient, the + /// colors between two adjacent gradient points are linearly interpolated. + /// + /// To add a gradient point to the color gradient, pass its position and + /// color to the AddGradientPoint() method. + /// + /// To retrieve a color from a specific position in the color gradient, + /// pass that position to the GetColor() method. + /// + /// This class is a useful tool for coloring height maps based on + /// elevation. + /// + /// Gradient example + /// + /// Suppose a gradient object contains the following gradient points: + /// - -1.0 maps to black. + /// - 0.0 maps to white. + /// - 1.0 maps to red. + /// + /// If an application passes -0.5 to the GetColor() method, this method + /// will return a gray color that is halfway between black and white. + /// + /// If an application passes 0.25 to the GetColor() method, this method + /// will return a very light pink color that is one quarter of the way + /// between white and red. + class GradientColor + { + + public: + + /// Constructor. + GradientColor (); + + /// Destructor. + ~GradientColor (); + + /// Adds a gradient point to this gradient object. + /// + /// @param gradientPos The position of this gradient point. + /// @param gradientColor The color of this gradient point. + /// + /// @pre No two gradient points have the same position. + /// + /// @throw noise::ExceptionInvalidParam See the precondition. + /// + /// It does not matter which order these gradient points are added. + void AddGradientPoint (double gradientPos, + const Color& gradientColor); + + /// Deletes all the gradient points from this gradient object. + /// + /// @post All gradient points from this gradient object are deleted. + void Clear (); + + /// Returns the color at the specified position in the color gradient. + /// + /// @param gradientPos The specified position. + /// + /// @returns The color at that position. + const Color& GetColor (double gradientPos) const; + + /// Returns a pointer to the array of gradient points in this object. + /// + /// @returns A pointer to the array of gradient points. + /// + /// Before calling this method, call GetGradientPointCount() to + /// determine the number of gradient points in this array. + /// + /// It is recommended that an application does not store this pointer + /// for later use since the pointer to the array may change if the + /// application calls another method of this object. + const GradientPoint* GetGradientPointArray () const + { + return m_pGradientPoints; + } + + /// Returns the number of gradient points stored in this object. + /// + /// @returns The number of gradient points stored in this object. + int GetGradientPointCount () const + { + return m_gradientPointCount; + } + + private: + + /// Determines the array index in which to insert the gradient point + /// into the internal gradient-point array. + /// + /// @param gradientPos The position of this gradient point. + /// + /// @returns The array index in which to insert the gradient point. + /// + /// @pre No two gradient points have the same input value. + /// + /// @throw noise::ExceptionInvalidParam See the precondition. + /// + /// By inserting the gradient point at the returned array index, this + /// object ensures that the gradient-point array is sorted by input + /// value. The code that maps a value to a color requires a sorted + /// gradient-point array. + int FindInsertionPos (double gradientPos); + + /// Inserts the gradient point at the specified position in the + /// internal gradient-point array. + /// + /// @param insertionPos The zero-based array position in which to + /// insert the gradient point. + /// @param gradientPos The position of this gradient point. + /// @param gradientColor The color of this gradient point. + /// + /// To make room for this new gradient point, this method reallocates + /// the gradient-point array and shifts all gradient points occurring + /// after the insertion position up by one. + /// + /// Because this object requires that all gradient points in the array + /// must be sorted by the position, the new gradient point should be + /// inserted at the position in which the order is still preserved. + void InsertAtPos (int insertionPos, double gradientPos, + const Color& gradientColor); + + /// Number of gradient points. + int m_gradientPointCount; + + /// Array that stores the gradient points. + GradientPoint* m_pGradientPoints; + + /// A color object that is used by a gradient object to store a + /// temporary value. + mutable Color m_workingColor; + }; + + /// Implements a noise map, a 2-dimensional array of floating-point + /// values. + /// + /// A noise map is designed to store coherent-noise values generated by a + /// noise module, although it can store values from any source. A noise + /// map is often used as a terrain height map or a grayscale texture. + /// + /// The size (width and height) of the noise map can be specified during + /// object construction or at any other time. + /// + /// The GetValue() and SetValue() methods can be used to access individual + /// values stored in the noise map. + /// + /// This class manages its own memory. If you copy a noise map object + /// into another noise map object, the original contents of the noise map + /// object will be freed. + /// + /// If you specify a new size for the noise map and the new size is + /// smaller than the current size, the allocated memory will not be + /// reallocated. + /// Call ReclaimMem() to reclaim the wasted memory. + /// + /// Border Values + /// + /// All of the values outside of the noise map are assumed to have a + /// common value known as the border value. + /// + /// To set the border value, call the SetBorderValue() method. + /// + /// The GetValue() method returns the border value if the specified value + /// lies outside of the noise map. + /// + /// Internal Noise Map Structure + /// + /// Internally, the values are organized into horizontal rows called @a + /// slabs. Slabs are ordered from bottom to top. + /// + /// Each slab contains a contiguous row of values in memory. The values + /// in a slab are organized left to right. + /// + /// The offset between the starting points of any two adjacent slabs is + /// called the stride amount. The stride amount is measured by + /// the number of @a float values between these two starting points, not + /// by the number of bytes. For efficiency reasons, the stride is often a + /// multiple of the machine word size. + /// + /// The GetSlabPtr() and GetConstSlabPtr() methods allow you to retrieve + /// pointers to the slabs themselves. + class NoiseMap + { + + public: + + /// Constructor. + /// + /// Creates an empty noise map. + NoiseMap (); + + /// Constructor. + /// + /// @param width The width of the new noise map. + /// @param height The height of the new noise map. + /// + /// @pre The width and height values are positive. + /// @pre The width and height values do not exceed the maximum + /// possible width and height for the noise map. + /// + /// @throw noise::ExceptionInvalidParam See the preconditions. + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// + /// Creates a noise map with uninitialized values. + /// + /// It is considered an error if the specified dimensions are not + /// positive. + NoiseMap (int width, int height); + + /// Copy constructor. + /// + /// @throw noise::ExceptionOutOfMemory Out of memory. + NoiseMap (const NoiseMap& rhs); + + /// Destructor. + /// + /// Frees the allocated memory for the noise map. + ~NoiseMap (); + + /// Assignment operator. + /// + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// + /// @returns Reference to self. + /// + /// Creates a copy of the noise map. + NoiseMap& operator= (const NoiseMap& rhs); + + /// Clears the noise map to a specified value. + /// + /// @param value The value that all positions within the noise map are + /// cleared to. + void Clear (float value); + + /// Returns the value used for all positions outside of the noise map. + /// + /// @returns The value used for all positions outside of the noise + /// map. + /// + /// All positions outside of the noise map are assumed to have a + /// common value known as the border value. + float GetBorderValue () const + { + return m_borderValue; + } + + /// Returns a const pointer to a slab. + /// + /// @returns A const pointer to a slab at the position (0, 0), or + /// @a NULL if the noise map is empty. + const float* GetConstSlabPtr () const + { + return m_pNoiseMap; + } + + /// Returns a const pointer to a slab at the specified row. + /// + /// @param row The row, or @a y coordinate. + /// + /// @returns A const pointer to a slab at the position ( 0, @a row ), + /// or @a NULL if the noise map is empty. + /// + /// @pre The coordinates must exist within the bounds of the noise + /// map. + /// + /// This method does not perform bounds checking so be careful when + /// calling it. + const float* GetConstSlabPtr (int row) const + { + return GetConstSlabPtr (0, row); + } + + /// Returns a const pointer to a slab at the specified position. + /// + /// @param x The x coordinate of the position. + /// @param y The y coordinate of the position. + /// + /// @returns A const pointer to a slab at the position ( @a x, @a y ), + /// or @a NULL if the noise map is empty. + /// + /// @pre The coordinates must exist within the bounds of the noise + /// map. + /// + /// This method does not perform bounds checking so be careful when + /// calling it. + const float* GetConstSlabPtr (int x, int y) const + { + return m_pNoiseMap + (size_t)x + (size_t)m_stride * (size_t)y; + } + + /// Returns the height of the noise map. + /// + /// @returns The height of the noise map. + int GetHeight () const + { + return m_height; + } + + /// Returns the amount of memory allocated for this noise map. + /// + /// @returns The amount of memory allocated for this noise map. + /// + /// This method returns the number of @a float values allocated. + size_t GetMemUsed () const + { + return m_memUsed; + } + + /// Returns a pointer to a slab. + /// + /// @returns A pointer to a slab at the position (0, 0), or @a NULL if + /// the noise map is empty. + float* GetSlabPtr () + { + return m_pNoiseMap; + } + + /// Returns a pointer to a slab at the specified row. + /// + /// @param row The row, or @a y coordinate. + /// + /// @returns A pointer to a slab at the position ( 0, @a row ), or + /// @a NULL if the noise map is empty. + /// + /// @pre The coordinates must exist within the bounds of the noise + /// map. + /// + /// This method does not perform bounds checking so be careful when + /// calling it. + float* GetSlabPtr (int row) + { + return GetSlabPtr (0, row); + } + + /// Returns a pointer to a slab at the specified position. + /// + /// @param x The x coordinate of the position. + /// @param y The y coordinate of the position. + /// + /// @returns A pointer to a slab at the position ( @a x, @a y ) or + /// @a NULL if the noise map is empty. + /// + /// @pre The coordinates must exist within the bounds of the noise + /// map. + /// + /// This method does not perform bounds checking so be careful when + /// calling it. + float* GetSlabPtr (int x, int y) + { + return m_pNoiseMap + (size_t)x + (size_t)m_stride * (size_t)y; + } + + /// Returns the stride amount of the noise map. + /// + /// @returns The stride amount of the noise map. + /// + /// - The stride amount is the offset between the starting + /// points of any two adjacent slabs in a noise map. + /// - The stride amount is measured by the number of @a float values + /// between these two points, not by the number of bytes. + int GetStride () const + { + return m_stride; + } + + /// Returns a value from the specified position in the noise map. + /// + /// @param x The x coordinate of the position. + /// @param y The y coordinate of the position. + /// + /// @returns The value at that position. + /// + /// This method returns the border value if the coordinates exist + /// outside of the noise map. + float GetValue (int x, int y) const; + + /// Returns the width of the noise map. + /// + /// @returns The width of the noise map. + int GetWidth () const + { + return m_width; + } + + /// Reallocates the noise map to recover wasted memory. + /// + /// @throw noise::ExceptionOutOfMemory Out of memory. (Yes, this + /// method can return an out-of-memory exception because two noise + /// maps will temporarily exist in memory during this call.) + /// + /// The contents of the noise map is unaffected. + void ReclaimMem (); + + /// Sets the value to use for all positions outside of the noise map. + /// + /// @param borderValue The value to use for all positions outside of + /// the noise map. + /// + /// All positions outside of the noise map are assumed to have a + /// common value known as the border value. + void SetBorderValue (float borderValue) + { + m_borderValue = borderValue; + } + + /// Sets the new size for the noise map. + /// + /// @param width The new width for the noise map. + /// @param height The new height for the noise map. + /// + /// @pre The width and height values are positive. + /// @pre The width and height values do not exceed the maximum + /// possible width and height for the noise map. + /// + /// @throw noise::ExceptionInvalidParam See the preconditions. + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// + /// On exit, the contents of the noise map are undefined. + /// + /// If the @a OUT_OF_MEMORY exception occurs, this noise map object + /// becomes empty. + /// + /// If the @a INVALID_PARAM exception occurs, the noise map is + /// unmodified. + void SetSize (int width, int height); + + /// Sets a value at a specified position in the noise map. + /// + /// @param x The x coordinate of the position. + /// @param y The y coordinate of the position. + /// @param value The value to set at the given position. + /// + /// This method does nothing if the noise map object is empty or the + /// position is outside the bounds of the noise map. + void SetValue (int x, int y, float value); + + /// Takes ownership of the buffer within the source noise map. + /// + /// @param source The source noise map. + /// + /// On exit, the source noise map object becomes empty. + /// + /// This method only moves the buffer pointer so this method is very + /// quick. + void TakeOwnership (NoiseMap& source); + + private: + + /// Returns the minimum amount of memory required to store a noise map + /// of the specified size. + /// + /// @param width The width of the noise map. + /// @param height The height of the noise map. + /// + /// @returns The minimum amount of memory required to store the noise + /// map. + /// + /// The returned value is measured by the number of @a float values + /// required to store the noise map, not by the number of bytes. + size_t CalcMinMemUsage (int width, int height) const + { + return CalcStride ((size_t)width) * (size_t)height; + } + + /// Calculates the stride amount for a noise map. + /// + /// @param width The width of the noise map. + /// + /// @returns The stride amount. + /// + /// - The stride amount is the offset between the starting + /// points of any two adjacent slabs in a noise map. + /// - The stride amount is measured by the number of @a float values + /// between these two points, not by the number of bytes. + size_t CalcStride (int width) const + { + return (size_t)(((width + RASTER_STRIDE_BOUNDARY - 1) + / RASTER_STRIDE_BOUNDARY) * RASTER_STRIDE_BOUNDARY); + } + + /// Copies the contents of the buffer in the source noise map into + /// this noise map. + /// + /// @param source The source noise map. + /// + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// + /// This method reallocates the buffer in this noise map object if + /// necessary. + /// + /// @warning This method calls the standard library function + /// @a memcpy, which probably violates the DMCA because it can be used + //. to make a bitwise copy of anything, like, say, a DVD. Don't call + /// this method if you live in the USA. + void CopyNoiseMap (const NoiseMap& source); + + /// Resets the noise map object. + /// + /// This method is similar to the InitObj() method, except this method + /// deletes the buffer in this noise map. + void DeleteNoiseMapAndReset (); + + /// Initializes the noise map object. + /// + /// @pre Must be called during object construction. + /// @pre The noise map buffer must not exist. + void InitObj (); + + /// Value used for all positions outside of the noise map. + float m_borderValue; + + /// The current height of the noise map. + int m_height; + + /// The amount of memory allocated for this noise map. + /// + /// This value is equal to the number of @a float values allocated for + /// the noise map, not the number of bytes. + size_t m_memUsed; + + /// A pointer to the noise map buffer. + float* m_pNoiseMap; + + /// The stride amount of the noise map. + int m_stride; + + /// The current width of the noise map. + int m_width; + + }; + + /// Implements an image, a 2-dimensional array of color values. + /// + /// An image can be used to store a color texture. + /// + /// These color values are of type Color. + /// + /// The size (width and height) of the image can be specified during + /// object construction or at any other time. + /// + /// The GetValue() and SetValue() methods can be used to access individual + /// color values stored in the image. + /// + /// This class manages its own memory. If you copy an image object into + /// another image object, the original contents of the image object will + /// be freed. + /// + /// If you specify a new size for the image and the new size is smaller + /// than the current size, the allocated memory will not be reallocated. + /// Call ReclaimMem() to reclaim the wasted memory. + /// + /// Border Values + /// + /// All of the color values outside of the image are assumed to have a + /// common color value known as the border value. + /// + /// To set the border value, call the SetBorderValue() method. + /// + /// The GetValue() method returns the border value if the specified + /// position lies outside of the image. + /// + /// Internal Image Structure + /// + /// Internally, the color values are organized into horizontal rows called + /// @a slabs. Slabs are ordered from bottom to top. + /// + /// Each slab contains a contiguous row of color values in memory. The + /// color values in a slab are organized left to right. These values are + /// of type Color. + /// + /// The offset between the starting points of any two adjacent slabs is + /// called the stride amount. The stride amount is measured by the + /// number of Color objects between these two starting points, not by the + /// number of bytes. For efficiency reasons, the stride is often a + /// multiple of the machine word size. + /// + /// The GetSlabPtr() methods allow you to retrieve pointers to the slabs + /// themselves. + class Image + { + + public: + + /// Constructor. + /// + /// Creates an empty image. + Image (); + + /// Constructor. + /// + /// @param width The width of the new image. + /// @param height The height of the new image. + /// + /// @pre The width and height values are positive. + /// @pre The width and height values do not exceed the maximum + /// possible width and height for the image. + /// + /// @throw noise::ExceptionInvalidParam See the preconditions. + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// + /// Creates an image with uninitialized color values. + /// + /// It is considered an error if the specified dimensions are not + /// positive. + Image (int width, int height); + + /// Copy constructor. + /// + /// @throw noise::ExceptionOutOfMemory Out of memory. + Image (const Image& rhs); + + /// Destructor. + /// + /// Frees the allocated memory for the image. + ~Image (); + + /// Assignment operator. + /// + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// + /// @returns Reference to self. + /// + /// Creates a copy of the image. + Image& operator= (const Image& rhs); + + /// Clears the image to a specified color value. + /// + /// @param value The color value that all positions within the image + /// are cleared to. + void Clear (const Color& value); + + /// Returns the color value used for all positions outside of the + /// image. + /// + /// @returns The color value used for all positions outside of the + /// image. + /// + /// All positions outside of the image are assumed to have a common + /// color value known as the border value. + Color GetBorderValue () const + { + return m_borderValue; + } + + /// Returns a const pointer to a slab. + /// + /// @returns A const pointer to a slab at the position (0, 0), or + /// @a NULL if the image is empty. + const Color* GetConstSlabPtr () const + { + return m_pImage; + } + + /// Returns a const pointer to a slab at the specified row. + /// + /// @param row The row, or @a y coordinate. + /// + /// @returns A const pointer to a slab at the position ( 0, @a row ), + /// or @a NULL if the image is empty. + /// + /// @pre The coordinates must exist within the bounds of the image. + /// + /// This method does not perform bounds checking so be careful when + /// calling it. + const Color* GetConstSlabPtr (int row) const + { + return GetConstSlabPtr (0, row); + } + + /// Returns a const pointer to a slab at the specified position. + /// + /// @param x The x coordinate of the position. + /// @param y The y coordinate of the position. + /// + /// @returns A const pointer to a slab at the position ( @a x, @a y ), + /// or @a NULL if the image is empty. + /// + /// @pre The coordinates must exist within the bounds of the image. + /// + /// This method does not perform bounds checking so be careful when + /// calling it. + const Color* GetConstSlabPtr (int x, int y) const + { + return m_pImage + (size_t)x + (size_t)m_stride * (size_t)y; + } + + /// Returns the height of the image. + /// + /// @returns The height of the image. + int GetHeight () const + { + return m_height; + } + + /// Returns the amount of memory allocated for this image. + /// + /// @returns The amount of memory allocated for this image. + /// + /// This method returns the number of Color objects allocated. + size_t GetMemUsed () const + { + return m_memUsed; + } + + /// Returns a pointer to a slab. + /// + /// @returns A pointer to a slab at the position (0, 0), or @a NULL if + /// the image is empty. + Color* GetSlabPtr () + { + return m_pImage; + } + + /// Returns a pointer to a slab at the specified row. + /// + /// @param row The row, or @a y coordinate. + /// + /// @returns A pointer to a slab at the position ( 0, @a row ), or + /// @a NULL if the image is empty. + /// + /// @pre The coordinates must exist within the bounds of the image. + /// + /// This method does not perform bounds checking so be careful when + /// calling it. + Color* GetSlabPtr (int row) + { + return GetSlabPtr (0, row); + } + + /// Returns a pointer to a slab at the specified position. + /// + /// @param x The x coordinate of the position. + /// @param y The y coordinate of the position. + /// + /// @returns A pointer to a slab at the position ( @a x, @a y ), or + /// @a NULL if the image is empty. + /// + /// @pre The coordinates must exist within the bounds of the image. + /// + /// This method does not perform bounds checking so be careful when + /// calling it. + Color* GetSlabPtr (int x, int y) + { + return m_pImage + (size_t)x + (size_t)m_stride * (size_t)y; + } + + /// Returns the stride amount of the image. + /// + /// @returns The stride amount of the image. + /// + /// - The stride amount is the offset between the starting + /// points of any two adjacent slabs in an image. + /// - The stride amount is measured by the number of Color objects + /// between these two points, not by the number of bytes. + int GetStride () const + { + return m_stride; + } + + /// Returns a color value from the specified position in the image. + /// + /// @param x The x coordinate of the position. + /// @param y The y coordinate of the position. + /// + /// @returns The color value at that position. + /// + /// This method returns the border value if the coordinates exist + /// outside of the image. + Color GetValue (int x, int y) const; + + /// Returns the width of the image. + /// + /// @returns The width of the image. + int GetWidth () const + { + return m_width; + } + + /// Reallocates the image to recover wasted memory. + /// + /// @throw noise::ExceptionOutOfMemory Out of memory. (Yes, this + /// method can return an out-of-memory exception because two images + /// will exist temporarily in memory during this call.) + /// + /// The contents of the image is unaffected. + void ReclaimMem (); + + /// Sets the color value to use for all positions outside of the + /// image. + /// + /// @param borderValue The color value to use for all positions + /// outside of the image. + /// + /// All positions outside of the image are assumed to have a common + /// color value known as the border value. + void SetBorderValue (const Color& borderValue) + { + m_borderValue = borderValue; + } + + /// Sets the new size for the image. + /// + /// @param width The new width for the image. + /// @param height The new height for the image. + /// + /// @pre The width and height values are positive. + /// @pre The width and height values do not exceed the maximum + /// possible width and height for the image. + /// + /// @throw noise::ExceptionInvalidParam See the preconditions. + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// + /// On exit, the contents of the image are undefined. + /// + /// If the @a OUT_OF_MEMORY exception occurs, this image becomes + /// empty. + /// + /// If the @a INVALID_PARAM exception occurs, the image is unmodified. + void SetSize (int width, int height); + + /// Sets a color value at a specified position in the image. + /// + /// @param x The x coordinate of the position. + /// @param y The y coordinate of the position. + /// @param value The color value to set at the given position. + /// + /// This method does nothing if the image is empty or the position is + /// outside the bounds of the image. + void SetValue (int x, int y, const Color& value); + + /// Takes ownership of the buffer within the source image. + /// + /// @param source The source image. + /// + /// On exit, the source image object becomes empty. + /// + /// This method only moves the buffer pointer so this method is very + /// quick. + void TakeOwnership (Image& source); + + private: + + /// Returns the minimum amount of memory required to store an image of + /// the specified size. + /// + /// @param width The width of the image. + /// @param height The height of the image. + /// + /// @returns The minimum amount of memory required to store the image. + /// + /// The returned color value is measured by the number of Color + /// objects required to store the image, not by the number of bytes. + size_t CalcMinMemUsage (int width, int height) const + { + return CalcStride ((size_t)width) * (size_t)height; + } + + /// Calculates the stride amount for an image. + /// + /// @param width The width of the image. + /// + /// @returns The stride amount. + /// + /// - The stride amount is the offset between the starting + /// points of any two adjacent slabs in an image. + /// - The stride amount is measured by the number of Color objects + /// between these two points, not by the number of bytes. + size_t CalcStride (int width) const + { + return (size_t)(((width + RASTER_STRIDE_BOUNDARY - 1) + / RASTER_STRIDE_BOUNDARY) * RASTER_STRIDE_BOUNDARY); + } + + /// Copies the contents of the buffer in the source image into this + /// image. + /// + /// @param source The source image. + /// + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// + /// This method reallocates the buffer in this image object if + /// necessary. + /// + /// @warning This method calls the standard library function + /// @a memcpy, which probably violates the DMCA because it can be used + /// to make a bitwise copy of anything, like, say, a DVD. Don't call + /// this method if you live in the USA. + void CopyImage (const Image& source); + + /// Resets the image object. + /// + /// This method is similar to the InitObj() method, except this method + /// deletes the memory allocated to the image. + void DeleteImageAndReset (); + + /// Initializes the image object. + /// + /// @pre Must be called during object construction. + /// @pre The image buffer must not exist. + void InitObj (); + + /// The Color value used for all positions outside of the image. + Color m_borderValue; + + /// The current height of the image. + int m_height; + + /// The amount of memory allocated for the image. + /// + /// This value is equal to the number of Color objects allocated for + /// the image, not the number of bytes. + size_t m_memUsed; + + /// A pointer to the image buffer. + Color* m_pImage; + + /// The stride amount of the image. + int m_stride; + + /// The current width of the image. + int m_width; + + }; + + /// Windows bitmap image writer class. + /// + /// This class creates a file in Windows bitmap (*.bmp) format given the + /// contents of an image object. + /// + /// Writing the image + /// + /// To write the image to a file, perform the following steps: + /// - Pass the filename to the SetDestFilename() method. + /// - Pass an Image object to the SetSourceImage() method. + /// - Call the WriteDestFile() method. + /// + /// The SetDestFilename() and SetSourceImage() methods must be called + /// before calling the WriteDestFile() method. + class WriterBMP + { + + public: + + /// Constructor. + WriterBMP (): + m_pSourceImage (NULL) + { + } + + /// Returns the name of the file to write. + /// + /// @returns The name of the file to write. + std::string GetDestFilename () const + { + return m_destFilename; + } + + /// Sets the name of the file to write. + /// + /// @param filename The name of the file to write. + /// + /// Call this method before calling the WriteDestFile() method. + void SetDestFilename (const std::string& filename) + { + m_destFilename = filename; + } + + /// Sets the image object that is written to the file. + /// + /// @param sourceImage The image object to write. + /// + /// This object only stores a pointer to an image object, so make sure + /// this object exists before calling the WriteDestFile() method. + void SetSourceImage (Image& sourceImage) + { + m_pSourceImage = &sourceImage; + } + + /// Writes the contents of the image object to the file. + /// + /// @pre SetDestFilename() has been previously called. + /// @pre SetSourceImage() has been previously called. + /// + /// @throw noise::ExceptionInvalidParam See the preconditions. + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// @throw noise::ExceptionUnknown An unknown exception occurred. + /// Possibly the file could not be written. + /// + /// This method encodes the contents of the image and writes it to a + /// file. Before calling this method, call the SetSourceImage() + /// method to specify the image, then call the SetDestFilename() + /// method to specify the name of the file to write. + void WriteDestFile (); + + protected: + + /// Calculates the width of one horizontal line in the file, in bytes. + /// + /// @param width The width of the image, in points. + /// + /// @returns The width of one horizontal line in the file. + /// + /// Windows bitmap files require that the width of one horizontal line + /// must be aligned to a 32-bit boundary. + int CalcWidthByteCount (int width) const; + + /// Name of the file to write. + std::string m_destFilename; + + /// A pointer to the image object that will be written to the file. + Image* m_pSourceImage; + + }; + + /// Terragen Terrain writer class. + /// + /// This class creates a file in Terrage Terrain (*.ter) format given the + /// contents of a noise map object. This class treats the values in the + /// noise map as elevations measured in meters. + /// + /// Terragen is a + /// terrain application that renders realistic landscapes. Terragen is + /// available for Windows and MacOS; unfortunately, Terragen does not have + /// UN*X versions. + /// + /// Writing the noise map + /// + /// To write the noise map, perform the following steps: + /// - Pass the filename to the SetDestFilename() method. + /// - Pass a NoiseMap object to the SetSourceNoiseMap() method. + /// - Call the WriteDestFile() method. + /// + /// The SetDestFilename() and SetSourceNoiseMap() methods must be called + /// before calling the WriteDestFile() method. + class WriterTER + { + + public: + + /// Constructor. + WriterTER (): + m_pSourceNoiseMap (NULL), + m_metersPerPoint (DEFAULT_METERS_PER_POINT) + { + } + + /// Returns the name of the file to write. + /// + /// @returns The name of the file to write. + std::string GetDestFilename () const + { + return m_destFilename; + } + + /// Returns the distance separating adjacent points in the noise map, + /// in meters. + /// + /// @returns The distance separating adjacent points in the noise map. + float GetMetersPerPoint () const + { + return m_metersPerPoint; + } + + /// Sets the name of the file to write. + /// + /// @param filename The name of the file to write. + /// + /// Call this method before calling the WriteDestFile() method. + void SetDestFilename (const std::string& filename) + { + m_destFilename = filename; + } + + /// Sets the distance separating adjacent points in the noise map, in + /// meters. + /// + /// @param metersPerPoint The distance separating adjacent points in + /// the noise map. + void SetMetersPerPoint (float metersPerPoint) + { + m_metersPerPoint = metersPerPoint; + } + + /// Sets the noise map object that is written to the file. + /// + /// @param sourceNoiseMap The noise map object to write. + /// + /// This object only stores a pointer to a noise map object, so make + /// sure this object exists before calling the WriteDestFile() method. + void SetSourceNoiseMap (NoiseMap& sourceNoiseMap) + { + m_pSourceNoiseMap = &sourceNoiseMap; + } + + /// Writes the contents of the noise map object to the file. + /// + /// @pre SetDestFilename() has been previously called. + /// @pre SetSourceNoiseMap() has been previously called. + /// + /// @throw noise::ExceptionInvalidParam See the preconditions. + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// @throw noise::ExceptionUnknown An unknown exception occurred. + /// Possibly the file could not be written. + /// + /// This method encodes the contents of the noise map and writes it to + /// a file. Before calling this method, call the SetSourceNoiseMap() + /// method to specify the noise map, then call the SetDestFilename() + /// method to specify the name of the file to write. + /// + /// This object assumes that the noise values represent elevations in + /// meters. + void WriteDestFile (); + + protected: + + /// Calculates the width of one horizontal line in the file, in bytes. + /// + /// @param width The width of the noise map, in points. + /// + /// @returns The width of one horizontal line in the file. + int CalcWidthByteCount (int width) const; + + /// Name of the file to write. + std::string m_destFilename; + + /// A pointer to the noise map that will be written to the file. + NoiseMap* m_pSourceNoiseMap; + + /// The distance separating adjacent points in the noise map, in + /// meters. + float m_metersPerPoint; + + }; + + /// Abstract base class for a noise-map builder + /// + /// A builder class builds a noise map by filling it with coherent-noise + /// values generated from the surface of a three-dimensional mathematical + /// object. Each builder class defines a specific three-dimensional + /// surface, such as a cylinder, sphere, or plane. + /// + /// A builder class describes these input values using a coordinate system + /// applicable for the mathematical object (e.g., a latitude/longitude + /// coordinate system for the spherical noise-map builder.) It then + /// "flattens" these coordinates onto a plane so that it can write the + /// coherent-noise values into a two-dimensional noise map. + /// + /// Building the Noise Map + /// + /// To build the noise map, perform the following steps: + /// - Pass the bounding coordinates to the SetBounds() method. + /// - Pass the noise map size, in points, to the SetDestSize() method. + /// - Pass a NoiseMap object to the SetDestNoiseMap() method. + /// - Pass a noise module (derived from noise::module::Module) to the + /// SetSourceModule() method. + /// - Call the Build() method. + /// + /// You may also pass a callback function to the SetCallback() method. + /// The Build() method calls this callback function each time it fills a + /// row of the noise map with coherent-noise values. This callback + /// function has a single integer parameter that contains a count of the + /// rows that have been completed. It returns void. + /// + /// Note that SetBounds() is not defined in the abstract base class; it is + /// only defined in the derived classes. This is because each model uses + /// a different coordinate system. + class NoiseMapBuilder + { + + public: + + /// Constructor. + NoiseMapBuilder (); + + /// Builds the noise map. + /// + /// @pre SetBounds() was previously called. + /// @pre SetDestNoiseMap() was previously called. + /// @pre SetSourceModule() was previously called. + /// @pre The width and height values specified by SetDestSize() are + /// positive. + /// @pre The width and height values specified by SetDestSize() do not + /// exceed the maximum possible width and height for the noise map. + /// + /// @post The original contents of the destination noise map is + /// destroyed. + /// + /// @throw noise::ExceptionInvalidParam See the preconditions. + /// @throw noise::ExceptionOutOfMemory Out of memory. + /// + /// If this method is successful, the destination noise map contains + /// the coherent-noise values from the noise module specified by + /// SetSourceModule(). + virtual void Build () = 0; + + /// Returns the height of the destination noise map. + /// + /// @returns The height of the destination noise map, in points. + /// + /// This object does not change the height in the destination noise + /// map object until the Build() method is called. + double GetDestHeight () const + { + return m_destHeight; + } + + /// Returns the width of the destination noise map. + /// + /// @returns The width of the destination noise map, in points. + /// + /// This object does not change the height in the destination noise + /// map object until the Build() method is called. + double GetDestWidth () const + { + return m_destWidth; + } + + /// Sets the callback function that Build() calls each time it fills a + /// row of the noise map with coherent-noise values. + /// + /// @param pCallback The callback function. + /// + /// This callback function has a single integer parameter that + /// contains a count of the rows that have been completed. It returns + /// void. Pass a function with this signature to the SetCallback() + /// method. + void SetCallback (NoiseMapCallback pCallback); + + /// Sets the destination noise map. + /// + /// @param destNoiseMap The destination noise map. + /// + /// The destination noise map will contain the coherent-noise values + /// from this noise map after a successful call to the Build() method. + /// + /// The destination noise map must exist throughout the lifetime of + /// this object unless another noise map replaces that noise map. + void SetDestNoiseMap (NoiseMap& destNoiseMap) + { + m_pDestNoiseMap = &destNoiseMap; + } + + /// Sets the source module. + /// + /// @param sourceModule The source module. + /// + /// This object fills in a noise map with the coherent-noise values + /// from this source module. + /// + /// The source module must exist throughout the lifetime of this + /// object unless another noise module replaces that noise module. + void SetSourceModule (const module::Module& sourceModule) + { + m_pSourceModule = &sourceModule; + } + + /// Sets the size of the destination noise map. + /// + /// @param destWidth The width of the destination noise map, in + /// points. + /// @param destHeight The height of the destination noise map, in + /// points. + /// + /// This method does not change the size of the destination noise map + /// until the Build() method is called. + void SetDestSize (int destWidth, int destHeight) + { + m_destWidth = destWidth ; + m_destHeight = destHeight; + } + + protected: + + /// The callback function that Build() calls each time it fills a row + /// of the noise map with coherent-noise values. + /// + /// This callback function has a single integer parameter that + /// contains a count of the rows that have been completed. It returns + /// void. Pass a function with this signature to the SetCallback() + /// method. + NoiseMapCallback m_pCallback; + + /// Height of the destination noise map, in points. + int m_destHeight; + + /// Width of the destination noise map, in points. + int m_destWidth; + + /// Destination noise map that will contain the coherent-noise values. + NoiseMap* m_pDestNoiseMap; + + /// Source noise module that will generate the coherent-noise values. + const module::Module* m_pSourceModule; + + }; + + /// Builds a cylindrical noise map. + /// + /// This class builds a noise map by filling it with coherent-noise values + /// generated from the surface of a cylinder. + /// + /// This class describes these input values using an (angle, height) + /// coordinate system. After generating the coherent-noise value from the + /// input value, it then "flattens" these coordinates onto a plane so that + /// it can write the values into a two-dimensional noise map. + /// + /// The cylinder model has a radius of 1.0 unit and has infinite height. + /// The cylinder is oriented along the @a y axis. Its center is at the + /// origin. + /// + /// The x coordinate in the noise map represents the angle around the + /// cylinder's y axis. The y coordinate in the noise map represents the + /// height above the x-z plane. + /// + /// The application must provide the lower and upper angle bounds of the + /// noise map, in degrees, and the lower and upper height bounds of the + /// noise map, in units. + class NoiseMapBuilderCylinder: public NoiseMapBuilder + { + + public: + + /// Constructor. + NoiseMapBuilderCylinder (); + + virtual void Build (); + + /// Returns the lower angle boundary of the cylindrical noise map. + /// + /// @returns The lower angle boundary of the noise map, in degrees. + double GetLowerAngleBound () const + { + return m_lowerAngleBound; + } + + /// Returns the lower height boundary of the cylindrical noise map. + /// + /// @returns The lower height boundary of the noise map, in units. + /// + /// One unit is equal to the radius of the cylinder. + double GetLowerHeightBound () const + { + return m_lowerHeightBound; + } + + /// Returns the upper angle boundary of the cylindrical noise map. + /// + /// @returns The upper angle boundary of the noise map, in degrees. + double GetUpperAngleBound () const + { + return m_upperAngleBound; + } + + /// Returns the upper height boundary of the cylindrical noise map. + /// + /// @returns The upper height boundary of the noise map, in units. + /// + /// One unit is equal to the radius of the cylinder. + double GetUpperHeightBound () const + { + return m_upperHeightBound; + } + + /// Sets the coordinate boundaries of the noise map. + /// + /// @param lowerAngleBound The lower angle boundary of the noise map, + /// in degrees. + /// @param upperAngleBound The upper angle boundary of the noise map, + /// in degrees. + /// @param lowerHeightBound The lower height boundary of the noise + /// map, in units. + /// @param upperHeightBound The upper height boundary of the noise + /// map, in units. + /// + /// @pre The lower angle boundary is less than the upper angle + /// boundary. + /// @pre The lower height boundary is less than the upper height + /// boundary. + /// + /// @throw noise::ExceptionInvalidParam See the preconditions. + /// + /// One unit is equal to the radius of the cylinder. + void SetBounds (double lowerAngleBound, double upperAngleBound, + double lowerHeightBound, double upperHeightBound) + { + if (lowerAngleBound >= upperAngleBound + || lowerHeightBound >= upperHeightBound) { + throw noise::ExceptionInvalidParam (); + } + + m_lowerAngleBound = lowerAngleBound ; + m_upperAngleBound = upperAngleBound ; + m_lowerHeightBound = lowerHeightBound; + m_upperHeightBound = upperHeightBound; + } + + private: + + /// Lower angle boundary of the cylindrical noise map, in degrees. + double m_lowerAngleBound; + + /// Lower height boundary of the cylindrical noise map, in units. + double m_lowerHeightBound; + + /// Upper angle boundary of the cylindrical noise map, in degrees. + double m_upperAngleBound; + + /// Upper height boundary of the cylindrical noise map, in units. + double m_upperHeightBound; + + }; + + /// Builds a planar noise map. + /// + /// This class builds a noise map by filling it with coherent-noise values + /// generated from the surface of a plane. + /// + /// This class describes these input values using (x, z) coordinates. + /// Their y coordinates are always 0.0. + /// + /// The application must provide the lower and upper x coordinate bounds + /// of the noise map, in units, and the lower and upper z coordinate + /// bounds of the noise map, in units. + /// + /// To make a tileable noise map with no seams at the edges, call the + /// EnableSeamless() method. + class NoiseMapBuilderPlane: public NoiseMapBuilder + { + + public: + + /// Constructor. + NoiseMapBuilderPlane (); + + virtual void Build (); + + /// Enables or disables seamless tiling. + /// + /// @param enable A flag that enables or disables seamless tiling. + /// + /// Enabling seamless tiling builds a noise map with no seams at the + /// edges. This allows the noise map to be tileable. + void EnableSeamless (bool enable = true) + { + m_isSeamlessEnabled = enable; + } + + /// Returns the lower x boundary of the planar noise map. + /// + /// @returns The lower x boundary of the planar noise map, in units. + double GetLowerXBound () const + { + return m_lowerXBound; + } + + /// Returns the lower z boundary of the planar noise map. + /// + /// @returns The lower z boundary of the noise map, in units. + double GetLowerZBound () const + { + return m_lowerZBound; + } + + /// Returns the upper x boundary of the planar noise map. + /// + /// @returns The upper x boundary of the noise map, in units. + double GetUpperXBound () const + { + return m_upperXBound; + } + + /// Returns the upper z boundary of the planar noise map. + /// + /// @returns The upper z boundary of the noise map, in units. + double GetUpperZBound () const + { + return m_upperZBound; + } + + /// Determines if seamless tiling is enabled. + /// + /// @returns + /// - @a true if seamless tiling is enabled. + /// - @a false if seamless tiling is disabled. + /// + /// Enabling seamless tiling builds a noise map with no seams at the + /// edges. This allows the noise map to be tileable. + bool IsSeamlessEnabled () const + { + return m_isSeamlessEnabled; + } + + /// Sets the boundaries of the planar noise map. + /// + /// @param lowerXBound The lower x boundary of the noise map, in + /// units. + /// @param upperXBound The upper x boundary of the noise map, in + /// units. + /// @param lowerZBound The lower z boundary of the noise map, in + /// units. + /// @param upperZBound The upper z boundary of the noise map, in + /// units. + /// + /// @pre The lower x boundary is less than the upper x boundary. + /// @pre Th