From c806da9bb7b1407a683137c094da7afe335b1145 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Thu, 16 May 2013 16:17:01 +0200 Subject: [PATCH 1/4] Compile fixes brought across from Cubiquity. --- .../PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h | 6 +++--- library/PolyVoxCore/source/Impl/ErrorHandling.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index 8df554a3..c81c8221 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -121,7 +121,7 @@ namespace PolyVox ss << " Condition: " << #condition << std::endl; \ ss << " Message: " << (message) << std::endl; \ ss << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ - logFatal(ss.str()); \ + PolyVox::logFatal(ss.str()); \ POLYVOX_HALT(); \ } \ } while(0) \ @@ -176,7 +176,7 @@ namespace PolyVox */ #ifdef POLYVOX_THROW_ENABLED #define POLYVOX_THROW(type, message) \ - log(message, LogLevels::Error); \ + PolyVox::logError(message); \ throw type((message)) #else namespace PolyVox @@ -188,7 +188,7 @@ namespace PolyVox } #define POLYVOX_THROW(type, message) \ - log(message, LogLevels::Error); \ + PolyVox::logError(message); \ type except = (type)((message)); \ getThrowHandler()((except), __FILE__, __LINE__) #endif diff --git a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp index c07429df..8e90bb3e 100644 --- a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp +++ b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp @@ -133,7 +133,7 @@ namespace PolyVox ss << " Line: " << line << std::endl; \ ss << " File: " << file << std::endl; \ ss << " Message: " << e.what() << std::endl << std::endl; \ - logFatal(ss.str()); \ + PolyVox::logFatal(ss.str()); \ POLYVOX_HALT(); \ } From db1c2bf0f8aec8dd6923d1c8e784d77cbfd3b3be Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Thu, 16 May 2013 16:19:38 +0200 Subject: [PATCH 2/4] Replaced 'code-block' with 'sourcecode'. --- documentation/Lighting.rst | 2 +- documentation/TextureMapping.rst | 6 +++--- documentation/python-bindings.rst | 4 ++-- documentation/tutorial1.rst | 16 ++++++++-------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/documentation/Lighting.rst b/documentation/Lighting.rst index 986f60a0..569f31cd 100644 --- a/documentation/Lighting.rst +++ b/documentation/Lighting.rst @@ -23,7 +23,7 @@ The description here is rather oversimplified, but the idea behind these operati Further information about the derivative operations can be found in the OpenGL/Direct3D API documentation, but the implementation in code is quite simple. Firstly you need to make sure that you have access to the fragments world space position in your shader, which means you need to pass it through from the vertex shader. Then you can use the following code in your fragment shader: -.. code-block:: glsl +.. sourcecode:: glsl vec3 worldNormal = cross(dFdy(inWorldPosition.xyz), dFdx(inWorldPosition.xyz)); worldNormal = normalize(worldNormal); diff --git a/documentation/TextureMapping.rst b/documentation/TextureMapping.rst index b3d3929f..f9b3ca2f 100644 --- a/documentation/TextureMapping.rst +++ b/documentation/TextureMapping.rst @@ -33,7 +33,7 @@ Triplanar Texturing ------------------- The most common approach to texture mapping smooth voxel terrain is to use *triplanar texturing*. The basic idea is to project a texture along all three main axes and blend between the three texture samples according to the surface normal. As an example, suppose that we wish to write a fragment shader to apply a single texture to our terrain, and assume that we have access to both the world space position of the fragment and also its normalised surface normal. Also, note that your textures should be set to wrap because the world space position will quickly go outside the bounds of 0.0-1.0. The world space position will need to have been passed through from earlier in the pipeline while the normal can be computed using one of the approaches in the lighting (link) document. The shader code would then look something like this [footnote: code is untested as is simplified compared to real world code. hopefully it compiles, but if not it should still give you an idea of how it works]: -.. code-block:: glsl +.. sourcecode:: glsl // Take the three texture samples vec4 sampleX = texture2d(inputTexture, worldSpacePos.yz); // Project along x axis @@ -47,7 +47,7 @@ Note that this approach will lead to the texture repeating once every world unit This idea of triplanar texturing can be applied to the cubic meshes as well, and in some ways it can be considered to be even simpler. With cubic meshes the normal always points exactly along one of the main axes, and so it is not necessary to sample the texture three times nor to blend the results. Instead you can use conditional branching in the fragment shader to determine which pair of values out of {x,y,z} should be used as the texture coordinates. Something like: -.. code-block:: glsl +.. sourcecode:: glsl vec4 sample = vec4(0, 0, 0, 0); // We'll fill this in below // Assume the normal is normalised. @@ -71,7 +71,7 @@ Both the CubicSurfaceExtractor and the MarchingCubesSurfacExtractor understand t The following code snippet assumes that you have passed the material identifier to your shaders and that you can access it in the fragment shader. It then chooses which colour to draw the polygon based on this identifier: -.. code-block:: glsl +.. sourcecode:: glsl vec4 fragmentColour = vec4(1, 1, 1, 1); // Default value if(materialId < 0.5) //Avoid '==' when working with floats. diff --git a/documentation/python-bindings.rst b/documentation/python-bindings.rst index 0e2d739e..c06750e8 100644 --- a/documentation/python-bindings.rst +++ b/documentation/python-bindings.rst @@ -22,13 +22,13 @@ Since C++ templates are essentially a code-generation system built into the C++ The way we work around this is by, as part of the bindings generation process, pre-compiling a number of different versions of each templated class. For example, in C++ a 3D vector containing 32-bit integers would be declared as -.. code-block:: c++ +.. sourcecode:: c++ PolyVox::Vector3D my_vec(0,1,4); but in Python it would be accessed as -.. code-block:: python +.. sourcecode:: python my_vec = PolyVoxCore.Vector3Dint32_t(0,1,4) diff --git a/documentation/tutorial1.rst b/documentation/tutorial1.rst index d546eb90..44660cb5 100644 --- a/documentation/tutorial1.rst +++ b/documentation/tutorial1.rst @@ -12,7 +12,7 @@ Creating a volume ================= To get started, we need to include the following headers: -.. code-block:: c++ +.. sourcecode:: c++ #include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h" #include "PolyVoxCore/MarchingCubesSurfaceExtractor.h" @@ -21,7 +21,7 @@ To get started, we need to include the following headers: The most fundamental construct when working with PolyVox is that of the volume. This is represented by the :polyvox:`SimpleVolume` class which stores a 3D grid of voxels. Our basic example application creates a volume with the following line of code: -.. code-block:: c++ +.. sourcecode:: c++ SimpleVolume volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63))); @@ -29,13 +29,13 @@ As can be seen, the SimpleVolume class is templated upon the voxel type. This me Next, we set some of the voxels in the volume to be 'solid' in order to create a large sphere in the centre of the volume. We do this with the following function call: -.. code-block:: c++ +.. sourcecode:: c++ createSphereInVolume(volData, 30); Note that this function is part of the BasicExample (rather than being part of the PolyVox library) and is implemented as follows: -.. code-block:: c++ +.. sourcecode:: c++ void createSphereInVolume(SimpleVolume& volData, float fRadius) { @@ -80,7 +80,7 @@ Extracting the surface ====================== Now that we have built our volume we need to convert it into a triangle mesh for rendering. This process can be performed by the :polyvox:`CubicSurfaceExtractorWithNormals` class. An instance of the :polyvox:`CubicSurfaceExtractorWithNormals` is created as follows: -.. code-block:: c++ +.. sourcecode:: c++ SurfaceMesh mesh; CubicSurfaceExtractorWithNormals< SimpleVolume > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); @@ -89,7 +89,7 @@ The :polyvox:`CubicSurfaceExtractorWithNormals` takes a pointer to the volume da The actual extraction happens in the :polyvox:`CubicSurfaceExtractorWithNormals::execute` function. This means you can set up a :polyvox:`CubicSurfaceExtractorWithNormals` with the required parameters and then actually execute it later. For this example we just call it straight away. -.. code-block:: c++ +.. sourcecode:: c++ surfaceExtractor.execute(); @@ -103,7 +103,7 @@ Rendering the surface with OpenGL is handled by the OpenGLWidget class. Again, t The OpenGLWidget::setSurfaceMeshToRender() function is implemented as follows: -.. code-block:: c++ +.. sourcecode:: c++ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh) { @@ -135,7 +135,7 @@ The begin and end indices are used in the OpenGLWidget::paintGL() to control wha With the OpenGL index and vertex buffers set up, we can now look at the code which is called each frame to render them: -.. code-block:: c++ +.. sourcecode:: c++ void OpenGLWidget::paintGL() { From f3b01830139fb04fbb6bdc1086d536e7d69ba618 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Wed, 22 May 2013 14:21:50 +0200 Subject: [PATCH 3/4] Switching to a stream-based interface for logging. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 55 +++----- .../PolyVoxCore/source/Impl/ErrorHandling.cpp | 120 +++++------------- 2 files changed, 52 insertions(+), 123 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index c81c8221..c48255d4 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -62,36 +62,19 @@ freely, subject to the following restrictions: * PolyVox provides basic logging facilities which can be redirected by your application. */ +#define LOG_DECLARATION(name) \ + std::ostream& log(name)(void); \ + void set(name)Stream(std::ostream& nameStream); + namespace PolyVox { - class LogLevels - { - public: - enum LogLevel - { - Debug, - Info, - Warning, - Error, - Fatal - }; - }; - typedef LogLevels::LogLevel LogLevel; + std::ostream& logError(void); + std::ostream& logFatal(void); - typedef void (*LogHandler)(const std::string& message, LogLevel logLevel); - - LogHandler getLogHandler(); - void setLogHandler(LogHandler newHandler); - - // The actual logging function - void log(const std::string& message, LogLevel logLevel); - - // Some handy wrappers - void logDebug (const std::string& message); - void logInfo (const std::string& message); - void logWarning(const std::string& message); - void logError (const std::string& message); - void logFatal (const std::string& message); + // These take pointers rather than references to emphasise that the + // user needs to keep the target alive as long as PolyVox is writing data. + void setErrorStream(std::ostream* errorStream); + void setFatalStream(std::ostream* fatalStream); } /* @@ -114,14 +97,12 @@ namespace PolyVox { \ if (!(condition)) \ { \ - std::stringstream ss; \ - ss << std::endl << std::endl; \ - ss << " PolyVox Assertion Failed!" << std::endl; \ - ss << " =========================" << std::endl; \ - ss << " Condition: " << #condition << std::endl; \ - ss << " Message: " << (message) << std::endl; \ - ss << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ - PolyVox::logFatal(ss.str()); \ + logFatal() << std::endl << std::endl; \ + logFatal() << " PolyVox Assertion Failed!" << std::endl; \ + logFatal() << " =========================" << std::endl; \ + logFatal() << " Condition: " << #condition << std::endl; \ + logFatal() << " Message: " << (message) << std::endl; \ + logFatal() << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ POLYVOX_HALT(); \ } \ } while(0) \ @@ -176,7 +157,7 @@ namespace PolyVox */ #ifdef POLYVOX_THROW_ENABLED #define POLYVOX_THROW(type, message) \ - PolyVox::logError(message); \ + logError() << (message); \ throw type((message)) #else namespace PolyVox @@ -188,7 +169,7 @@ namespace PolyVox } #define POLYVOX_THROW(type, message) \ - PolyVox::logError(message); \ + logError() << (message); \ type except = (type)((message)); \ getThrowHandler()((except), __FILE__, __LINE__) #endif diff --git a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp index 8e90bb3e..8cef5e6d 100644 --- a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp +++ b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp @@ -25,115 +25,63 @@ freely, subject to the following restrictions: namespace PolyVox { - void defaultLogHandler(const std::string& message, LogLevel logLevel) + // Error stream for logging + std::ostream*& getErrorStreamInstance() { - switch(logLevel) - { - case LogLevels::Debug: - { - // Debug messages are not output by this default log handler. - // Provide a custom handler if you want to process them. - break; - } - case LogLevels::Info: - { - std::cout << "Info: " << message.c_str() << std::endl; - break; - } - case LogLevels::Warning: - { - std::cerr << "Warning: " << message.c_str() << std::endl; - break; - } - case LogLevels::Error: - { - std::cerr << "Error: " << message.c_str() << std::endl; - break; - } - case LogLevels::Fatal: - { - std::cerr << "Fatal: " << message.c_str() << std::endl; - break; - } - } + static std::ostream* s_pErrorStream = &(std::cerr); + return s_pErrorStream; } - LogHandler& getLogHandlerInstance() + void setErrorStream(std::ostream* errorStream) { - static LogHandler s_fLogHandler = &defaultLogHandler; - return s_fLogHandler; + getErrorStreamInstance() = errorStream; } - LogHandler getLogHandler() + std::ostream& logError(void) { - return getLogHandlerInstance(); + return *(getErrorStreamInstance()); } - void setLogHandler(LogHandler fNewHandler) + // Fatal stream for logging + std::ostream*& getFatalStreamInstance() { - getLogHandlerInstance() = fNewHandler; + static std::ostream* s_pFatalStream = &(std::cerr); + return s_pFatalStream; } - void log(const std::string& message, LogLevel logLevel) + void setFatalStream(std::ostream* fatalStream) { - LogHandler logHandler = getLogHandler(); - if(logHandler) - { - logHandler(message, logLevel); - } + getFatalStreamInstance() = fatalStream; } - // Some handy wrappers - void logDebug(const std::string& message) - { - log(message, LogLevels::Debug ); - } - - void logInfo(const std::string& message) + std::ostream& logFatal(void) { - log(message, LogLevels::Info); - } - - void logWarning(const std::string& message) - { - log(message, LogLevels::Warning); - } - - void logError(const std::string& message) - { - log(message, LogLevels::Error); - } - - void logFatal(const std::string& message) - { - log(message, LogLevels::Fatal); + return *(getFatalStreamInstance()); } #ifndef POLYVOX_THROW_ENABLED void defaultThrowHandler(std::exception& e, const char* file, int line) { - std::stringstream ss; \ - ss << std::endl << std::endl; \ - ss << " PolyVox exception thrown!" << std::endl; \ - ss << " =========================" << std::endl; \ - ss << " PolyVox has tried to throw an exception but it was built without support" << std::endl; \ - ss << " for exceptions. In this scenario PolyVox will call a 'throw handler'" << std::endl; \ - ss << " and this message is being printed by the default throw handler." << std::endl << std::endl; \ + logFatal() << std::endl << std::endl; \ + logFatal() << " PolyVox exception thrown!" << std::endl; \ + logFatal() << " =========================" << std::endl; \ + logFatal() << " PolyVox has tried to throw an exception but it was built without support" << std::endl; \ + logFatal() << " for exceptions. In this scenario PolyVox will call a 'throw handler'" << std::endl; \ + logFatal() << " and this message is being printed by the default throw handler." << std::endl << std::endl; \ - ss << " If you don't want to enable exceptions then you should try to determine why" << std::endl; \ - ss << " this exception was thrown and make sure it doesn't happen again. If it was" << std::endl; \ - ss << " due to something like an invalid argument to a function then you should be" << std::endl; \ - ss << " able to fix it quite easily by validating parameters as appropriate. More" << std::endl; \ - ss << " complex exception scenarios (out of memory, etc) might be harder to fix and" << std::endl; \ - ss << " you should replace this default handler with something which is more" << std::endl; \ - ss << " meaningful to your users." << std::endl << std::endl; \ + logFatal() << " If you don't want to enable exceptions then you should try to determine why" << std::endl; \ + logFatal() << " this exception was thrown and make sure it doesn't happen again. If it was" << std::endl; \ + logFatal() << " due to something like an invalid argument to a function then you should be" << std::endl; \ + logFatal() << " able to fix it quite easily by validating parameters as appropriate. More" << std::endl; \ + logFatal() << " complex exception scenarios (out of memory, etc) might be harder to fix and" << std::endl; \ + logFatal() << " you should replace this default handler with something which is more" << std::endl; \ + logFatal() << " meaningful to your users." << std::endl << std::endl; \ - ss << " Exception details" << std::endl; \ - ss << " -----------------" << std::endl; \ - ss << " Line: " << line << std::endl; \ - ss << " File: " << file << std::endl; \ - ss << " Message: " << e.what() << std::endl << std::endl; \ - PolyVox::logFatal(ss.str()); \ + logFatal() << " Exception details" << std::endl; \ + logFatal() << " -----------------" << std::endl; \ + logFatal() << " Line: " << line << std::endl; \ + logFatal() << " File: " << file << std::endl; \ + logFatal() << " Message: " << e.what() << std::endl << std::endl; \ POLYVOX_HALT(); \ } From 6c77e778ddf1e4b2fca595c2634e0e54ee715956 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Wed, 22 May 2013 15:18:08 +0200 Subject: [PATCH 4/4] Added namespace qualifiers. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index c48255d4..17a31107 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -97,12 +97,12 @@ namespace PolyVox { \ if (!(condition)) \ { \ - logFatal() << std::endl << std::endl; \ - logFatal() << " PolyVox Assertion Failed!" << std::endl; \ - logFatal() << " =========================" << std::endl; \ - logFatal() << " Condition: " << #condition << std::endl; \ - logFatal() << " Message: " << (message) << std::endl; \ - logFatal() << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ + PolyVox::logFatal() << std::endl << std::endl; \ + PolyVox::logFatal() << " PolyVox Assertion Failed!" << std::endl; \ + PolyVox::logFatal() << " =========================" << std::endl; \ + PolyVox::logFatal() << " Condition: " << #condition << std::endl; \ + PolyVox::logFatal() << " Message: " << (message) << std::endl; \ + PolyVox::logFatal() << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ POLYVOX_HALT(); \ } \ } while(0) \ @@ -157,7 +157,7 @@ namespace PolyVox */ #ifdef POLYVOX_THROW_ENABLED #define POLYVOX_THROW(type, message) \ - logError() << (message); \ + PolyVox::logError() << (message); \ throw type((message)) #else namespace PolyVox @@ -169,7 +169,7 @@ namespace PolyVox } #define POLYVOX_THROW(type, message) \ - logError() << (message); \ + PolyVox::logError() << (message); \ type except = (type)((message)); \ getThrowHandler()((except), __FILE__, __LINE__) #endif