Initial changes required for Cubiquity.

This commit is contained in:
David Williams 2012-12-15 17:49:43 +01:00
parent c0d4b2a36f
commit a1ac75022c
15 changed files with 734 additions and 753 deletions

View File

@ -81,7 +81,7 @@ namespace PolyVox
struct IndexAndMaterial struct IndexAndMaterial
{ {
int32_t iIndex; int32_t iIndex;
int32_t uMaterial; //Should actually use the material type here, but this is ok for now. typename VolumeType::VoxelType uMaterial;
}; };
enum FaceNames enum FaceNames
@ -109,13 +109,12 @@ namespace PolyVox
}; };
public: public:
CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial>* result, bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial<typename VolumeType::VoxelType> >* result, bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded());
void execute(); void execute();
private: private:
int32_t addVertex(float fX, float fY, float fZ, uint32_t uMaterial, Array<3, IndexAndMaterial>& existingVertices); int32_t addVertex(float fX, float fY, float fZ, typename VolumeType::VoxelType uMaterial, Array<3, IndexAndMaterial>& existingVertices);
bool performQuadMerging(std::list<Quad>& quads); bool performQuadMerging(std::list<Quad>& quads);
bool mergeQuads(Quad& q1, Quad& q2); bool mergeQuads(Quad& q1, Quad& q2);
@ -128,7 +127,7 @@ namespace PolyVox
Region m_regSizeInVoxels; Region m_regSizeInVoxels;
//The surface patch we are currently filling. //The surface patch we are currently filling.
SurfaceMesh<PositionMaterial>* m_meshCurrent; SurfaceMesh<PositionMaterial<typename VolumeType::VoxelType> >* m_meshCurrent;
//Used to avoid creating duplicate vertices. //Used to avoid creating duplicate vertices.
Array<3, IndexAndMaterial> m_previousSliceVertices; Array<3, IndexAndMaterial> m_previousSliceVertices;

View File

@ -35,7 +35,7 @@ namespace PolyVox
const uint32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::MaxVerticesPerPosition = 6; const uint32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::MaxVerticesPerPosition = 6;
template<typename VolumeType, typename IsQuadNeeded> template<typename VolumeType, typename IsQuadNeeded>
CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial>* result, bool bMergeQuads, IsQuadNeeded isQuadNeeded) CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial<typename VolumeType::VoxelType> >* result, bool bMergeQuads, IsQuadNeeded isQuadNeeded)
:m_volData(volData) :m_volData(volData)
,m_regSizeInVoxels(region) ,m_regSizeInVoxels(region)
,m_meshCurrent(result) ,m_meshCurrent(result)
@ -58,6 +58,10 @@ namespace PolyVox
memset(m_previousSliceVertices.getRawData(), 0xff, m_previousSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial)); memset(m_previousSliceVertices.getRawData(), 0xff, m_previousSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial)); memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
uint32_t uRegionWidth = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 1;
uint32_t uRegionHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 1;
uint32_t uRegionDepth = m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 1;
m_vecQuads[NegativeX].resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2); m_vecQuads[NegativeX].resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2);
m_vecQuads[PositiveX].resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2); m_vecQuads[PositiveX].resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2);
@ -83,7 +87,7 @@ namespace PolyVox
volumeSampler.setPosition(x,y,z); volumeSampler.setPosition(x,y,z);
uint32_t material; //Filled in by callback typename VolumeType::VoxelType material; //Filled in by callback
typename VolumeType::VoxelType currentVoxel = volumeSampler.getVoxel(); typename VolumeType::VoxelType currentVoxel = volumeSampler.getVoxel();
typename VolumeType::VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz(); typename VolumeType::VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz();
typename VolumeType::VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz(); typename VolumeType::VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz();
@ -92,20 +96,20 @@ namespace PolyVox
// X // X
if(m_funcIsQuadNeededCallback(currentVoxel, negXVoxel, material)) if(m_funcIsQuadNeededCallback(currentVoxel, negXVoxel, material))
{ {
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v1 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices); uint32_t v1 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
uint32_t v2 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices); uint32_t v2 = addVertex(regX - 0.5f, regY + 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
uint32_t v3 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v3 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
m_vecQuads[NegativeX][regX].push_back(Quad(v0, v1, v2, v3)); m_vecQuads[NegativeX][regX].push_back(Quad(v0, v1, v2, v3));
} }
if(m_funcIsQuadNeededCallback(negXVoxel, currentVoxel, material)) if(m_funcIsQuadNeededCallback(negXVoxel, currentVoxel, material))
{ {
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v1 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices); uint32_t v1 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
uint32_t v2 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices); uint32_t v2 = addVertex(regX - 0.5f, regY + 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
uint32_t v3 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v3 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
m_vecQuads[PositiveX][regX].push_back(Quad(v0, v3, v2, v1)); m_vecQuads[PositiveX][regX].push_back(Quad(v0, v3, v2, v1));
} }
@ -113,20 +117,20 @@ namespace PolyVox
// Y // Y
if(m_funcIsQuadNeededCallback(currentVoxel, negYVoxel, material)) if(m_funcIsQuadNeededCallback(currentVoxel, negYVoxel, material))
{ {
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v1 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v1 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v2 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices); uint32_t v2 = addVertex(regX + 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
uint32_t v3 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices); uint32_t v3 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
m_vecQuads[NegativeY][regY].push_back(Quad(v0, v1, v2, v3)); m_vecQuads[NegativeY][regY].push_back(Quad(v0, v1, v2, v3));
} }
if(m_funcIsQuadNeededCallback(negYVoxel, currentVoxel, material)) if(m_funcIsQuadNeededCallback(negYVoxel, currentVoxel, material))
{ {
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v1 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v1 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v2 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices); uint32_t v2 = addVertex(regX + 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
uint32_t v3 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) + 0.5f, material, m_currentSliceVertices); uint32_t v3 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
m_vecQuads[PositiveY][regY].push_back(Quad(v0, v3, v2, v1)); m_vecQuads[PositiveY][regY].push_back(Quad(v0, v3, v2, v1));
} }
@ -134,20 +138,20 @@ namespace PolyVox
// Z // Z
if(m_funcIsQuadNeededCallback(currentVoxel, negZVoxel, material)) if(m_funcIsQuadNeededCallback(currentVoxel, negZVoxel, material))
{ {
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v1 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v1 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v2 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v2 = addVertex(regX + 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v3 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v3 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
m_vecQuads[NegativeZ][regZ].push_back(Quad(v0, v1, v2, v3)); m_vecQuads[NegativeZ][regZ].push_back(Quad(v0, v1, v2, v3));
} }
if(m_funcIsQuadNeededCallback(negZVoxel, currentVoxel, material)) if(m_funcIsQuadNeededCallback(negZVoxel, currentVoxel, material))
{ {
uint32_t v0 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v1 = addVertex(static_cast<float>(regX) - 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v1 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v2 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) + 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v2 = addVertex(regX + 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
uint32_t v3 = addVertex(static_cast<float>(regX) + 0.5f, static_cast<float>(regY) - 0.5f, static_cast<float>(regZ) - 0.5f, material, m_previousSliceVertices); uint32_t v3 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
m_vecQuads[PositiveZ][regZ].push_back(Quad(v0, v3, v2, v1)); m_vecQuads[PositiveZ][regZ].push_back(Quad(v0, v3, v2, v1));
} }
@ -184,7 +188,7 @@ namespace PolyVox
} }
m_meshCurrent->m_Region = m_regSizeInVoxels; m_meshCurrent->m_Region = m_regSizeInVoxels;
m_meshCurrent->removeUnusedVertices(); //m_meshCurrent->removeUnusedVertices();
m_meshCurrent->m_vecLodRecords.clear(); m_meshCurrent->m_vecLodRecords.clear();
LodRecord lodRecord; LodRecord lodRecord;
@ -194,7 +198,7 @@ namespace PolyVox
} }
template<typename VolumeType, typename IsQuadNeeded> template<typename VolumeType, typename IsQuadNeeded>
int32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::addVertex(float fX, float fY, float fZ, uint32_t uMaterialIn, Array<3, IndexAndMaterial>& existingVertices) int32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::addVertex(float fX, float fY, float fZ, typename VolumeType::VoxelType uMaterialIn, Array<3, IndexAndMaterial>& existingVertices)
{ {
uint32_t uX = static_cast<uint32_t>(fX + 0.75f); uint32_t uX = static_cast<uint32_t>(fX + 0.75f);
uint32_t uY = static_cast<uint32_t>(fY + 0.75f); uint32_t uY = static_cast<uint32_t>(fY + 0.75f);
@ -206,14 +210,14 @@ namespace PolyVox
if(rEntry.iIndex == -1) if(rEntry.iIndex == -1)
{ {
//No vertices matched and we've now hit an empty space. Fill it by creating a vertex. //No vertices matched and we've now hit an empty space. Fill it by creating a vertex.
rEntry.iIndex = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(fX, fY, fZ), uMaterialIn)); rEntry.iIndex = m_meshCurrent->addVertex(PositionMaterial<typename VolumeType::VoxelType> (Vector3DFloat(fX, fY, fZ), uMaterialIn));
rEntry.uMaterial = uMaterialIn; rEntry.uMaterial = uMaterialIn;
return rEntry.iIndex; return rEntry.iIndex;
} }
//If we have an existing vertex and the material matches then we can return it. //If we have an existing vertex and the material matches then we can return it.
if(rEntry.uMaterial == static_cast<int32_t>(uMaterialIn)) if(rEntry.uMaterial == uMaterialIn)
{ {
return rEntry.iIndex; return rEntry.iIndex;
} }
@ -260,7 +264,7 @@ namespace PolyVox
{ {
//All four vertices of a given quad have the same material, //All four vertices of a given quad have the same material,
//so just check that the first pair of vertices match. //so just check that the first pair of vertices match.
if(std::abs(m_meshCurrent->getVertices()[q1.vertices[0]].getMaterial() - m_meshCurrent->getVertices()[q2.vertices[0]].getMaterial()) < 0.001) if(m_meshCurrent->getVertices()[q1.vertices[0]].getMaterial() == m_meshCurrent->getVertices()[q2.vertices[0]].getMaterial())
{ {
//Now check whether quad 2 is adjacent to quad one by comparing vertices. //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 //Adjacent quads must share two vertices, and the second quad could be to the

View File

@ -1,50 +1,50 @@
/******************************************************************************* /*******************************************************************************
Copyright (c) 2005-2009 David Williams Copyright (c) 2005-2009 David Williams
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
arising from the use of this software. arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions: freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not 1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be in a product, an acknowledgment in the product documentation would be
appreciated but is not required. appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be 2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software. misrepresented as being the original software.
3. This notice may not be removed or altered from any source 3. This notice may not be removed or altered from any source
distribution. distribution.
*******************************************************************************/ *******************************************************************************/
#ifndef __PolyVox_DefaultIsQuadNeeded_H__ #ifndef __PolyVox_DefaultIsQuadNeeded_H__
#define __PolyVox_DefaultIsQuadNeeded_H__ #define __PolyVox_DefaultIsQuadNeeded_H__
#include "PolyVoxCore/Impl/TypeDef.h" #include "PolyVoxCore/Impl/TypeDef.h"
namespace PolyVox namespace PolyVox
{ {
template<typename VoxelType> template<typename VoxelType>
class DefaultIsQuadNeeded class DefaultIsQuadNeeded
{ {
public: public:
bool operator()(VoxelType back, VoxelType front, uint32_t& materialToUse) bool operator()(VoxelType back, VoxelType front, float& materialToUse)
{ {
if((back > 0) && (front == 0)) if((back > 0) && (front == 0))
{ {
materialToUse = static_cast<uint32_t>(back); materialToUse = static_cast<float>(back);
return true; return true;
} }
else else
{ {
return false; return false;
} }
} }
}; };
} }
#endif //__PolyVox_DefaultIsQuadNeeded_H__ #endif //__PolyVox_DefaultIsQuadNeeded_H__

View File

@ -1,148 +1,134 @@
/******************************************************************************* /*******************************************************************************
Copyright (c) 2005-2009 David Williams Copyright (c) 2005-2009 David Williams
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
arising from the use of this software. arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions: freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not 1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be in a product, an acknowledgment in the product documentation would be
appreciated but is not required. appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be 2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software. misrepresented as being the original software.
3. This notice may not be removed or altered from any source 3. This notice may not be removed or altered from any source
distribution. distribution.
*******************************************************************************/ *******************************************************************************/
#ifndef __PolyVox_MarchingCubesController_H__ #ifndef __PolyVox_MarchingCubesController_H__
#define __PolyVox_MarchingCubesController_H__ #define __PolyVox_MarchingCubesController_H__
#include "PolyVoxCore/BaseVolume.h" #include "PolyVoxCore/BaseVolume.h"
#include <limits> #include <limits>
namespace PolyVox namespace PolyVox
{ {
/** ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
* This class provides a default implementation of a controller for the MarchingCubesSurfaceExtractor. It controls the behaviour of the /// This class provides a default implementation of a controller for the MarchingCubesSurfaceExtractor. It controls the behaviour of the
* MarchingCubesSurfaceExtractor and provides the required properties from the underlying voxel type. /// MarchingCubesSurfaceExtractor and provides the required properties from the underlying voxel type.
* ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
* PolyVox does not enforce any requirements regarding what data must be present in a voxel, and instead allows any primitive or user-defined /// PolyVox does not enforce any requirements regarding what data must be present in a voxel, and instead allows any primitive or user-defined
* type to be used. However, the Marching Cubes algorithm does have some requirents about the underlying data in that conceptually it operates /// type to be used. However, the Marching Cubes algorithm does have some requirents about the underlying data in that conceptually it operates
* on a <i>density field</i>. In addition, the PolyVox implementation of the Marching Cubes algorithm also understands the idea of each voxel /// on a <i>density field</i>. In addition, the PolyVox implementation of the Marching Cubes algorithm also understands the idea of each voxel
* having a material which is copied into the vertex data. /// having a material which is copied into the vertex data.
* ///
* Because we want the MarchingCubesSurfaceExtractor to work on <i>any</i> voxel type, we use a <i>Marching Cubes controller</i> (passed as /// Because we want the MarchingCubesSurfaceExtractor to work on <i>any</i> voxel type, we use a <i>Marching Cubes controller</i> (passed as
* a parameter of the MarchingCubesSurfaceExtractor) to expose the required properties. This parameter defaults to the DefaultMarchingCubesController. /// a parameter of the MarchingCubesSurfaceExtractor) to expose the required properties. This parameter defaults to the DefaultMarchingCubesController.
* The main implementation of this class is designed to work with primitives data types, and the class is also specialised for the Material, /// The main implementation of this class is designed to work with primitives data types, and the class is also specialised for the Material,
* Density and MaterialdensityPair classes. /// Density and MaterialdensityPair classes.
* ///
* If you create a custom class for your voxel data then you probably want to include a specialisation of DefaultMarchingCubesController, /// If you create a custom class for your voxel data then you probably want to include a specialisation of DefaultMarchingCubesController,
* though you don't have to if you don't want to use the Marching Cubes algorithm or if you prefer to define a seperate Marching Cubes controller /// though you don't have to if you don't want to use the Marching Cubes algorithm or if you prefer to define a seperate Marching Cubes controller
* and pass it as an explicit parameter (rather than relying on the default). /// and pass it as an explicit parameter (rather than relying on the default).
* ///
* For primitive types, the DefaultMarchingCubesController considers the value of the voxel to represent it's density and just returns a constant /// For primitive types, the DefaultMarchingCubesController considers the value of the voxel to represent it's density and just returns a constant
* for the material. So you can, for example, run the MarchingCubesSurfaceExtractor on a volume of floats or ints. /// for the material. So you can, for example, run the MarchingCubesSurfaceExtractor on a volume of floats or ints.
* ///
* It is possible to customise the behaviour of the controller by providing a threshold value through the constructor. The extracted surface /// It is possible to customise the behaviour of the controller by providing a threshold value through the constructor. The extracted surface
* will pass through the density value specified by the threshold, and so you should make sure that the threshold value you choose is between /// will pass through the density value specified by the threshold, and so you should make sure that the threshold value you choose is between
* the minimum and maximum values found in your volume data. By default it is in the middle of the representable range of the underlying type. /// the minimum and maximum values found in your volume data. By default it is in the middle of the representable range of the underlying type.
* ///
* \sa MarchingCubesSurfaceExtractor /// \sa MarchingCubesSurfaceExtractor
* ///
*/ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename VoxelType> template<typename VoxelType>
class DefaultMarchingCubesController class DefaultMarchingCubesController
{ {
public: public:
/// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing densities. /// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing densities.
typedef VoxelType DensityType; typedef VoxelType DensityType;
/// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing materials. We're using a float here /// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing materials. We're using a float here
/// because this implementation always returns a constant value off 1.0f. PolyVox also uses floats to store the materials in the mesh vertices /// because this implementation always returns a constant value off 1.0f. PolyVox also uses floats to store the materials in the mesh vertices
/// but this is not really desirable on modern hardware. We'll probably come back to material representation in the future. /// but this is not really desirable on modern hardware. We'll probably come back to material representation in the future.
typedef float MaterialType; typedef float MaterialType;
/** ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
* Constructor /// Constructor
* ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
* This version of the constructor takes no parameters and sets the threshold to the middle of the representable range of the underlying type. /// This version of the constructor takes no parameters and sets the threshold to the middle of the representable range of the underlying type.
* For example, if the voxel type is 'uint8_t' then the representable range is 0-255, and the threshold will be set to 127. On the other hand, /// For example, if the voxel type is 'uint8_t' then the representable range is 0-255, and the threshold will be set to 127. On the other hand,
* if the voxel type is 'float' then the representable range is -FLT_MAX to FLT_MAX and the threshold will be set to zero. /// if the voxel type is 'float' then the representable range is -FLT_MAX to FLT_MAX and the threshold will be set to zero.
*/ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DefaultMarchingCubesController(void) DefaultMarchingCubesController(void)
:m_tThreshold(((std::numeric_limits<DensityType>::min)() + (std::numeric_limits<DensityType>::max)()) / 2) {
,m_eWrapMode(WrapModes::Border) m_tThreshold = ((std::numeric_limits<DensityType>::min)() + (std::numeric_limits<DensityType>::max)()) / 2;
,m_tBorder(VoxelType(0)) }
{
} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructor
/** ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
* Converts the underlying voxel type into a density value. /// This version of the constructor allows you to set a custom threshold.
* /// \param tThreshold The threshold to use.
* The default implementation of this function just returns the voxel type directly and is suitable for primitives types. Specialisations of ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
* this class can modify this behaviour. DefaultMarchingCubesController(DensityType tThreshold)
*/ {
DensityType convertToDensity(VoxelType voxel) m_tThreshold = tThreshold;
{ }
return voxel;
} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Converts the underlying voxel type into a density value.
/** ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
* Converts the underlying voxel type into a material value. /// The default implementation of this function just returns the voxel type directly and is suitable for primitives types. Specialisations of
* /// this class can modify this behaviour.
* The default implementation of this function just returns the constant '1'. There's not much else it can do, as it needs to work with primitive ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
* types and the actual value of the type is already being considered to be the density. Specialisations of this class can modify this behaviour. DensityType convertToDensity(VoxelType voxel)
*/ {
MaterialType convertToMaterial(VoxelType /*voxel*/) return voxel;
{ }
return 1;
} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Converts the underlying voxel type into a material value.
VoxelType getBorderValue(void) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{ /// The default implementation of this function just returns the constant '1'. There's not much else it can do, as it needs to work with primitive
return m_tBorder; /// types and the actual value of the type is already being considered to be the density. Specialisations of this class can modify this behaviour.
} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MaterialType convertToMaterial(VoxelType voxel)
/** {
* Returns the density value which was passed to the constructor. return 1;
* }
* As mentioned in the class description, the extracted surface will pass through the density value specified by the threshold, and so you
* should make sure that the threshold value you choose is between the minimum and maximum values found in your volume data. By default it ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
* is in the middle of the representable range of the underlying type. /// Returns the density value which was passed to the constructor.
*/ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DensityType getThreshold(void) /// As mentioned in the class description, the extracted surface will pass through the density value specified by the threshold, and so you
{ /// should make sure that the threshold value you choose is between the minimum and maximum values found in your volume data. By default it
return m_tThreshold; ///is in the middle of the representable range of the underlying type.
} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DensityType getThreshold(void)
WrapMode getWrapMode(void) {
{ return m_tThreshold;
return m_eWrapMode; }
}
private:
void setThreshold(DensityType tThreshold) DensityType m_tThreshold;
{ };
m_tThreshold = tThreshold; }
}
#endif
void setWrapMode(WrapMode eWrapMode, VoxelType tBorder = VoxelType(0))
{
m_eWrapMode = eWrapMode;
m_tBorder = tBorder;
}
private:
DensityType m_tThreshold;
WrapMode m_eWrapMode;
VoxelType m_tBorder;
};
}
#endif

View File

@ -1,82 +1,82 @@
/******************************************************************************* /*******************************************************************************
Copyright (c) 2005-2009 David Williams Copyright (c) 2005-2009 David Williams
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
arising from the use of this software. arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions: freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not 1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be in a product, an acknowledgment in the product documentation would be
appreciated but is not required. appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be 2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software. misrepresented as being the original software.
3. This notice may not be removed or altered from any source 3. This notice may not be removed or altered from any source
distribution. distribution.
*******************************************************************************/ *******************************************************************************/
#ifndef __PolyVox_Interpolation_H__ #ifndef __PolyVox_Interpolation_H__
#define __PolyVox_Interpolation_H__ #define __PolyVox_Interpolation_H__
#include <cassert> #include <cassert>
namespace PolyVox namespace PolyVox
{ {
template <typename Type> template <typename Type>
Type lerp( Type lerp(
const Type& v0,const Type& v1, const Type& v0,const Type& v1,
const float x) const float x)
{ {
assert((x >= 0.0f) && (x <= 1.0f)); assert((x >= 0.0f) && (x <= 1.0f));
//Interpolate along X //Interpolate along X
Type v0_1 = v0 + x * (v1 - v0); Type v0_1 = (v1 - v0) * x + v0;
return v0_1; return v0_1;
} }
template <typename Type> template <typename Type>
Type bilerp( Type bilerp(
const Type& v00,const Type& v10,const Type& v01,const Type& v11, const Type& v00,const Type& v10,const Type& v01,const Type& v11,
const float x, const float y) const float x, const float y)
{ {
assert((x >= 0.0f) && (y >= 0.0f) && assert((x >= 0.0f) && (y >= 0.0f) &&
(x <= 1.0f) && (y <= 1.0f)); (x <= 1.0f) && (y <= 1.0f));
// Linearly interpolate along x // Linearly interpolate along x
Type v00_10 = lerp(v00, v10, x); Type v00_10 = lerp(v00, v10, x);
Type v01_11 = lerp(v01, v11, x); Type v01_11 = lerp(v01, v11, x);
// And linearly interpolate the results along y // And linearly interpolate the results along y
Type v00_10__v01_11 = lerp(v00_10, v01_11, y); Type v00_10__v01_11 = lerp(v00_10, v01_11, y);
return v00_10__v01_11; return v00_10__v01_11;
} }
template <typename Type> template <typename Type>
Type trilerp( Type trilerp(
const Type& v000,const Type& v100,const Type& v010,const Type& v110, const Type& v000,const Type& v100,const Type& v010,const Type& v110,
const Type& v001,const Type& v101,const Type& v011,const Type& v111, const Type& v001,const Type& v101,const Type& v011,const Type& v111,
const float x, const float y, const float z) const float x, const float y, const float z)
{ {
assert((x >= 0.0f) && (y >= 0.0f) && (z >= 0.0f) && assert((x >= 0.0f) && (y >= 0.0f) && (z >= 0.0f) &&
(x <= 1.0f) && (y <= 1.0f) && (z <= 1.0f)); (x <= 1.0f) && (y <= 1.0f) && (z <= 1.0f));
// Bilinearly interpolate along Y // Bilinearly interpolate along Y
Type v000_v100__v010_v110 = bilerp(v000, v100, v010, v110, x, y); Type v000_v100__v010_v110 = bilerp(v000, v100, v010, v110, x, y);
Type v001_v101__v011_v111 = bilerp(v001, v101, v011, v111, x, y); Type v001_v101__v011_v111 = bilerp(v001, v101, v011, v111, x, y);
// And linearly interpolate the results along z // And linearly interpolate the results along z
Type v000_v100__v010_v110____v001_v101__v011_v111 = lerp(v000_v100__v010_v110, v001_v101__v011_v111, z); Type v000_v100__v010_v110____v001_v101__v011_v111 = lerp(v000_v100__v010_v110, v001_v101__v011_v111, z);
return v000_v100__v010_v110____v001_v101__v011_v111; return v000_v100__v010_v110____v001_v101__v011_v111;
} }
} }
#endif //__PolyVox_Interpolation_H__ #endif //__PolyVox_Interpolation_H__

View File

@ -1,210 +1,220 @@
/******************************************************************************* /*******************************************************************************
Copyright (c) 2005-2009 David Williams Copyright (c) 2005-2009 David Williams
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
arising from the use of this software. arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions: freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not 1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be in a product, an acknowledgment in the product documentation would be
appreciated but is not required. appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be 2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software. misrepresented as being the original software.
3. This notice may not be removed or altered from any source 3. This notice may not be removed or altered from any source
distribution. distribution.
*******************************************************************************/ *******************************************************************************/
#ifndef __PolyVox_SurfaceExtractor_H__ #ifndef __PolyVox_SurfaceExtractor_H__
#define __PolyVox_SurfaceExtractor_H__ #define __PolyVox_SurfaceExtractor_H__
#include "Impl/MarchingCubesTables.h" #include "Impl/MarchingCubesTables.h"
#include "Impl/TypeDef.h" #include "Impl/TypeDef.h"
#include "PolyVoxCore/Array.h" #include "PolyVoxCore/Array.h"
#include "PolyVoxCore/SurfaceMesh.h" #include "PolyVoxCore/SurfaceMesh.h"
#include "PolyVoxCore/DefaultMarchingCubesController.h" #include "PolyVoxCore/DefaultMarchingCubesController.h"
namespace PolyVox namespace PolyVox
{ {
template< typename VolumeType, typename Controller = DefaultMarchingCubesController<typename VolumeType::VoxelType> > template< typename VolumeType, typename Controller = DefaultMarchingCubesController<typename VolumeType::VoxelType> >
class MarchingCubesSurfaceExtractor class MarchingCubesSurfaceExtractor
{ {
public: public:
MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, Controller controller = Controller()); MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal<typename Controller::MaterialType> >* result, Controller controller = Controller());
void execute(); void execute();
private: private:
//Compute the cell bitmask for a particular slice in z. //Compute the cell bitmask for a particular slice in z.
template<bool isPrevZAvail> template<bool isPrevZAvail>
uint32_t computeBitmaskForSlice(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask); uint32_t computeBitmaskForSlice(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask);
//Compute the cell bitmask for a given cell. //Compute the cell bitmask for a given cell.
template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail> template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail>
void computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask, uint32_t uXRegSpace, uint32_t uYRegSpace); void computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask);
//Use the cell bitmasks to generate all the vertices needed for that slice //Use the cell bitmasks to generate all the vertices needed for that slice
void generateVerticesForSlice(const Array2DUint8& pCurrentBitmask, void generateVerticesForSlice(const Array2DUint8& pCurrentBitmask,
Array2DInt32& m_pCurrentVertexIndicesX, Array2DInt32& m_pCurrentVertexIndicesX,
Array2DInt32& m_pCurrentVertexIndicesY, Array2DInt32& m_pCurrentVertexIndicesY,
Array2DInt32& m_pCurrentVertexIndicesZ); Array2DInt32& m_pCurrentVertexIndicesZ);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// NOTE: These two functions are in the .h file rather than the .inl due to an apparent bug in VC2010. // NOTE: These two functions are in the .h file rather than the .inl due to an apparent bug in VC2010.
//See http://stackoverflow.com/questions/1484885/strange-vc-compile-error-c2244 for details. //See http://stackoverflow.com/questions/1484885/strange-vc-compile-error-c2244 for details.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Vector3DFloat computeCentralDifferenceGradient(const typename VolumeType::Sampler& volIter) Vector3DFloat computeCentralDifferenceGradient(const typename VolumeType::Sampler& volIter)
{ {
//FIXME - Should actually use DensityType here, both in principle and because the maths may be //FIXME - Should actually use DensityType here, both in principle and because the maths may be
//faster (and to reduce casts). So it would be good to add a way to get DensityType from a voxel. //faster (and to reduce casts). So it would be good to add a way to get DensityType from a voxel.
//But watch out for when the DensityType is unsigned and the difference could be negative. //But watch out for when the DensityType is unsigned and the difference could be negative.
float voxel1nx = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py0pz())); float voxel1nx = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py0pz()));
float voxel1px = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py0pz())); float voxel1px = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py0pz()));
float voxel1ny = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny0pz())); float voxel1ny = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny0pz()));
float voxel1py = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py0pz())); float voxel1py = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py0pz()));
float voxel1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1nz())); float voxel1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1nz()));
float voxel1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1pz())); float voxel1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1pz()));
return Vector3DFloat return Vector3DFloat
( (
voxel1nx - voxel1px, voxel1nx - voxel1px,
voxel1ny - voxel1py, voxel1ny - voxel1py,
voxel1nz - voxel1pz voxel1nz - voxel1pz
); );
} }
Vector3DFloat computeSobelGradient(const typename VolumeType::Sampler& volIter) Vector3DFloat computeSobelGradient(const typename VolumeType::Sampler& volIter)
{ {
static const int weights[3][3][3] = { { {2,3,2}, {3,6,3}, {2,3,2} }, { static const int weights[3][3][3] = { { {2,3,2}, {3,6,3}, {2,3,2} }, {
{3,6,3}, {6,0,6}, {3,6,3} }, { {2,3,2}, {3,6,3}, {2,3,2} } }; {3,6,3}, {6,0,6}, {3,6,3} }, { {2,3,2}, {3,6,3}, {2,3,2} } };
//FIXME - Should actually use DensityType here, both in principle and because the maths may be //FIXME - Should actually use DensityType here, both in principle and because the maths may be
//faster (and to reduce casts). So it would be good to add a way to get DensityType from a voxel. //faster (and to reduce casts). So it would be good to add a way to get DensityType from a voxel.
//But watch out for when the DensityType is unsigned and the difference could be negative. //But watch out for when the DensityType is unsigned and the difference could be negative.
const float pVoxel1nx1ny1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1ny1nz())); const float pVoxel1nx1ny1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1ny1nz()));
const float pVoxel1nx1ny0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1ny0pz())); const float pVoxel1nx1ny0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1ny0pz()));
const float pVoxel1nx1ny1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1ny1pz())); const float pVoxel1nx1ny1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1ny1pz()));
const float pVoxel1nx0py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py1nz())); const float pVoxel1nx0py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py1nz()));
const float pVoxel1nx0py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py0pz())); const float pVoxel1nx0py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py0pz()));
const float pVoxel1nx0py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py1pz())); const float pVoxel1nx0py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx0py1pz()));
const float pVoxel1nx1py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1py1nz())); const float pVoxel1nx1py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1py1nz()));
const float pVoxel1nx1py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1py0pz())); const float pVoxel1nx1py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1py0pz()));
const float pVoxel1nx1py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1py1pz())); const float pVoxel1nx1py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1nx1py1pz()));
const float pVoxel0px1ny1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny1nz())); const float pVoxel0px1ny1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny1nz()));
const float pVoxel0px1ny0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny0pz())); const float pVoxel0px1ny0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny0pz()));
const float pVoxel0px1ny1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny1pz())); const float pVoxel0px1ny1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1ny1pz()));
const float pVoxel0px0py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1nz())); const float pVoxel0px0py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1nz()));
//const float pVoxel0px0py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py0pz())); //const float pVoxel0px0py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py0pz()));
const float pVoxel0px0py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1pz())); const float pVoxel0px0py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px0py1pz()));
const float pVoxel0px1py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py1nz())); const float pVoxel0px1py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py1nz()));
const float pVoxel0px1py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py0pz())); const float pVoxel0px1py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py0pz()));
const float pVoxel0px1py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py1pz())); const float pVoxel0px1py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel0px1py1pz()));
const float pVoxel1px1ny1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1ny1nz())); const float pVoxel1px1ny1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1ny1nz()));
const float pVoxel1px1ny0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1ny0pz())); const float pVoxel1px1ny0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1ny0pz()));
const float pVoxel1px1ny1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1ny1pz())); const float pVoxel1px1ny1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1ny1pz()));
const float pVoxel1px0py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py1nz())); const float pVoxel1px0py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py1nz()));
const float pVoxel1px0py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py0pz())); const float pVoxel1px0py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py0pz()));
const float pVoxel1px0py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py1pz())); const float pVoxel1px0py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px0py1pz()));
const float pVoxel1px1py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1py1nz())); const float pVoxel1px1py1nz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1py1nz()));
const float pVoxel1px1py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1py0pz())); const float pVoxel1px1py0pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1py0pz()));
const float pVoxel1px1py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1py1pz())); const float pVoxel1px1py1pz = static_cast<float>(m_controller.convertToDensity(volIter.peekVoxel1px1py1pz()));
const float xGrad(- weights[0][0][0] * pVoxel1nx1ny1nz - const float xGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] * weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
pVoxel1nx1ny1pz - weights[0][1][0] * pVoxel1nx0py1nz - pVoxel1nx1ny1pz - weights[0][1][0] * pVoxel1nx0py1nz -
weights[1][1][0] * pVoxel1nx0py0pz - weights[2][1][0] * weights[1][1][0] * pVoxel1nx0py0pz - weights[2][1][0] *
pVoxel1nx0py1pz - weights[0][2][0] * pVoxel1nx1py1nz - pVoxel1nx0py1pz - weights[0][2][0] * pVoxel1nx1py1nz -
weights[1][2][0] * pVoxel1nx1py0pz - weights[2][2][0] * weights[1][2][0] * pVoxel1nx1py0pz - weights[2][2][0] *
pVoxel1nx1py1pz + weights[0][0][2] * pVoxel1px1ny1nz + pVoxel1nx1py1pz + weights[0][0][2] * pVoxel1px1ny1nz +
weights[1][0][2] * pVoxel1px1ny0pz + weights[2][0][2] * weights[1][0][2] * pVoxel1px1ny0pz + weights[2][0][2] *
pVoxel1px1ny1pz + weights[0][1][2] * pVoxel1px0py1nz + pVoxel1px1ny1pz + weights[0][1][2] * pVoxel1px0py1nz +
weights[1][1][2] * pVoxel1px0py0pz + weights[2][1][2] * weights[1][1][2] * pVoxel1px0py0pz + weights[2][1][2] *
pVoxel1px0py1pz + weights[0][2][2] * pVoxel1px1py1nz + pVoxel1px0py1pz + weights[0][2][2] * pVoxel1px1py1nz +
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] * weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
pVoxel1px1py1pz); pVoxel1px1py1pz);
const float yGrad(- weights[0][0][0] * pVoxel1nx1ny1nz - const float yGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] * weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
pVoxel1nx1ny1pz + weights[0][2][0] * pVoxel1nx1py1nz + pVoxel1nx1ny1pz + weights[0][2][0] * pVoxel1nx1py1nz +
weights[1][2][0] * pVoxel1nx1py0pz + weights[2][2][0] * weights[1][2][0] * pVoxel1nx1py0pz + weights[2][2][0] *
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz - pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz -
weights[1][0][1] * pVoxel0px1ny0pz - weights[2][0][1] * weights[1][0][1] * pVoxel0px1ny0pz - weights[2][0][1] *
pVoxel0px1ny1pz + weights[0][2][1] * pVoxel0px1py1nz + pVoxel0px1ny1pz + weights[0][2][1] * pVoxel0px1py1nz +
weights[1][2][1] * pVoxel0px1py0pz + weights[2][2][1] * weights[1][2][1] * pVoxel0px1py0pz + weights[2][2][1] *
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz - pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz -
weights[1][0][2] * pVoxel1px1ny0pz - weights[2][0][2] * weights[1][0][2] * pVoxel1px1ny0pz - weights[2][0][2] *
pVoxel1px1ny1pz + weights[0][2][2] * pVoxel1px1py1nz + pVoxel1px1ny1pz + weights[0][2][2] * pVoxel1px1py1nz +
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] * weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
pVoxel1px1py1pz); pVoxel1px1py1pz);
const float zGrad(- weights[0][0][0] * pVoxel1nx1ny1nz + const float zGrad(- weights[0][0][0] * pVoxel1nx1ny1nz +
weights[2][0][0] * pVoxel1nx1ny1pz - weights[0][1][0] * weights[2][0][0] * pVoxel1nx1ny1pz - weights[0][1][0] *
pVoxel1nx0py1nz + weights[2][1][0] * pVoxel1nx0py1pz - pVoxel1nx0py1nz + weights[2][1][0] * pVoxel1nx0py1pz -
weights[0][2][0] * pVoxel1nx1py1nz + weights[2][2][0] * weights[0][2][0] * pVoxel1nx1py1nz + weights[2][2][0] *
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz + pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz +
weights[2][0][1] * pVoxel0px1ny1pz - weights[0][1][1] * weights[2][0][1] * pVoxel0px1ny1pz - weights[0][1][1] *
pVoxel0px0py1nz + weights[2][1][1] * pVoxel0px0py1pz - pVoxel0px0py1nz + weights[2][1][1] * pVoxel0px0py1pz -
weights[0][2][1] * pVoxel0px1py1nz + weights[2][2][1] * weights[0][2][1] * pVoxel0px1py1nz + weights[2][2][1] *
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz + pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz +
weights[2][0][2] * pVoxel1px1ny1pz - weights[0][1][2] * weights[2][0][2] * pVoxel1px1ny1pz - weights[0][1][2] *
pVoxel1px0py1nz + weights[2][1][2] * pVoxel1px0py1pz - pVoxel1px0py1nz + weights[2][1][2] * pVoxel1px0py1pz -
weights[0][2][2] * pVoxel1px1py1nz + weights[2][2][2] * weights[0][2][2] * pVoxel1px1py1nz + weights[2][2][2] *
pVoxel1px1py1pz); pVoxel1px1py1pz);
//Note: The above actually give gradients going from low density to high density. //Note: The above actually give gradients going from low density to high density.
//For our normals we want the the other way around, so we switch the components as we return them. //For our normals we want the the other way around, so we switch the components as we return them.
return Vector3DFloat(-xGrad,-yGrad,-zGrad); return Vector3DFloat(-xGrad,-yGrad,-zGrad);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// End of compiler bug workaroumd. // End of compiler bug workaroumd.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//Use the cell bitmasks to generate all the indices needed for that slice //Use the cell bitmasks to generate all the indices needed for that slice
void generateIndicesForSlice(const Array2DUint8& pPreviousBitmask, void generateIndicesForSlice(const Array2DUint8& pPreviousBitmask,
const Array2DInt32& m_pPreviousVertexIndicesX, const Array2DInt32& m_pPreviousVertexIndicesX,
const Array2DInt32& m_pPreviousVertexIndicesY, const Array2DInt32& m_pPreviousVertexIndicesY,
const Array2DInt32& m_pPreviousVertexIndicesZ, const Array2DInt32& m_pPreviousVertexIndicesZ,
const Array2DInt32& m_pCurrentVertexIndicesX, const Array2DInt32& m_pCurrentVertexIndicesX,
const Array2DInt32& m_pCurrentVertexIndicesY); const Array2DInt32& m_pCurrentVertexIndicesY);
//The volume data and a sampler to access it. //The volume data and a sampler to access it.
VolumeType* m_volData; VolumeType* m_volData;
typename VolumeType::Sampler m_sampVolume; typename VolumeType::Sampler m_sampVolume;
//Used to return the number of cells in a slice which contain triangles. //Holds a position in volume space.
uint32_t m_uNoOfOccupiedCells; int32_t iXVolSpace;
int32_t iYVolSpace;
//The surface patch we are currently filling. int32_t iZVolSpace;
SurfaceMesh<PositionMaterialNormal>* m_meshCurrent;
//Holds a position in region space.
//Information about the region we are currently processing uint32_t uXRegSpace;
Region m_regSizeInVoxels; uint32_t uYRegSpace;
Region m_regSizeInCells; uint32_t uZRegSpace;
/*Region m_regSizeInVoxelsCropped;
Region m_regSizeInVoxelsUncropped; //Used to return the number of cells in a slice which contain triangles.
Region m_regVolumeCropped;*/ uint32_t m_uNoOfOccupiedCells;
Region m_regSlicePrevious;
Region m_regSliceCurrent; //The surface patch we are currently filling.
SurfaceMesh<PositionMaterialNormal<typename Controller::MaterialType> >* m_meshCurrent;
//Used to convert arbitrary voxel types in densities and materials.
Controller m_controller; //Information about the region we are currently processing
Region m_regSizeInVoxels;
//Our threshold value Region m_regSizeInCells;
typename Controller::DensityType m_tThreshold; /*Region m_regSizeInVoxelsCropped;
}; Region m_regSizeInVoxelsUncropped;
} Region m_regVolumeCropped;*/
Region m_regSlicePrevious;
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.inl" Region m_regSliceCurrent;
#endif //Our threshold value
typename Controller::DensityType m_tThreshold;
//Used to convert arbitrary voxel types in densities and materials.
Controller m_controller;
};
}
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.inl"
#endif

View File

@ -24,19 +24,18 @@ freely, subject to the following restrictions:
namespace PolyVox namespace PolyVox
{ {
template<typename VolumeType, typename Controller> template<typename VolumeType, typename Controller>
MarchingCubesSurfaceExtractor<VolumeType, Controller>::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result, Controller controller) MarchingCubesSurfaceExtractor<VolumeType, Controller>::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterialNormal<typename Controller::MaterialType> >* result, Controller controller)
:m_volData(volData) :m_volData(volData)
,m_sampVolume(volData) ,m_sampVolume(volData)
,m_meshCurrent(result) ,m_meshCurrent(result)
,m_regSizeInVoxels(region) ,m_regSizeInVoxels(region)
,m_controller(controller)
,m_tThreshold(m_controller.getThreshold())
{ {
//m_regSizeInVoxels.cropTo(m_volData->getEnclosingRegion()); //m_regSizeInVoxels.cropTo(m_volData->getEnclosingRegion());
m_regSizeInCells = m_regSizeInVoxels; m_regSizeInCells = m_regSizeInVoxels;
m_regSizeInCells.setUpperCorner(m_regSizeInCells.getUpperCorner() - Vector3DInt32(1,1,1)); m_regSizeInCells.setUpperCorner(m_regSizeInCells.getUpperCorner() - Vector3DInt32(1,1,1));
m_sampVolume.setWrapMode(m_controller.getWrapMode(), m_controller.getBorderValue()); m_controller = controller;
m_tThreshold = m_controller.getThreshold();
} }
template<typename VolumeType, typename Controller> template<typename VolumeType, typename Controller>
@ -44,9 +43,9 @@ namespace PolyVox
{ {
m_meshCurrent->clear(); m_meshCurrent->clear();
const uint32_t uArrayWidth = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 1; uint32_t uArrayWidth = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 1;
const uint32_t uArrayHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 1; uint32_t uArrayHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 1;
const uint32_t arraySizes[2]= {uArrayWidth, uArrayHeight}; // Array dimensions uint32_t arraySizes[2]= {uArrayWidth, uArrayHeight}; // Array dimensions
//For edge indices //For edge indices
Array2DInt32 m_pPreviousVertexIndicesX(arraySizes); Array2DInt32 m_pPreviousVertexIndicesX(arraySizes);
@ -137,18 +136,18 @@ namespace PolyVox
const int32_t iMaxXVolSpace = m_regSliceCurrent.getUpperCorner().getX(); const int32_t iMaxXVolSpace = m_regSliceCurrent.getUpperCorner().getX();
const int32_t iMaxYVolSpace = m_regSliceCurrent.getUpperCorner().getY(); const int32_t iMaxYVolSpace = m_regSliceCurrent.getUpperCorner().getY();
const int32_t iZVolSpace = m_regSliceCurrent.getLowerCorner().getZ(); iZVolSpace = m_regSliceCurrent.getLowerCorner().getZ();
uZRegSpace = iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ();
//Process the lower left corner //Process the lower left corner
int32_t iYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); iYVolSpace = m_regSliceCurrent.getLowerCorner().getY();
int32_t iXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); iXVolSpace = m_regSliceCurrent.getLowerCorner().getX();
uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX(); uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
uint32_t uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY(); uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace); m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
computeBitmaskForCell<false, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); computeBitmaskForCell<false, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
//Process the edge where x is minimal. //Process the edge where x is minimal.
iXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); iXVolSpace = m_regSliceCurrent.getLowerCorner().getX();
@ -160,7 +159,7 @@ namespace PolyVox
m_sampVolume.movePositiveY(); m_sampVolume.movePositiveY();
computeBitmaskForCell<false, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); computeBitmaskForCell<false, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
} }
//Process the edge where y is minimal. //Process the edge where y is minimal.
@ -173,7 +172,7 @@ namespace PolyVox
m_sampVolume.movePositiveX(); m_sampVolume.movePositiveX();
computeBitmaskForCell<true, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); computeBitmaskForCell<true, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
} }
//Process all remaining elemnents of the slice. In this case, previous x and y values are always available //Process all remaining elemnents of the slice. In this case, previous x and y values are always available
@ -187,7 +186,7 @@ namespace PolyVox
m_sampVolume.movePositiveX(); m_sampVolume.movePositiveX();
computeBitmaskForCell<true, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); computeBitmaskForCell<true, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask);
} }
} }
@ -196,7 +195,7 @@ namespace PolyVox
template<typename VolumeType, typename Controller> template<typename VolumeType, typename Controller>
template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail> template<bool isPrevXAvail, bool isPrevYAvail, bool isPrevZAvail>
void MarchingCubesSurfaceExtractor<VolumeType, Controller>::computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask, uint32_t uXRegSpace, uint32_t uYRegSpace) void MarchingCubesSurfaceExtractor<VolumeType, Controller>::computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask)
{ {
uint8_t iCubeIndex = 0; uint8_t iCubeIndex = 0;
@ -386,7 +385,7 @@ namespace PolyVox
} }
//Save the bitmask //Save the bitmask
pCurrentBitmask[uXRegSpace][uYRegSpace] = iCubeIndex; pCurrentBitmask[uXRegSpace][iYVolSpace- m_regSizeInVoxels.getLowerCorner().getY()] = iCubeIndex;
if(edgeTable[iCubeIndex] != 0) if(edgeTable[iCubeIndex] != 0)
{ {
@ -400,7 +399,7 @@ namespace PolyVox
Array2DInt32& m_pCurrentVertexIndicesY, Array2DInt32& m_pCurrentVertexIndicesY,
Array2DInt32& m_pCurrentVertexIndicesZ) Array2DInt32& m_pCurrentVertexIndicesZ)
{ {
const int32_t iZVolSpace = m_regSliceCurrent.getLowerCorner().getZ(); int32_t iZVolSpace = m_regSliceCurrent.getLowerCorner().getZ();
//Iterate over each cell in the region //Iterate over each cell in the region
for(int32_t iYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); iYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); iYVolSpace++) for(int32_t iYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); iYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); iYVolSpace++)
@ -413,7 +412,7 @@ namespace PolyVox
const uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX(); const uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
//Determine the index into the edge table which tells us which vertices are inside of the surface //Determine the index into the edge table which tells us which vertices are inside of the surface
const uint8_t iCubeIndex = pCurrentBitmask[uXRegSpace][uYRegSpace]; uint8_t iCubeIndex = pCurrentBitmask[uXRegSpace][uYRegSpace];
/* Cube is entirely in/out of the surface */ /* Cube is entirely in/out of the surface */
if (edgeTable[iCubeIndex] == 0) if (edgeTable[iCubeIndex] == 0)
@ -426,16 +425,16 @@ namespace PolyVox
m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace); m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
const typename VolumeType::VoxelType v000 = m_sampVolume.getVoxel(); const typename VolumeType::VoxelType v000 = m_sampVolume.getVoxel();
const Vector3DFloat n000 = computeCentralDifferenceGradient(m_sampVolume); const Vector3DFloat n000 = computeSobelGradient(m_sampVolume);
/* Find the vertices where the surface intersects the cube */ /* Find the vertices where the surface intersects the cube */
if (edgeTable[iCubeIndex] & 1) if (edgeTable[iCubeIndex] & 1)
{ {
m_sampVolume.movePositiveX(); m_sampVolume.movePositiveX();
const typename VolumeType::VoxelType v100 = m_sampVolume.getVoxel(); const typename VolumeType::VoxelType v100 = m_sampVolume.getVoxel();
const Vector3DFloat n100 = computeCentralDifferenceGradient(m_sampVolume); const Vector3DFloat n100 = computeSobelGradient(m_sampVolume);
const float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000)); float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000));
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()) + fInterp, static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast<float>(iZVolSpace - m_regSizeInCells.getLowerCorner().getZ())); const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()) + fInterp, static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast<float>(iZVolSpace - m_regSizeInCells.getLowerCorner().getZ()));
@ -445,12 +444,13 @@ namespace PolyVox
//Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of //Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of
//material IDs does not make sense). We take the largest, so that if we are working on a material-only //material IDs does not make sense). We take the largest, so that if we are working on a material-only
//volume we get the one which is non-zero. Both materials can be non-zero if our volume has a density component. //volume we get the one which is non-zero. Both materials can be non-zero if our volume has a density component.
const typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000); typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000);
const typename Controller::MaterialType uMaterial100 = m_controller.convertToMaterial(v100); typename Controller::MaterialType uMaterial100 = m_controller.convertToMaterial(v100);
const typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial100); //typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial100);
typename Controller::MaterialType uMaterial = m_controller.blendMaterials(uMaterial000, uMaterial100, fInterp);
const PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial)); PositionMaterialNormal<typename Controller::MaterialType> surfaceVertex(v3dPosition, v3dNormal, uMaterial);
const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex; m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
m_sampVolume.moveNegativeX(); m_sampVolume.moveNegativeX();
@ -459,9 +459,9 @@ namespace PolyVox
{ {
m_sampVolume.movePositiveY(); m_sampVolume.movePositiveY();
const typename VolumeType::VoxelType v010 = m_sampVolume.getVoxel(); const typename VolumeType::VoxelType v010 = m_sampVolume.getVoxel();
const Vector3DFloat n010 = computeCentralDifferenceGradient(m_sampVolume); const Vector3DFloat n010 = computeSobelGradient(m_sampVolume);
const float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000)); float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000));
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()) + fInterp, static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ())); const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()) + fInterp, static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ()));
@ -471,12 +471,13 @@ namespace PolyVox
//Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of //Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of
//material IDs does not make sense). We take the largest, so that if we are working on a material-only //material IDs does not make sense). We take the largest, so that if we are working on a material-only
//volume we get the one which is non-zero. Both materials can be non-zero if our volume has a density component. //volume we get the one which is non-zero. Both materials can be non-zero if our volume has a density component.
const typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000); typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000);
const typename Controller::MaterialType uMaterial010 = m_controller.convertToMaterial(v010); typename Controller::MaterialType uMaterial010 = m_controller.convertToMaterial(v010);
const typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial010); //typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial010);
typename Controller::MaterialType uMaterial = m_controller.blendMaterials(uMaterial000, uMaterial010, fInterp);
const PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial)); PositionMaterialNormal<typename Controller::MaterialType> surfaceVertex(v3dPosition, v3dNormal, uMaterial);
const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex; m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
m_sampVolume.moveNegativeY(); m_sampVolume.moveNegativeY();
@ -485,9 +486,9 @@ namespace PolyVox
{ {
m_sampVolume.movePositiveZ(); m_sampVolume.movePositiveZ();
const typename VolumeType::VoxelType v001 = m_sampVolume.getVoxel(); const typename VolumeType::VoxelType v001 = m_sampVolume.getVoxel();
const Vector3DFloat n001 = computeCentralDifferenceGradient(m_sampVolume); const Vector3DFloat n001 = computeSobelGradient(m_sampVolume);
const float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000)); float fInterp = static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000));
const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ()) + fInterp); const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ()) + fInterp);
@ -497,12 +498,13 @@ namespace PolyVox
//Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of //Choose one of the two materials to use for the vertex (we don't interpolate as interpolation of
//material IDs does not make sense). We take the largest, so that if we are working on a material-only //material IDs does not make sense). We take the largest, so that if we are working on a material-only
//volume we get the one which is non-zero. Both materials can be non-zero if our volume has a density component. //volume we get the one which is non-zero. Both materials can be non-zero if our volume has a density component.
const typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000); typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000);
const typename Controller::MaterialType uMaterial001 = m_controller.convertToMaterial(v001); typename Controller::MaterialType uMaterial001 = m_controller.convertToMaterial(v001);
const typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial001); //typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial001);
typename Controller::MaterialType uMaterial = m_controller.blendMaterials(uMaterial000, uMaterial001, fInterp);
const PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial)); PositionMaterialNormal<typename Controller::MaterialType> surfaceVertex(v3dPosition, v3dNormal, uMaterial);
const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex; m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
m_sampVolume.moveNegativeZ(); m_sampVolume.moveNegativeZ();
@ -525,12 +527,11 @@ namespace PolyVox
indlist[i] = -1; indlist[i] = -1;
} }
const int32_t iZVolSpace = m_regSlicePrevious.getLowerCorner().getZ();
for(int32_t iYVolSpace = m_regSlicePrevious.getLowerCorner().getY(); iYVolSpace <= m_regSizeInCells.getUpperCorner().getY(); iYVolSpace++) for(int32_t iYVolSpace = m_regSlicePrevious.getLowerCorner().getY(); iYVolSpace <= m_regSizeInCells.getUpperCorner().getY(); iYVolSpace++)
{ {
for(int32_t iXVolSpace = m_regSlicePrevious.getLowerCorner().getX(); iXVolSpace <= m_regSizeInCells.getUpperCorner().getX(); iXVolSpace++) for(int32_t iXVolSpace = m_regSlicePrevious.getLowerCorner().getX(); iXVolSpace <= m_regSizeInCells.getUpperCorner().getX(); iXVolSpace++)
{ {
int32_t iZVolSpace = m_regSlicePrevious.getLowerCorner().getZ();
m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace); m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
//Current position //Current position
@ -538,7 +539,7 @@ namespace PolyVox
const uint32_t uYRegSpace = m_sampVolume.getPosition().getY() - m_regSizeInVoxels.getLowerCorner().getY(); const uint32_t uYRegSpace = m_sampVolume.getPosition().getY() - m_regSizeInVoxels.getLowerCorner().getY();
//Determine the index into the edge table which tells us which vertices are inside of the surface //Determine the index into the edge table which tells us which vertices are inside of the surface
const uint8_t iCubeIndex = pPreviousBitmask[uXRegSpace][uYRegSpace]; uint8_t iCubeIndex = pPreviousBitmask[uXRegSpace][uYRegSpace];
/* Cube is entirely in/out of the surface */ /* Cube is entirely in/out of the surface */
if (edgeTable[iCubeIndex] == 0) if (edgeTable[iCubeIndex] == 0)
@ -610,9 +611,9 @@ namespace PolyVox
for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3) for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3)
{ {
const int32_t ind0 = indlist[triTable[iCubeIndex][i ]]; int32_t ind0 = indlist[triTable[iCubeIndex][i ]];
const int32_t ind1 = indlist[triTable[iCubeIndex][i+1]]; int32_t ind1 = indlist[triTable[iCubeIndex][i+1]];
const int32_t ind2 = indlist[triTable[iCubeIndex][i+2]]; int32_t ind2 = indlist[triTable[iCubeIndex][i+2]];
if((ind0 != -1) && (ind1 != -1) && (ind2 != -1)) if((ind0 != -1) && (ind1 != -1) && (ind2 != -1))
{ {

View File

@ -110,12 +110,12 @@ namespace PolyVox
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// PositionMaterial // PositionMaterial
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class PositionMaterial; template<typename MaterialType> class PositionMaterial;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// PositionMaterialNormal // PositionMaterialNormal
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class PositionMaterialNormal; template<typename MaterialType> class PositionMaterialNormal;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// RawVolume // RawVolume

View File

@ -95,8 +95,8 @@ namespace PolyVox
std::vector<LodRecord> m_vecLodRecords; std::vector<LodRecord> m_vecLodRecords;
}; };
template <typename VertexType> /*template <typename VertexType>
polyvox_shared_ptr< SurfaceMesh<VertexType> > extractSubset(SurfaceMesh<VertexType>& inputMesh, std::set<uint8_t> setMaterials); polyvox_shared_ptr< SurfaceMesh<VertexType> > extractSubset(SurfaceMesh<VertexType>& inputMesh, std::set<uint8_t> setMaterials);*/
} }
#include "PolyVoxCore/SurfaceMesh.inl" #include "PolyVoxCore/SurfaceMesh.inl"

View File

@ -365,7 +365,7 @@ namespace PolyVox
void SurfaceMesh<VertexType>::removeUnusedVertices(void) void SurfaceMesh<VertexType>::removeUnusedVertices(void)
{ {
std::vector<bool> isVertexUsed(m_vecVertices.size()); std::vector<bool> isVertexUsed(m_vecVertices.size());
fill(isVertexUsed.begin(), isVertexUsed.end(), false); std::fill(isVertexUsed.begin(), isVertexUsed.end(), false);
for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt++) for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt++)
{ {
@ -394,7 +394,7 @@ namespace PolyVox
} }
//Currently a free function - think where this needs to go. //Currently a free function - think where this needs to go.
template <typename VertexType> /*template <typename VertexType>
polyvox_shared_ptr< SurfaceMesh<VertexType> > extractSubset(SurfaceMesh<VertexType>& inputMesh, std::set<uint8_t> setMaterials) polyvox_shared_ptr< SurfaceMesh<VertexType> > extractSubset(SurfaceMesh<VertexType>& inputMesh, std::set<uint8_t> setMaterials)
{ {
polyvox_shared_ptr< SurfaceMesh<VertexType> > result(new SurfaceMesh<VertexType>); polyvox_shared_ptr< SurfaceMesh<VertexType> > result(new SurfaceMesh<VertexType>);
@ -460,7 +460,7 @@ namespace PolyVox
result->m_vecLodRecords.push_back(lodRecord); result->m_vecLodRecords.push_back(lodRecord);
return result; return result;
} }*/
template <typename VertexType> template <typename VertexType>
void SurfaceMesh<VertexType>::scaleVertices(float amount) void SurfaceMesh<VertexType>::scaleVertices(float amount)

View File

@ -54,7 +54,7 @@ namespace PolyVox
Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y) Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y)
{ {
#ifndef SWIGPYTHON // SWIG instantiates all constructors, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it? #ifndef SWIGPYTHON // SWIG instantiates all constructors, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it?
static_assert(Size == 2, "This constructor should only be used for vectors with two elements."); //static_assert(Size == 2, "This constructor should only be used for vectors with two elements.");
#endif #endif
m_tElements[0] = x; m_tElements[0] = x;
@ -71,7 +71,7 @@ namespace PolyVox
Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y, StorageType z) Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y, StorageType z)
{ {
#ifndef SWIGPYTHON // SWIG instantiates all constructors, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it? #ifndef SWIGPYTHON // SWIG instantiates all constructors, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it?
static_assert(Size == 3, "This constructor should only be used for vectors with three elements."); //static_assert(Size == 3, "This constructor should only be used for vectors with three elements.");
#endif #endif
m_tElements[0] = x; m_tElements[0] = x;
@ -91,7 +91,7 @@ namespace PolyVox
Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y, StorageType z, StorageType w) Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y, StorageType z, StorageType w)
{ {
#ifndef SWIGPYTHON // SWIG instantiates all constructors, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it? #ifndef SWIGPYTHON // SWIG instantiates all constructors, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it?
static_assert(Size == 4, "This constructor should only be used for vectors with four elements."); //static_assert(Size == 4, "This constructor should only be used for vectors with four elements.");
#endif #endif
m_tElements[0] = x; m_tElements[0] = x;
@ -142,7 +142,7 @@ namespace PolyVox
// vector with one element, and supporting this would cause confusion over the // vector with one element, and supporting this would cause confusion over the
// behaviour of the constructor taking a single value, as this fills all elements // behaviour of the constructor taking a single value, as this fills all elements
// to that value rather than just the first one. // to that value rather than just the first one.
static_assert(Size > 1, "Vector must have a length greater than one."); //static_assert(Size > 1, "Vector must have a length greater than one.");
} }
/** /**
@ -449,7 +449,7 @@ namespace PolyVox
inline StorageType Vector<Size, StorageType, OperationType>::getZ(void) const inline StorageType Vector<Size, StorageType, OperationType>::getZ(void) const
{ {
#ifndef SWIGPYTHON // SWIG instantiates all getters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it? #ifndef SWIGPYTHON // SWIG instantiates all getters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it?
static_assert(Size >= 3, "You can only get the 'z' component from a vector with at least three elements."); //static_assert(Size >= 3, "You can only get the 'z' component from a vector with at least three elements.");
#endif #endif
return m_tElements[2]; return m_tElements[2];
@ -462,7 +462,7 @@ namespace PolyVox
inline StorageType Vector<Size, StorageType, OperationType>::getW(void) const inline StorageType Vector<Size, StorageType, OperationType>::getW(void) const
{ {
#ifndef SWIGPYTHON // SWIG instantiates all getters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it? #ifndef SWIGPYTHON // SWIG instantiates all getters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it?
static_assert(Size >= 4, "You can only get the 'w' component from a vector with at least four elements."); //static_assert(Size >= 4, "You can only get the 'w' component from a vector with at least four elements.");
#endif #endif
return m_tElements[3]; return m_tElements[3];
@ -502,7 +502,7 @@ namespace PolyVox
inline void Vector<Size,StorageType,OperationType>::setElements(StorageType x, StorageType y, StorageType z) inline void Vector<Size,StorageType,OperationType>::setElements(StorageType x, StorageType y, StorageType z)
{ {
#ifndef SWIGPYTHON // SWIG instantiates all setters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it? #ifndef SWIGPYTHON // SWIG instantiates all setters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it?
static_assert(Size >= 3, "You can only use this version of setElements() on a vector with at least three elements."); //static_assert(Size >= 3, "You can only use this version of setElements() on a vector with at least three elements.");
#endif #endif
m_tElements[0] = x; m_tElements[0] = x;
m_tElements[1] = y; m_tElements[1] = y;
@ -520,7 +520,7 @@ namespace PolyVox
inline void Vector<Size,StorageType,OperationType>::setElements(StorageType x, StorageType y, StorageType z, StorageType w) inline void Vector<Size,StorageType,OperationType>::setElements(StorageType x, StorageType y, StorageType z, StorageType w)
{ {
#ifndef SWIGPYTHON // SWIG instantiates all setters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it? #ifndef SWIGPYTHON // SWIG instantiates all setters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it?
static_assert(Size >= 4, "You can only use this version of setElements() on a vector with at least four elements."); //static_assert(Size >= 4, "You can only use this version of setElements() on a vector with at least four elements.");
#endif #endif
m_tElements[0] = x; m_tElements[0] = x;
m_tElements[1] = y; m_tElements[1] = y;
@ -553,7 +553,7 @@ namespace PolyVox
inline void Vector<Size, StorageType, OperationType>::setZ(StorageType tZ) inline void Vector<Size, StorageType, OperationType>::setZ(StorageType tZ)
{ {
#ifndef SWIGPYTHON // SWIG instantiates all setters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it? #ifndef SWIGPYTHON // SWIG instantiates all setters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it?
static_assert(Size >= 3, "You can only set the 'w' component from a vector with at least three elements."); //static_assert(Size >= 3, "You can only set the 'w' component from a vector with at least three elements.");
#endif #endif
m_tElements[2] = tZ; m_tElements[2] = tZ;
} }
@ -565,7 +565,7 @@ namespace PolyVox
inline void Vector<Size, StorageType, OperationType>::setW(StorageType tW) inline void Vector<Size, StorageType, OperationType>::setW(StorageType tW)
{ {
#ifndef SWIGPYTHON // SWIG instantiates all setters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it? #ifndef SWIGPYTHON // SWIG instantiates all setters, unless we can find a way around that. Should we use SWIGIMPORT here, and then %import this file rather then %include it?
static_assert(Size >= 4, "You can only set the 'w' component from a vector with at least four elements."); //static_assert(Size >= 4, "You can only set the 'w' component from a vector with at least four elements.");
#endif #endif
m_tElements[3] = tW; m_tElements[3] = tW;
} }

View File

@ -36,49 +36,107 @@ namespace PolyVox
#ifdef SWIG #ifdef SWIG
class PositionMaterial class PositionMaterial
#else #else
template<typename MaterialType>
class POLYVOX_API PositionMaterial class POLYVOX_API PositionMaterial
#endif #endif
{ {
public: public:
PositionMaterial(); PositionMaterial()
PositionMaterial(Vector3DFloat positionToSet, float materialToSet); {
}
float getMaterial(void) const; PositionMaterial(Vector3DFloat positionToSet, MaterialType materialToSet)
const Vector3DFloat& getPosition(void) const; :position(positionToSet)
,material(materialToSet)
{
}
void setMaterial(float materialToSet); MaterialType getMaterial(void) const
void setPosition(const Vector3DFloat& positionToSet); {
return material;
}
const Vector3DFloat& getPosition(void) const
{
return position;
}
void setMaterial(MaterialType materialToSet)
{
material = materialToSet;
}
void setPosition(const Vector3DFloat& positionToSet)
{
position = positionToSet;
}
public: public:
//Nicely fits into four floats. //Nicely fits into four floats.
Vector3DFloat position; Vector3DFloat position;
float material; MaterialType material;
}; };
#ifdef SWIG #ifdef SWIG
class PositionMaterialNormal class PositionMaterialNormal
#else #else
template<typename MaterialType>
class POLYVOX_API PositionMaterialNormal class POLYVOX_API PositionMaterialNormal
#endif #endif
{ {
public: public:
PositionMaterialNormal(); PositionMaterialNormal()
PositionMaterialNormal(Vector3DFloat positionToSet, float materialToSet); {
PositionMaterialNormal(Vector3DFloat positionToSet, Vector3DFloat normalToSet, float materialToSet); }
float getMaterial(void) const; PositionMaterialNormal(Vector3DFloat positionToSet, MaterialType materialToSet)
const Vector3DFloat& getNormal(void) const; :position(positionToSet)
const Vector3DFloat& getPosition(void) const; ,material(materialToSet)
{
}
void setMaterial(float materialToSet); PositionMaterialNormal(Vector3DFloat positionToSet, Vector3DFloat normalToSet, MaterialType materialToSet)
void setNormal(const Vector3DFloat& normalToSet); :position(positionToSet)
void setPosition(const Vector3DFloat& positionToSet); ,normal(normalToSet)
,material(materialToSet)
{
}
MaterialType getMaterial(void) const
{
return material;
}
const Vector3DFloat& getNormal(void) const
{
return normal;
}
const Vector3DFloat& getPosition(void) const
{
return position;
}
void setMaterial(MaterialType materialToSet)
{
material = materialToSet;
}
void setNormal(const Vector3DFloat& normalToSet)
{
normal = normalToSet;
}
void setPosition(const Vector3DFloat& positionToSet)
{
position = positionToSet;
}
public: public:
//Nicely fits into seven floats, meaning we //Nicely fits into seven floats, meaning we
//can squeeze in one more for material blending. //can squeeze in one more for material blending.
Vector3DFloat position; Vector3DFloat position;
Vector3DFloat normal; Vector3DFloat normal;
float material; //FIXME: This shouldn't be float on CPU? MaterialType material; //FIXME: This shouldn't be float on CPU?
}; };
} }

View File

@ -127,7 +127,7 @@ namespace PolyVox
sy = modf(sy, &dummy); sy = modf(sy, &dummy);
sz = modf(sz, &dummy); sz = modf(sz, &dummy);
typename SrcVolumeType::VoxelType tInterpolatedValue = trilerp<float>(voxel000,voxel100,voxel010,voxel110,voxel001,voxel101,voxel011,voxel111,sx,sy,sz); typename SrcVolumeType::VoxelType tInterpolatedValue = trilerp(voxel000,voxel100,voxel010,voxel110,voxel001,voxel101,voxel011,voxel111,sx,sy,sz);
typename DstVolumeType::VoxelType result = static_cast<typename DstVolumeType::VoxelType>(tInterpolatedValue); typename DstVolumeType::VoxelType result = static_cast<typename DstVolumeType::VoxelType>(tInterpolatedValue);
m_pVolDst->setVoxelAt(dx,dy,dz,result); m_pVolDst->setVoxelAt(dx,dy,dz,result);

View File

@ -1,65 +1,65 @@
/******************************************************************************* /*******************************************************************************
Copyright (c) 2005-2009 David Williams Copyright (c) 2005-2009 David Williams
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
arising from the use of this software. arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions: freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not 1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be in a product, an acknowledgment in the product documentation would be
appreciated but is not required. appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be 2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software. misrepresented as being the original software.
3. This notice may not be removed or altered from any source 3. This notice may not be removed or altered from any source
distribution. distribution.
*******************************************************************************/ *******************************************************************************/
#include "PolyVoxCore/Impl/Utility.h" #include "PolyVoxCore/Impl/Utility.h"
#include <cassert> #include <cassert>
#include <stdexcept> #include <stdexcept>
namespace PolyVox namespace PolyVox
{ {
//Note: this function only works for inputs which are a power of two and not zero //Note: this function only works for inputs which are a power of two and not zero
//If this is not the case then the output is undefined. //If this is not the case then the output is undefined.
uint8_t logBase2(uint32_t uInput) uint8_t logBase2(uint32_t uInput)
{ {
//Debug mode validation //Debug mode validation
assert(uInput != 0); assert(uInput != 0);
assert(isPowerOf2(uInput)); assert(isPowerOf2(uInput));
//Release mode validation //Release mode validation
if(uInput == 0) if(uInput == 0)
{ {
throw std::invalid_argument("Cannot compute the log of zero."); //throw std::invalid_argument("Cannot compute the log of zero.");
} }
if(!isPowerOf2(uInput)) if(!isPowerOf2(uInput))
{ {
throw std::invalid_argument("Input must be a power of two in order to compute the log."); //throw std::invalid_argument("Input must be a power of two in order to compute the log.");
} }
uint32_t uResult = 0; uint32_t uResult = 0;
while( (uInput >> uResult) != 0) while( (uInput >> uResult) != 0)
{ {
++uResult; ++uResult;
} }
return static_cast<uint8_t>(uResult-1); return static_cast<uint8_t>(uResult-1);
} }
bool isPowerOf2(uint32_t uInput) bool isPowerOf2(uint32_t uInput)
{ {
if(uInput == 0) if(uInput == 0)
return false; return false;
else else
return ((uInput & (uInput-1)) == 0); return ((uInput & (uInput-1)) == 0);
} }
} }

View File

@ -25,86 +25,9 @@ freely, subject to the following restrictions:
namespace PolyVox namespace PolyVox
{ {
PositionMaterialNormal::PositionMaterialNormal()
{
}
PositionMaterialNormal::PositionMaterialNormal(Vector3DFloat positionToSet, float materialToSet)
:position(positionToSet)
,material(materialToSet)
{
}
PositionMaterialNormal::PositionMaterialNormal(Vector3DFloat positionToSet, Vector3DFloat normalToSet, float materialToSet)
:position(positionToSet)
,normal(normalToSet)
,material(materialToSet)
{
}
float PositionMaterialNormal::getMaterial(void) const
{
return material;
}
const Vector3DFloat& PositionMaterialNormal::getNormal(void) const
{
return normal;
}
const Vector3DFloat& PositionMaterialNormal::getPosition(void) const
{
return position;
}
void PositionMaterialNormal::setMaterial(float materialToSet)
{
material = materialToSet;
}
void PositionMaterialNormal::setNormal(const Vector3DFloat& normalToSet)
{
normal = normalToSet;
}
void PositionMaterialNormal::setPosition(const Vector3DFloat& positionToSet)
{
position = positionToSet;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// PositionMaterial // PositionMaterial
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
PositionMaterial::PositionMaterial()
{
}
PositionMaterial::PositionMaterial(Vector3DFloat positionToSet, float materialToSet)
:position(positionToSet)
,material(materialToSet)
{
}
float PositionMaterial::getMaterial(void) const
{
return material;
}
const Vector3DFloat& PositionMaterial::getPosition(void) const
{
return position;
}
void PositionMaterial::setMaterial(float materialToSet)
{
material = materialToSet;
}
void PositionMaterial::setPosition(const Vector3DFloat& positionToSet)
{
position = positionToSet;
}
} }