From 959621854b34311395c701f44b4be41d44a7434a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 16 Sep 2012 21:48:12 +0200 Subject: [PATCH 1/3] Extending documentation for CubicSurfaceExtractor. --- .../diagrams/CubicSurfaceExtractor3.dia | Bin 0 -> 2894 bytes .../images/CubicSurfaceExtractor2.png | Bin 0 -> 13766 bytes .../images/CubicSurfaceExtractor3.png | Bin 0 -> 16120 bytes .../PolyVoxCore/CubicSurfaceExtractor.h | 25 ++++++++++++++++-- 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 documentation/diagrams/CubicSurfaceExtractor3.dia create mode 100644 documentation/images/CubicSurfaceExtractor2.png create mode 100644 documentation/images/CubicSurfaceExtractor3.png diff --git a/documentation/diagrams/CubicSurfaceExtractor3.dia b/documentation/diagrams/CubicSurfaceExtractor3.dia new file mode 100644 index 0000000000000000000000000000000000000000..256e6ffee3b044e2251dace59132b2df5bae02c5 GIT binary patch literal 2894 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 literal 0 HcmV?d00001 diff --git a/documentation/images/CubicSurfaceExtractor2.png b/documentation/images/CubicSurfaceExtractor2.png new file mode 100644 index 0000000000000000000000000000000000000000..6c67154b14b963d8e375078251a6a19baa8a3491 GIT binary patch literal 13766 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 literal 0 HcmV?d00001 diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index 387e4e14..10a54bfa 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -44,13 +44,34 @@ namespace PolyVox /// /// Basic Operation /// --------------- - /// At its core, the CubicSurfaceExtractor works by by looking at pairs of adjacent voxels and determining whether a quad should be placed between then. The most simple situation to imagine is a binary volume where every voxel is either solid or empty. In this case a quad should be generated when ever a solid voxel is next to an empty voxel as this represent part of the surface of the solid object. there is no need to generate a quad between two solid voxels (this quad would never be seen as it is inside the object) and there is no need to generate a quad between two empty voxels (there is no object here). PolyVox allows the principle to be extended far beyond such simple binary volumes but they provide a useful starting point for understanding how the algorithm works. + /// At its core, the CubicSurfaceExtractor works by by looking at pairs of adjacent voxels and determining whether a quad should be placed between then. The most simple situation to imagine is a binary volume where every voxel is either solid or empty. In this case a quad should be generated whenever a solid voxel is next to an empty voxel as this represents part of the surface of the solid object. There is no need to generate a quad between two solid voxels (this quad would never be seen as it is inside the object) and there is no need to generate a quad between two empty voxels (there is no object here). PolyVox allows the principle to be extended far beyond such simple binary volumes but they provide a useful starting point for understanding how the algorithm works. /// - /// As an example, lets consider the part of a volume shown below. We are going to explain the principles in only two dimentions as this makes it much simpler to illustrate, so you will need to mentally extend the process into the third dimension. Hopefully you will find this intuitive. The diagram below shows a small part of a larger volume (as indicated by the voxel coordinate on the axes) which contains only solid and empty voxels represented by solid and hollow circles respectively. The region on which we are running the surface extractor is marked in pink, and for the purpose of this example it corresponds to the whole of the diagram. + /// As an example, lets consider the part of a volume shown below. We are going to explain the principles in only two dimensions as this makes it much simpler to illustrate, so you will need to mentally extend the process into the third dimension. Hopefully you will find this intuitive. The diagram below shows a small part of a larger volume (as indicated by the voxel coordinates on the axes) which contains only solid and empty voxels represented by solid and hollow circles respectively. The region on which we are running the surface extractor is marked in pink, and for the purpose of this example it corresponds to the whole of the diagram. /// /// \image html CubicSurfaceExtractor1.png /// /// The output of the surface extractor is the mesh marked in red. As you can see, this forms a closed object which corrsponds to the shape of the underlying voxel data. We won't describe the rendering of such meshes here - for details of this please see (SOME LINK HERE). + /// + /// Working with Regions + /// -------------------- + /// So far the behaviour is easy to understand, but let's look at what happens when the extraction is limited to a particular region of the volume. The figure below shows the same data set as the previous figure, but the extraction region (still marked in pink) has been limited to 13 to 16 in x and 47 to 51 in y: + /// + /// \image html CubicSurfaceExtractor2.png + /// + /// As you can see, the extractor continues to generate a number of quads as indicated by the solid red lines. However, you can also see that the shape is no longer closed. This is because the solid voxels actually extend outside the region which is being processed, and so the extractor does not encounter a boundary between solid and empty voxels. Although this may initially appear problematic, the hole in the mesh does not actually matter because it will be hidden by the mesh corresponding to the region adjacent to it (see next diagram). + /// + /// More interestingly, the diagram also contains a couple of dotted red lines lying on the bottom and right hand side of the extracted region. These are present to illustrate a common point of confusion, which is that *no quads are generated at this position even though it is a boundary between solid and empty voxels*. This is indeed somewhat counter intuitive but there is a rational reasaoning behind it. + /// If you consider the dashed line on the righthand side of the extracted region, then it is clear that this lies on a boundary between solid and empty voxels and so we do need to create quads here. But what is not so clear is whether these quads should be assigned to the mesh which corresponds to the region in pink, or whether they should be assigned to the region to the right of it which is marked in blue in the diagram below: + /// + /// \image html CubicSurfaceExtractor3.png + /// + /// We could choose to add the quads to *both* regions, but this can cause confusion when one of the region is modified (causing the face to disappear or a new one to be created) as *both* regions need to have their mesh regenerated to correctly represent the new state of the volume data. Such pairs of coplanar quads can also cause problems with physics engines, and may prevent transparent block from rendering correctly. Therefore we choose to instead only add the quad to one of the the regions and we always choose the one with the greater coordinate value in the direction in which they differ. In the above example the regions differ by the 'x' component of their position, and so the quad is added to the region with the greater 'x' value (the one marked in blue). + /// + /// **Note:** *This behaviour has changed recently (September 2012). Earlier versions of PolyVox tried to be smart about this problem by looking beyond the region which was being processed, but this complicated the code and didn't work very well. Ultimatly we decided to simply stick with the convention outlined above.* + /// + /// One of the practical implications of this is that when you modify a voxel *you may have to re-extract the mesh for regions other than region which actually contains the voxel you modified.* This happens when the voxel lies on the upper x,y or z face of a region. Assuming that you have some management code which can mark a region as needing re-extraction when a voxel changes, you should probably extend this to mark the regions of neighbouring voxels as invalid (this will have no effect when the voxel is well within a region, but will mark the neighbouring region as needing an update if the voxel lies on a region face). + /// + /// Another scenario which sometimes results in confusion is when you wish to extract a region which corresponds to the whole volume, partcularly when solid voxels extend right to the edge of the volume. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template > class CubicSurfaceExtractor From 79ca5aaae7f2fd6fa9ef0d89820aae70a5934703 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Sep 2012 19:27:01 +0200 Subject: [PATCH 2/3] Work on prerequisites documentation. --- documentation/Prerequisites.rst | 45 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/documentation/Prerequisites.rst b/documentation/Prerequisites.rst index a014c45b..cddb1d0b 100644 --- a/documentation/Prerequisites.rst +++ b/documentation/Prerequisites.rst @@ -1,33 +1,38 @@ ************* Prerequisites ************* -The PolyVox library is also quite low-level in terms of the functionality it provides, and as a result of these factors you will need some significant previous expeience in order to make use of the library effectively. In this document we summarise the key areas with which you will need to be familier, and explain why they are necesssary when using PolyVox. We also provide some links where you can study some background material. +The PolyVox library is aimed at experinced games and graphics programmers who wish to incorporate voxel environments into their applications. It is not a drop in solution, but instead provides a set of building blocks which you can use to construct a complete system. Most of the functionality could be considered quite low-level. For example, it provides mesh extractors to generate a surface from volume data but requires the application developer to handle all tasks related to scene management and rendering of such data. -You should also be aware that voxel terrain is still an open research area and had not yet seen widespread adoption in games and simulations. There are many questions to which we do not currently know the best answer and so you can expect to have to do some research and experimentation yourself when trying to opbtain your desired result. So pease do let us know if you come up with a trick or technique which you think could benefit other users. +As a result you will need a decent amount of graphics programming experience to effectively make use of the library. The purpose of this document is to highlight some of the core areas with which you will need to be familier. In some cases we also provide links to places where you can find more information about the subject in question. -Using the library +You should also be aware that voxel terrain is still an open research area and has not yet seen widespread adoption in games and simulations. There are many questions to which we do not currently know the best answer and so you may have to do some research and experimentation yourself when trying to opbtain your desired result. Please do let us know if you come up with a trick or technique which you think could benefit other users. + +Programming +=========== +This section describes some of the programming concepts with which you will need to be familiar: + +**C++:** PolyVox is written using the C++ language and we expect this is what the majority of our users will be developing in. You will need to be familer with the basic process of building and linking against external libraires as well as setting up your development environment. Note that you do have the option of working with other languages via the SWIG bindings but you may not have as much flexibility with this approach. + +**Templates:** PolyVox also makes heavy use of template programming in order to be both fast and generic, so familiarity with templates will be very useful. You should't need to do much template programming yourself but an understanding of them will help you understand errors and resolve any problems. + +**Callbacks:** Several of the algorithms in PolyVox can be customised through the use of callbacks. In general there are sensible defaults provided, but for maximum control you may wish to learn how to define you own. In general the principle is similar to the way in which callbacks are used in the STL. + +Graphics Concepts ================= -This section describes some of the key principles which you may want to understand in order to make use of PolyVox. Not all of these are strictly required as it depends on exactly what you are trying to achive, but in general you should find them useful: +Several core graphics principles will be useful in understanding and using PolyVox: -Volume graphics: -Surface extaction (MC and our own cubic docs): -Mesh representation: -Image processing: +**Volume representation:** PolyVox revolves around the idea of storing and manipulating volume data and using this as a representation of a 3d world. This is a fairly intuitaive extension of traditional heightmap terrain but does require the ability to 'think in 3D'. You will need to understand that data stored in this way can become very large, and understand the idea that paging and compression can be used to combat this. -There are also some programming concepts with which you will need to be familiar: +**Mesh representation:** Most PolyVox projects will involve using one of the surface extractors, which output their data as index and vertex buffers. Therefore you will need to understand this representation in order to pass the data to your rendering engine or in order to perform further modifications to it. You can find out about more about this here: (ADD LINK) -C++: PolyVox is written using the C++ language and we expect this is what the majority of our users will be developing in. You will need to be familer with the basic process of building and linking against external libraires as well as setting up your development environment. Note that you do have the option of working with other languages via the SWIG bindings but you may not have as much flexibility with this approach. -Templates: PolyVox also makes heavy use of template programming in order to be both fast and generic, so familiarity with templates will be very useful. You should need to do much template programming yourself but an understanding of them will help you understand errors and resolve any problems. -Callbacks: +**Image processing:** For certain advanced application an understanding of image processing methods can be useful. For example the process of blurring an image via a low pass filter can be used to effectively smooth out voxel terrain. There are plans to add more image processing operations to PolyVox particularly with regard to morphological operations which you might want to use to modify your environment. Rendering ========= -Runtime geometry creation: PolyVox is independant of any particular graphics API which means it outputs its data using API-neutral structures such as index/vertex buffers. You will need to write the code which converts these structures into a format which your API or engine can understand. This is not a difficult task but does require some knowledge of the rendering technology you are using. -Scene management: - -Culling, organisation, LOD. +**Runtime geometry creation:** PolyVox is independant of any particular graphics API which means it outputs its data using API-neutral structures such as index and vertex buffers (as mentioned above). You will need to write the code which converts these structures into a format which your API or engine can understand. This is not a difficult task but does require some knowledge of the rendering technology which you are using. -Shader programming -================== -Triplanar texturing: -Texture atlases: -Lighting: +**Scene management:** PolyVox is only responsible for providing you with the mesh data to be displayed, so you application or engine will need to make sensible decisions about how this data should be organised in terms of a spactial structure (octree, bounding volumes tree, etc). It will also need to provide some approach to visibility determination such as frustum culling or a more advanced appraoch. If you are integrating Polyvox with an existing rendering engine then you should find that many of these aspects are already handled for you. + +**Shader programming:** The meshes which are generated by PolyVox are very basic in terms of the vertex data they provide. You get vertex positions, a material identifier, and sometimes vertex normals. It is the responsibility of application programmer to decide how to use this data to create visually interesting renderings. This means you will almost certainly want to make use of shader programs. Of course, in our texturing (LINK) and lighting (LINK) documents you will find many ideas and common solutions, but you will need strong shader programming experience to make effective use of these. + +If you don't have much experience with shader programming then there are many free resources available. The Cg Tutorial (LINK) provides a good introduction here (the concepts are applicable to other shader languages) as does the documentation for the main graphics (LINK to OpenGL docs) APIs (Link to D3D docs). there is nothing special about PolyVox meshes so you would be advised to practice development on simple meshes such as spheres and cubes before trying to apply it to the output of the mesh extractors. \ No newline at end of file From 035c2e7de25d367934f8415fc42bae6ba31f6684 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Sep 2012 19:38:49 +0200 Subject: [PATCH 3/3] Added GLSL example code. --- documentation/Lighting.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/documentation/Lighting.rst b/documentation/Lighting.rst index d316fe5f..daddac37 100644 --- a/documentation/Lighting.rst +++ b/documentation/Lighting.rst @@ -23,7 +23,12 @@ 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: -//GLSL code +.. code-block:: glsl + + vec3 worldNormal = cross(dFdy(inWorldPosition.xyz), dFdx(inWorldPosition.xyz)); + worldNormal = normalize(worldNormal); + +**TODO: Check the normal direction** Similar code can be implemented in HLSL but you may need to invert the normal due to coordinate system differences between the two APIs. Also, be aware that it may be necessary to use OpenGL ES XXX extension in order to access this derivative functionality on mobile hardware.