Created
June 14, 2016 06:05
-
-
Save mgerhardy/e3e06822f7b8813fa31b88fb3e23bae6 to your computer and use it in GitHub Desktop.
Ambient occlusion patch for PolyVox develop branch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From d24f9b9d4c95e148b52ab6cc8dd1d16daa87ba95 Mon Sep 17 00:00:00 2001 | |
From: Martin Gerhardy <martin.gerhardy@gmail.com> | |
Date: Fri, 20 May 2016 11:52:38 +0200 | |
Subject: [PATCH] implemented ao | |
--- | |
examples/DecodeOnGPU/decode.vert | 1 + | |
examples/Paging/main.cpp | 10 +- | |
examples/common/OpenGLWidget.inl | 1 + | |
examples/common/PolyVoxExample.h | 14 +- | |
examples/common/example.vert | 2 + | |
include/PolyVox/CubicSurfaceExtractor.h | 11 +- | |
include/PolyVox/CubicSurfaceExtractor.inl | 266 ++++++++++++++++++++++-------- | |
include/PolyVox/DefaultContributeToAO.h | 45 +++++ | |
include/PolyVox/Vertex.h | 1 + | |
9 files changed, 276 insertions(+), 75 deletions(-) | |
create mode 100644 include/PolyVox/DefaultContributeToAO.h | |
diff --git a/examples/DecodeOnGPU/decode.vert b/examples/DecodeOnGPU/decode.vert | |
index 41aaf82..e5a1481 100644 | |
--- a/examples/DecodeOnGPU/decode.vert | |
+++ b/examples/DecodeOnGPU/decode.vert | |
@@ -1,6 +1,7 @@ | |
#version 140 | |
in uvec4 position; // This will be the position of the vertex in model-space | |
+in int ao; | |
in uint normal; | |
// The usual matrices are provided | |
diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp | |
index 1537adc..52eeafb 100644 | |
--- a/examples/Paging/main.cpp | |
+++ b/examples/Paging/main.cpp | |
@@ -115,6 +115,14 @@ public: | |
protected: | |
void initializeExample() override | |
{ | |
+ class ContributeToAO | |
+ { | |
+ public: | |
+ bool operator()(MaterialDensityPair44 voxeltype) | |
+ { | |
+ return voxeltype.getMaterial() > 0; | |
+ } | |
+ }; | |
PerlinNoisePager* pager = new PerlinNoisePager(); | |
PagedVolume<MaterialDensityPair44> volData(pager, 8 * 1024 * 1024, 64); | |
@@ -130,7 +138,7 @@ protected: | |
// Extract the surface | |
PolyVox::Region reg2(Vector3DInt32(0, 0, 0), Vector3DInt32(254, 254, 254)); | |
- auto mesh = extractCubicMesh(&volData, reg2); | |
+ auto mesh = extractCubicMesh(&volData, reg2, DefaultIsQuadNeeded<MaterialDensityPair44>(), ContributeToAO()); | |
std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl; | |
auto decodedMesh = decodeMesh(mesh); | |
diff --git a/examples/common/OpenGLWidget.inl b/examples/common/OpenGLWidget.inl | |
index 9365789..f231567 100644 | |
--- a/examples/common/OpenGLWidget.inl | |
+++ b/examples/common/OpenGLWidget.inl | |
@@ -2,6 +2,7 @@ | |
#include <QMouseEvent> | |
#include <QTimer> | |
+#include <cmath> | |
#include <iostream> | |
diff --git a/examples/common/PolyVoxExample.h b/examples/common/PolyVoxExample.h | |
index ea2efbe..c2994d3 100644 | |
--- a/examples/common/PolyVoxExample.h | |
+++ b/examples/common/PolyVoxExample.h | |
@@ -85,18 +85,22 @@ public: | |
glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions | |
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) | |
+ // Now the ambient occlusion | |
+ glEnableVertexAttribArray(1); //We're talking about shader attribute '1' | |
+ glVertexAttribIPointer(1, 1, GL_UNSIGNED_BYTE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, ambientOcclusion))); | |
+ | |
// Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor | |
// does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the | |
// shader. This is mostly just to simplify this example code - in a real application you will know whether your | |
// chosen surface extractor generates normals and can skip uploading them if not. | |
- glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. | |
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, normal))); | |
+ glEnableVertexAttribArray(2); // Attrib '2' is the vertex normals. | |
+ glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, normal))); | |
// Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code | |
// we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. | |
- glEnableVertexAttribArray(2); //We're talking about shader attribute '2' | |
+ glEnableVertexAttribArray(3); //We're talking about shader attribute '3' | |
GLint size = (std::min)(sizeof(typename MeshType::VertexType::DataType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) | |
- glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, data))); | |
+ glVertexAttribIPointer(3, size, GL_UNSIGNED_BYTE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, data))); | |
// We're done uploading and can now unbind. | |
glBindVertexArray(0); | |
@@ -198,4 +202,4 @@ private: | |
QSharedPointer<QGLShaderProgram> mShader; | |
}; | |
-#endif //__PolyVoxExample_H__ | |
\ No newline at end of file | |
+#endif //__PolyVoxExample_H__ | |
diff --git a/examples/common/example.vert b/examples/common/example.vert | |
index c0643e1..29916e4 100644 | |
--- a/examples/common/example.vert | |
+++ b/examples/common/example.vert | |
@@ -1,6 +1,8 @@ | |
#version 140 | |
in vec4 position; // This will be the position of the vertex in model-space | |
+in int ao; | |
+in vec4 normal; // This will be the position of the vertex in model-space | |
// The usual matrices are provided | |
uniform mat4 projectionMatrix; | |
diff --git a/include/PolyVox/CubicSurfaceExtractor.h b/include/PolyVox/CubicSurfaceExtractor.h | |
index d0499b8..f72eebe 100644 | |
--- a/include/PolyVox/CubicSurfaceExtractor.h | |
+++ b/include/PolyVox/CubicSurfaceExtractor.h | |
@@ -30,6 +30,7 @@ | |
#include "Array.h" | |
#include "BaseVolume.h" //For wrap modes... should move these? | |
#include "DefaultIsQuadNeeded.h" | |
+#include "DefaultContributeToAO.h" | |
#include "Mesh.h" | |
#include "Vertex.h" | |
@@ -47,6 +48,8 @@ namespace PolyVox | |
/// The true position is found by offseting each component by 0.5f. | |
Vector3DUint8 encodedPosition; | |
+ uint8_t ambientOcclusion; | |
+ | |
/// A copy of the data which was stored in the voxel which generated this vertex. | |
DataType data; | |
}; | |
@@ -64,12 +67,12 @@ namespace PolyVox | |
Vertex<DataType> decodeVertex(const CubicVertex<DataType>& cubicVertex); | |
/// Generates a cubic-style mesh from the voxel data. | |
- template<typename VolumeType, typename MeshType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> > | |
- void extractCubicMeshCustom(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), bool bMergeQuads = true); | |
+ template<typename VolumeType, typename MeshType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType>, typename ContributeToAO = DefaultContributeToAO<typename VolumeType::VoxelType> > | |
+ void extractCubicMeshCustom(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), ContributeToAO contributeToAO = ContributeToAO(), bool bMergeQuads = true); | |
/// Generates a cubic-style mesh from the voxel data, placing the result into a user-provided Mesh. | |
- template<typename VolumeType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> > | |
- Mesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicMesh(VolumeType* volData, Region region, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), bool bMergeQuads = true); | |
+ template<typename VolumeType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType>, typename ContributeToAO = DefaultContributeToAO<typename VolumeType::VoxelType> > | |
+ Mesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicMesh(VolumeType* volData, Region region, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), ContributeToAO contributeToAO = ContributeToAO(), bool bMergeQuads = true); | |
} | |
diff --git a/include/PolyVox/CubicSurfaceExtractor.inl b/include/PolyVox/CubicSurfaceExtractor.inl | |
index 846c776..ffb1666 100644 | |
--- a/include/PolyVox/CubicSurfaceExtractor.inl | |
+++ b/include/PolyVox/CubicSurfaceExtractor.inl | |
@@ -70,6 +70,7 @@ namespace PolyVox | |
{ | |
int32_t iIndex; | |
typename VolumeType::VoxelType uMaterial; | |
+ uint8_t ambientOcclusion; | |
}; | |
//////////////////////////////////////////////////////////////////////////////// | |
@@ -90,6 +91,7 @@ namespace PolyVox | |
result.position = decodePosition(cubicVertex.encodedPosition); | |
result.normal.setElements(0.0f, 0.0f, 0.0f); // Currently not calculated | |
result.data = cubicVertex.data; // Data is not encoded | |
+ result.ambientOcclusion = cubicVertex.ambientOcclusion; | |
return result; | |
} | |
@@ -97,13 +99,24 @@ namespace PolyVox | |
// Surface extraction | |
//////////////////////////////////////////////////////////////////////////////// | |
+ template<typename VertexType> | |
+ bool isSameVertex(const VertexType& v1, const VertexType& v2) | |
+ { | |
+ return v1.data == v2.data && v1.ambientOcclusion == v2.ambientOcclusion; | |
+ } | |
+ | |
template<typename MeshType> | |
bool mergeQuads(Quad& q1, Quad& q2, MeshType* m_meshCurrent) | |
{ | |
- //All four vertices of a given quad have the same data, | |
- //so just check that the first pair of vertices match. | |
- if (m_meshCurrent->getVertex(q1.vertices[0]).data == m_meshCurrent->getVertex(q2.vertices[0]).data) | |
- { | |
+ const typename MeshType::VertexType& v11 = m_meshCurrent->getVertex(q1.vertices[0]); | |
+ const typename MeshType::VertexType& v21 = m_meshCurrent->getVertex(q2.vertices[0]); | |
+ const typename MeshType::VertexType& v12 = m_meshCurrent->getVertex(q1.vertices[1]); | |
+ const typename MeshType::VertexType& v22 = m_meshCurrent->getVertex(q2.vertices[1]); | |
+ const typename MeshType::VertexType& v13 = m_meshCurrent->getVertex(q1.vertices[2]); | |
+ const typename MeshType::VertexType& v23 = m_meshCurrent->getVertex(q2.vertices[2]); | |
+ const typename MeshType::VertexType& v14 = m_meshCurrent->getVertex(q1.vertices[3]); | |
+ const typename MeshType::VertexType& v24 = m_meshCurrent->getVertex(q2.vertices[3]); | |
+ if (isSameVertex(v11, v21) && isSameVertex(v12, v22) && isSameVertex(v13, v23) && isSameVertex(v14, v24)) { | |
//Now check whether quad 2 is adjacent to quad one by comparing vertices. | |
//Adjacent quads must share two vertices, and the second quad could be to the | |
//top, bottom, left, of right of the first one. This gives four combinations to test. | |
@@ -167,27 +180,42 @@ namespace PolyVox | |
return bDidMerge; | |
} | |
- template<typename VolumeType, typename MeshType> | |
- int32_t addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterialIn, Array<3, IndexAndMaterial<VolumeType> >& existingVertices, MeshType* m_meshCurrent) | |
+ // https://0fps.net/2013/07/03/ambient-occlusion-for-minecraft-like-worlds/ | |
+ // 0 is the darkest | |
+ // 3 is no occlusion at all | |
+ inline uint8_t vertexAmbientOcclusion(bool side1, bool side2, bool corner) | |
+ { | |
+ if (side1 && side2) { | |
+ return 0; | |
+ } | |
+ return 3 - (side1 + side2 + corner); | |
+ } | |
+ | |
+ template<typename VolumeType, typename MeshType, typename ContributeToAO> | |
+ int32_t addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterialIn, Array<3, IndexAndMaterial<VolumeType> >& existingVertices, MeshType* m_meshCurrent, const typename VolumeType::VoxelType& face1, const typename VolumeType::VoxelType& face2, const typename VolumeType::VoxelType& corner, ContributeToAO contributeToAO) | |
{ | |
for (uint32_t ct = 0; ct < MaxVerticesPerPosition; ct++) | |
{ | |
IndexAndMaterial<VolumeType>& rEntry = existingVertices(uX, uY, ct); | |
+ const uint8_t ambientOcclusion = vertexAmbientOcclusion(contributeToAO(face1), contributeToAO(face2), contributeToAO(corner)); | |
+ | |
if (rEntry.iIndex == -1) | |
{ | |
//No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them. | |
CubicVertex<typename VolumeType::VoxelType> cubicVertex; | |
cubicVertex.encodedPosition.setElements(static_cast<uint8_t>(uX), static_cast<uint8_t>(uY), static_cast<uint8_t>(uZ)); | |
cubicVertex.data = uMaterialIn; | |
+ cubicVertex.ambientOcclusion = ambientOcclusion; | |
rEntry.iIndex = m_meshCurrent->addVertex(cubicVertex); | |
rEntry.uMaterial = uMaterialIn; | |
+ rEntry.ambientOcclusion = ambientOcclusion; | |
return rEntry.iIndex; | |
} | |
//If we have an existing vertex and the material matches then we can return it. | |
- if (rEntry.uMaterial == uMaterialIn) | |
+ if (rEntry.uMaterial == uMaterialIn && rEntry.ambientOcclusion == ambientOcclusion) | |
{ | |
return rEntry.iIndex; | |
} | |
@@ -240,11 +268,11 @@ namespace PolyVox | |
/// | |
/// 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<typename VolumeType, typename IsQuadNeeded> | |
- Mesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicMesh(VolumeType* volData, Region region, IsQuadNeeded isQuadNeeded, bool bMergeQuads) | |
+ template<typename VolumeType, typename IsQuadNeeded, typename ContributeToAO> | |
+ Mesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicMesh(VolumeType* volData, Region region, IsQuadNeeded isQuadNeeded, ContributeToAO contributeToAO, bool bMergeQuads) | |
{ | |
Mesh< CubicVertex<typename VolumeType::VoxelType> > result; | |
- extractCubicMeshCustom(volData, region, &result, isQuadNeeded, bMergeQuads); | |
+ extractCubicMeshCustom(volData, region, &result, isQuadNeeded, contributeToAO, bMergeQuads); | |
return result; | |
} | |
@@ -261,8 +289,8 @@ namespace PolyVox | |
/// Note: This function is called 'extractCubicMeshCustom' rather than 'extractCubicMesh' to avoid ambiguity when only three parameters | |
/// are provided (would the third parameter be a controller or a mesh?). It seems this can be fixed by using enable_if/static_assert to emulate concepts, | |
/// but this is relatively complex and I haven't done it yet. Could always add it later as another overload. | |
- template<typename VolumeType, typename MeshType, typename IsQuadNeeded> | |
- void extractCubicMeshCustom(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded, bool bMergeQuads) | |
+ template<typename VolumeType, typename MeshType, typename IsQuadNeeded, typename ContributeToAO> | |
+ void extractCubicMeshCustom(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded, ContributeToAO contributeToAO, bool bMergeQuads) | |
{ | |
// This extractor has a limit as to how large the extracted region can be, because the vertex positions are encoded with a single byte per component. | |
int32_t maxReionDimensionInVoxels = 255; | |
@@ -310,73 +338,170 @@ namespace PolyVox | |
{ | |
uint32_t regX = x - region.getLowerX(); | |
+ /** | |
+ * | |
+ * | |
+ * [D] | |
+ * 8 ____________ 7 | |
+ * /| /| | |
+ * / | / | ABOVE [D] | | |
+ * / | [F] / | BELOW [C] | |
+ * 5 /___|_______/ 6 | [B] y BEHIND [F] | |
+ * [A] | |_______|___| | z BEFORE [E] / | |
+ * | 4 / | / 3 | / | |
+ * | / [E] | / | / . center | |
+ * | / | / | / | |
+ * |/__________|/ |/________ LEFT RIGHT | |
+ * 1 2 x [A] - [B] | |
+ * [C] | |
+ */ | |
+ | |
typename VolumeType::VoxelType material; //Filled in by callback | |
- typename VolumeType::VoxelType currentVoxel = volumeSampler.getVoxel(); | |
- typename VolumeType::VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz(); | |
- typename VolumeType::VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz(); | |
- typename VolumeType::VoxelType negZVoxel = volumeSampler.peekVoxel0px0py1nz(); | |
- // X | |
- if (isQuadNeeded(currentVoxel, negXVoxel, material)) | |
+ typename VolumeType::VoxelType voxelCurrent = volumeSampler.getVoxel(); | |
+ | |
+ const typename VolumeType::VoxelType voxelLeft = volumeSampler.peekVoxel1nx0py0pz(); | |
+ const typename VolumeType::VoxelType voxelBefore = volumeSampler.peekVoxel0px0py1nz(); | |
+ const typename VolumeType::VoxelType voxelLeftBefore = volumeSampler.peekVoxel1nx0py1nz(); | |
+ const typename VolumeType::VoxelType voxelRightBefore = volumeSampler.peekVoxel1px0py1nz(); | |
+ const typename VolumeType::VoxelType voxelLeftBehind = volumeSampler.peekVoxel1nx0py1pz(); | |
+ | |
+ const typename VolumeType::VoxelType voxelAboveLeft = volumeSampler.peekVoxel1nx1py0pz(); | |
+ const typename VolumeType::VoxelType voxelAboveBefore = volumeSampler.peekVoxel0px1py1nz(); | |
+ const typename VolumeType::VoxelType voxelAboveLeftBefore = volumeSampler.peekVoxel1nx1py1nz(); | |
+ const typename VolumeType::VoxelType voxelAboveRightBefore = volumeSampler.peekVoxel1px1py1nz(); | |
+ const typename VolumeType::VoxelType voxelAboveLeftBehind = volumeSampler.peekVoxel1nx1py1pz(); | |
+ | |
+ const typename VolumeType::VoxelType voxelBelow = volumeSampler.peekVoxel0px1ny0pz(); | |
+ const typename VolumeType::VoxelType voxelBelowLeft = volumeSampler.peekVoxel1nx1ny0pz(); | |
+ const typename VolumeType::VoxelType voxelBelowRight = volumeSampler.peekVoxel1px1ny0pz(); | |
+ const typename VolumeType::VoxelType voxelBelowBefore = volumeSampler.peekVoxel0px1ny1nz(); | |
+ const typename VolumeType::VoxelType voxelBelowBehind = volumeSampler.peekVoxel0px1ny1pz(); | |
+ const typename VolumeType::VoxelType voxelBelowLeftBefore = volumeSampler.peekVoxel1nx1ny1nz(); | |
+ const typename VolumeType::VoxelType voxelBelowRightBefore = volumeSampler.peekVoxel1px1ny1nz(); | |
+ const typename VolumeType::VoxelType voxelBelowLeftBehind = volumeSampler.peekVoxel1nx1ny1pz(); | |
+ const typename VolumeType::VoxelType voxelBelowRightBehind = volumeSampler.peekVoxel1px1ny1pz(); | |
+ | |
+ // X [A] LEFT | |
+ if (isQuadNeeded(voxelCurrent, voxelLeft, material)) | |
{ | |
- uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v1 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result); | |
- uint32_t v2 = addVertex(regX, regY + 1, regZ + 1, material, m_currentSliceVertices, result); | |
- uint32_t v3 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result); | |
- | |
- m_vecQuads[NegativeX][regX].push_back(Quad(v0, v1, v2, v3)); | |
+ const uint32_t v_0_1 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result, | |
+ voxelLeftBefore, voxelBelowLeft, voxelBelowLeftBefore, contributeToAO); | |
+ const uint32_t v_1_4 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result, | |
+ voxelBelowLeft, voxelLeftBehind, voxelBelowLeftBehind, contributeToAO); | |
+ const uint32_t v_2_8 = addVertex(regX, regY + 1, regZ + 1, material, m_currentSliceVertices, result, | |
+ voxelLeftBehind, voxelAboveLeft, voxelAboveLeftBehind, contributeToAO); | |
+ const uint32_t v_3_5 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result, | |
+ voxelAboveLeft, voxelLeftBefore, voxelAboveLeftBefore, contributeToAO); | |
+ m_vecQuads[NegativeX][regX].push_back(Quad(v_0_1, v_1_4, v_2_8, v_3_5)); | |
} | |
- if (isQuadNeeded(negXVoxel, currentVoxel, material)) | |
- { | |
- uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v1 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result); | |
- uint32_t v2 = addVertex(regX, regY + 1, regZ + 1, material, m_currentSliceVertices, result); | |
- uint32_t v3 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result); | |
+ // X [B] RIGHT | |
+ if (isQuadNeeded(voxelLeft, voxelCurrent, material)) { | |
+ volumeSampler.moveNegativeX(); | |
- m_vecQuads[PositiveX][regX].push_back(Quad(v0, v3, v2, v1)); | |
- } | |
+ const typename VolumeType::VoxelType _voxelRightBefore = volumeSampler.peekVoxel1px0py1nz(); | |
+ const typename VolumeType::VoxelType _voxelRightBehind = volumeSampler.peekVoxel1px0py1pz(); | |
- // Y | |
- if (isQuadNeeded(currentVoxel, negYVoxel, material)) | |
- { | |
- uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v1 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v2 = addVertex(regX + 1, regY, regZ + 1, material, m_currentSliceVertices, result); | |
- uint32_t v3 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result); | |
+ const typename VolumeType::VoxelType _voxelAboveRight = volumeSampler.peekVoxel1px1py0pz(); | |
+ const typename VolumeType::VoxelType _voxelAboveRightBefore = volumeSampler.peekVoxel1px1py1nz(); | |
+ const typename VolumeType::VoxelType _voxelAboveRightBehind = volumeSampler.peekVoxel1px1py1pz(); | |
- m_vecQuads[NegativeY][regY].push_back(Quad(v0, v1, v2, v3)); | |
- } | |
+ const typename VolumeType::VoxelType _voxelBelowRight = volumeSampler.peekVoxel1px1ny0pz(); | |
+ const typename VolumeType::VoxelType _voxelBelowRightBefore = volumeSampler.peekVoxel1px1ny1nz(); | |
+ const typename VolumeType::VoxelType _voxelBelowRightBehind = volumeSampler.peekVoxel1px1ny1pz(); | |
- if (isQuadNeeded(negYVoxel, currentVoxel, material)) | |
- { | |
- uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v1 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v2 = addVertex(regX + 1, regY, regZ + 1, material, m_currentSliceVertices, result); | |
- uint32_t v3 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result); | |
+ const uint32_t v_0_2 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result, | |
+ _voxelBelowRight, _voxelRightBefore, _voxelBelowRightBefore, contributeToAO); | |
+ const uint32_t v_1_3 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result, | |
+ _voxelBelowRight, _voxelRightBehind, _voxelBelowRightBehind, contributeToAO); | |
+ const uint32_t v_2_7 = addVertex(regX, regY + 1, regZ + 1, material, m_currentSliceVertices, result, | |
+ _voxelAboveRight, _voxelRightBehind, _voxelAboveRightBehind, contributeToAO); | |
+ const uint32_t v_3_6 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result, | |
+ _voxelAboveRight, _voxelRightBefore, _voxelAboveRightBefore, contributeToAO); | |
+ m_vecQuads[PositiveX][regX].push_back(Quad(v_0_2, v_3_6, v_2_7, v_1_3)); | |
- m_vecQuads[PositiveY][regY].push_back(Quad(v0, v3, v2, v1)); | |
+ volumeSampler.movePositiveX(); | |
} | |
- // Z | |
- if (isQuadNeeded(currentVoxel, negZVoxel, material)) | |
- { | |
- uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v1 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v2 = addVertex(regX + 1, regY + 1, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v3 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result); | |
+ // Y [C] BELOW | |
+ if (isQuadNeeded(voxelCurrent, voxelBelow, material)) { | |
+ const uint32_t v_0_1 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result, | |
+ voxelBelowBefore, voxelBelowLeft, voxelBelowLeftBefore, contributeToAO); | |
+ const uint32_t v_1_2 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result, | |
+ voxelBelowRight, voxelBelowBefore, voxelBelowRightBefore, contributeToAO); | |
+ const uint32_t v_2_3 = addVertex(regX + 1, regY, regZ + 1, material, m_currentSliceVertices, result, | |
+ voxelBelowBehind, voxelBelowRight, voxelBelowRightBehind, contributeToAO); | |
+ const uint32_t v_3_4 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result, | |
+ voxelBelowLeft, voxelBelowBehind, voxelBelowLeftBehind, contributeToAO); | |
+ m_vecQuads[NegativeY][regY].push_back(Quad(v_0_1, v_1_2, v_2_3, v_3_4)); | |
+ } | |
- m_vecQuads[NegativeZ][regZ].push_back(Quad(v0, v1, v2, v3)); | |
+ // Y [D] ABOVE | |
+ if (isQuadNeeded(voxelBelow, voxelCurrent, material)) { | |
+ volumeSampler.moveNegativeY(); | |
+ | |
+ const typename VolumeType::VoxelType _voxelAboveLeft = volumeSampler.peekVoxel1nx1py0pz(); | |
+ const typename VolumeType::VoxelType _voxelAboveRight = volumeSampler.peekVoxel1px1py0pz(); | |
+ const typename VolumeType::VoxelType _voxelAboveBefore = volumeSampler.peekVoxel0px1py1nz(); | |
+ const typename VolumeType::VoxelType _voxelAboveBehind = volumeSampler.peekVoxel0px1py1pz(); | |
+ const typename VolumeType::VoxelType _voxelAboveLeftBefore = volumeSampler.peekVoxel1nx1py1nz(); | |
+ const typename VolumeType::VoxelType _voxelAboveRightBefore = volumeSampler.peekVoxel1px1py1nz(); | |
+ const typename VolumeType::VoxelType _voxelAboveLeftBehind = volumeSampler.peekVoxel1nx1py1pz(); | |
+ const typename VolumeType::VoxelType _voxelAboveRightBehind = volumeSampler.peekVoxel1px1py1pz(); | |
+ | |
+ const uint32_t v_0_5 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result, | |
+ _voxelAboveBefore, _voxelAboveLeft, _voxelAboveLeftBefore, contributeToAO); | |
+ const uint32_t v_1_6 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result, | |
+ _voxelAboveRight, _voxelAboveBefore, _voxelAboveRightBefore, contributeToAO); | |
+ const uint32_t v_2_7 = addVertex(regX + 1, regY, regZ + 1, material, m_currentSliceVertices, result, | |
+ _voxelAboveBehind, _voxelAboveRight, _voxelAboveRightBehind, contributeToAO); | |
+ const uint32_t v_3_8 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result, | |
+ _voxelAboveLeft, _voxelAboveBehind, _voxelAboveLeftBehind, contributeToAO); | |
+ m_vecQuads[PositiveY][regY].push_back(Quad(v_0_5, v_3_8, v_2_7, v_1_6)); | |
+ | |
+ volumeSampler.movePositiveY(); | |
} | |
- if (isQuadNeeded(negZVoxel, currentVoxel, material)) | |
- { | |
- uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v1 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v2 = addVertex(regX + 1, regY + 1, regZ, material, m_previousSliceVertices, result); | |
- uint32_t v3 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result); | |
+ // Z [E] BEFORE | |
+ if (isQuadNeeded(voxelCurrent, voxelBefore, material)) { | |
+ const uint32_t v_0_1 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result, | |
+ voxelBelowBefore, voxelLeftBefore, voxelBelowLeftBefore, contributeToAO); | |
+ const uint32_t v_1_5 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result, | |
+ voxelAboveBefore, voxelLeftBefore, voxelAboveLeftBefore, contributeToAO); | |
+ const uint32_t v_2_6 = addVertex(regX + 1, regY + 1, regZ, material, m_previousSliceVertices, result, | |
+ voxelAboveBefore, voxelRightBefore, voxelAboveRightBefore, contributeToAO); | |
+ const uint32_t v_3_2 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result, | |
+ voxelBelowBefore, voxelRightBefore, voxelBelowRightBefore, contributeToAO); | |
+ m_vecQuads[NegativeZ][regZ].push_back(Quad(v_0_1, v_1_5, v_2_6, v_3_2)); | |
+ } | |
- m_vecQuads[PositiveZ][regZ].push_back(Quad(v0, v3, v2, v1)); | |
+ // Z [F] BEHIND | |
+ if (isQuadNeeded(voxelBefore, voxelCurrent, material)) { | |
+ volumeSampler.moveNegativeZ(); | |
+ | |
+ const typename VolumeType::VoxelType _voxelLeftBehind = volumeSampler.peekVoxel1nx0py1pz(); | |
+ const typename VolumeType::VoxelType _voxelRightBehind = volumeSampler.peekVoxel1px0py1pz(); | |
+ | |
+ const typename VolumeType::VoxelType _voxelAboveBehind = volumeSampler.peekVoxel0px1py1pz(); | |
+ const typename VolumeType::VoxelType _voxelAboveLeftBehind = volumeSampler.peekVoxel1nx1py1pz(); | |
+ const typename VolumeType::VoxelType _voxelAboveRightBehind = volumeSampler.peekVoxel1px1py1pz(); | |
+ | |
+ const typename VolumeType::VoxelType _voxelBelowBehind = volumeSampler.peekVoxel0px1ny1pz(); | |
+ const typename VolumeType::VoxelType _voxelBelowLeftBehind = volumeSampler.peekVoxel1nx1ny1pz(); | |
+ const typename VolumeType::VoxelType _voxelBelowRightBehind = volumeSampler.peekVoxel1px1ny1pz(); | |
+ | |
+ const uint32_t v_0_4 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result, | |
+ _voxelBelowBehind, _voxelLeftBehind, _voxelBelowLeftBehind, contributeToAO); | |
+ const uint32_t v_1_8 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result, | |
+ _voxelAboveBehind, _voxelLeftBehind, _voxelAboveLeftBehind, contributeToAO); | |
+ const uint32_t v_2_7 = addVertex(regX + 1, regY + 1, regZ, material, m_previousSliceVertices, result, | |
+ _voxelAboveBehind, _voxelRightBehind, _voxelAboveRightBehind, contributeToAO); | |
+ const uint32_t v_3_3 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result, | |
+ _voxelBelowBehind, _voxelRightBehind, _voxelBelowRightBehind, contributeToAO); | |
+ m_vecQuads[PositiveZ][regZ].push_back(Quad(v_0_4, v_3_3, v_2_7, v_1_8)); | |
+ | |
+ volumeSampler.movePositiveZ(); | |
} | |
volumeSampler.movePositiveX(); | |
@@ -405,8 +530,19 @@ namespace PolyVox | |
typename std::list<Quad>::iterator iterEnd = listQuads.end(); | |
for (typename std::list<Quad>::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++) | |
{ | |
- Quad& quad = *quadIter; | |
- result->addTriangle(quad.vertices[0], quad.vertices[1], quad.vertices[2]); | |
+ const Quad& quad = *quadIter; | |
+ const CubicVertex<typename VolumeType::VoxelType>& v00 = result->getVertex(quad.vertices[3]); | |
+ const CubicVertex<typename VolumeType::VoxelType>& v01 = result->getVertex(quad.vertices[0]); | |
+ const CubicVertex<typename VolumeType::VoxelType>& v10 = result->getVertex(quad.vertices[2]); | |
+ const CubicVertex<typename VolumeType::VoxelType>& v11 = result->getVertex(quad.vertices[1]); | |
+ | |
+ if (v00.ambientOcclusion + v11.ambientOcclusion > v01.ambientOcclusion + v10.ambientOcclusion) { | |
+ result->addTriangle(quad.vertices[1], quad.vertices[2], quad.vertices[3]); | |
+ result->addTriangle(quad.vertices[1], quad.vertices[3], quad.vertices[0]); | |
+ } else { | |
+ result->addTriangle(quad.vertices[0], quad.vertices[1], quad.vertices[2]); | |
+ result->addTriangle(quad.vertices[0], quad.vertices[2], quad.vertices[3]); | |
+ } | |
result->addTriangle(quad.vertices[0], quad.vertices[2], quad.vertices[3]); | |
} | |
} | |
diff --git a/include/PolyVox/DefaultContributeToAO.h b/include/PolyVox/DefaultContributeToAO.h | |
new file mode 100644 | |
index 0000000..5b4a94c | |
--- /dev/null | |
+++ b/include/PolyVox/DefaultContributeToAO.h | |
@@ -0,0 +1,45 @@ | |
+/******************************************************************************* | |
+* The MIT License (MIT) | |
+* | |
+* Copyright (c) 2015 David Williams and Matthew Williams | |
+* | |
+* Permission is hereby granted, free of charge, to any person obtaining a copy | |
+* of this software and associated documentation files (the "Software"), to deal | |
+* in the Software without restriction, including without limitation the rights | |
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
+* copies of the Software, and to permit persons to whom the Software is | |
+* furnished to do so, subject to the following conditions: | |
+* | |
+* The above copyright notice and this permission notice shall be included in all | |
+* copies or substantial portions of the Software. | |
+* | |
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
+* SOFTWARE. | |
+*******************************************************************************/ | |
+ | |
+#ifndef __PolyVox_DefaultContributeToAO_H__ | |
+#define __PolyVox_DefaultContributeToAO_H__ | |
+ | |
+#include "Impl/PlatformDefinitions.h" | |
+ | |
+#include <cstdint> | |
+ | |
+namespace PolyVox | |
+{ | |
+ template<typename VoxelType> | |
+ class DefaultContributeToAO | |
+ { | |
+ public: | |
+ bool operator()(VoxelType voxeltype) const | |
+ { | |
+ return voxeltype != 0; | |
+ } | |
+ }; | |
+} | |
+ | |
+#endif //__PolyVox_DefaultContributeToAO_H__ | |
diff --git a/include/PolyVox/Vertex.h b/include/PolyVox/Vertex.h | |
index 1fbf65f..ab01192 100644 | |
--- a/include/PolyVox/Vertex.h | |
+++ b/include/PolyVox/Vertex.h | |
@@ -46,6 +46,7 @@ namespace PolyVox | |
Vector3DFloat position; | |
Vector3DFloat normal; | |
+ uint8_t ambientOcclusion; | |
DataType data; | |
}; | |
} | |
-- | |
2.8.1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment