From 31656cb68b2b05ba63209a9b496ebe15cdb9d111 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 3 Dec 2007 22:24:48 +0000 Subject: [PATCH] Started using texture atlas instead of many small meshes. --- include/IndexedSurfacePatch.h | 12 +- include/PolyVoxSceneManager.h | 5 +- include/SurfacePatchRenderable.h | 10 +- .../programs/TextureAtlasFragmentProgram.cg | 44 ++++++ .../programs/TextureAtlasVertexProgram.cg | 138 ++++++++++++++++++ media/materials/programs/Thermite.program | 14 ++ media/materials/scripts/TextureAtlas.material | 28 ++++ source/IndexedSurfacePatch.cpp | 57 ++++++-- source/PolyVoxSceneManager.cpp | 35 +++-- source/SurfacePatchRenderable.cpp | 9 +- source/VolumeSerializer.cpp | 8 +- 11 files changed, 317 insertions(+), 43 deletions(-) create mode 100644 media/materials/programs/TextureAtlasFragmentProgram.cg create mode 100644 media/materials/programs/TextureAtlasVertexProgram.cg create mode 100644 media/materials/scripts/TextureAtlas.material diff --git a/include/IndexedSurfacePatch.h b/include/IndexedSurfacePatch.h index 638ee24b..cbf3b065 100644 --- a/include/IndexedSurfacePatch.h +++ b/include/IndexedSurfacePatch.h @@ -4,15 +4,16 @@ #include #include -#include "AbstractSurfacePatch.h" +#include "Constants.h" #include "IntegralVector3.h" #include "SurfaceTypes.h" +#include "SurfaceVertex.h" #include "VolumeIterator.h" namespace Ogre { - class IndexedSurfacePatch : public AbstractSurfacePatch + class IndexedSurfacePatch { public: IndexedSurfacePatch(); @@ -21,8 +22,11 @@ namespace Ogre void addTriangle(const SurfaceVertex& v0,const SurfaceVertex& v1,const SurfaceVertex& v2); void fillVertexAndIndexData(std::vector& vecVertices, std::vector& vecIndices); - private: - std::vector m_vecTriangleIndices; + //private: + std::vector m_vecTriangleIndices; + std::vector m_vecVertices; + + long int vertexIndices[OGRE_REGION_SIDE_LENGTH*2+1][OGRE_REGION_SIDE_LENGTH*2+1][OGRE_REGION_SIDE_LENGTH*2+1]; }; } diff --git a/include/PolyVoxSceneManager.h b/include/PolyVoxSceneManager.h index 14d579ef..b2188842 100644 --- a/include/PolyVoxSceneManager.h +++ b/include/PolyVoxSceneManager.h @@ -23,10 +23,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "OgreSceneManager.h" #include "Constants.h" +#include "IndexedSurfacePatch.h" #include "MaterialMap.h" #include "SurfacePatchRenderable.h" #include "SurfaceTriangle.h" -#include "AbstractSurfacePatch.h" +//#include "AbstractSurfacePatch.h" #include "TypeDef.h" #include "Volume.h" #include "SurfaceVertex.h" @@ -81,7 +82,7 @@ namespace Ogre void generateLevelVolume(void); - std::map generateMeshDataForRegion(uint regionX, uint regionY, uint regionZ) const; + std::map generateMeshDataForRegion(uint regionX, uint regionY, uint regionZ) const; void doRegionGrowing(uint xStart, uint yStart, uint zStart, uchar value); diff --git a/include/SurfacePatchRenderable.h b/include/SurfacePatchRenderable.h index af834960..b580338d 100644 --- a/include/SurfacePatchRenderable.h +++ b/include/SurfacePatchRenderable.h @@ -4,10 +4,12 @@ #include "Ogre.h" #include -#include "AbstractSurfacePatch.h" +//#include "AbstractSurfacePatch.h" //#include "SurfaceTriangle.h" //#include "SurfaceVertex.h" +#include "IndexedSurfacePatch.h" + namespace Ogre { //IDEA - If profiling identifies this class as a bottleneck, we could implement a memory pooling system. @@ -16,11 +18,11 @@ namespace Ogre class SurfacePatchRenderable : public SimpleRenderable { public: - SurfacePatchRenderable(AbstractSurfacePatch* patchToRender, const String& material = "BaseWhiteNoLighting"); + SurfacePatchRenderable(IndexedSurfacePatch* patchToRender, const String& material = "BaseWhiteNoLighting"); ~SurfacePatchRenderable(void); - void updateWithNewSurfacePatch(AbstractSurfacePatch* patchToRender); - void setGeometry(AbstractSurfacePatch* patchToRender); + void updateWithNewSurfacePatch(IndexedSurfacePatch* patchToRender); + void setGeometry(IndexedSurfacePatch* patchToRender); Real getSquaredViewDepth(const Camera *cam) const; Real getBoundingRadius(void) const; diff --git a/media/materials/programs/TextureAtlasFragmentProgram.cg b/media/materials/programs/TextureAtlasFragmentProgram.cg new file mode 100644 index 00000000..71a398d5 --- /dev/null +++ b/media/materials/programs/TextureAtlasFragmentProgram.cg @@ -0,0 +1,44 @@ +struct v2f +{ + float4 Position : POSITION; //in projection space + float4 Color : COLOR; + float4 TexCoords : TEXCOORD0; + float4 Normal : TEXCOORD1; + float Alpha : TEXCOORD2; +}; + +float4 main(v2f IN, uniform sampler2D colourMap : TEXUNIT0) : COLOR +{ + /*OUT.TexCoordsXY.xy = OUT.Position.xy; + OUT.TexCoordsYZ.xy = OUT.Position.yz; + OUT.TexCoordsXZ.xy = OUT.Position.xz;*/ + + /*OUT.TexCoordsXY.xy /= textureScale; + OUT.TexCoordsYZ.xy /= textureScale; + OUT.TexCoordsXZ.xy /= textureScale;*/ + + IN.TexCoords /= 16; + IN.TexCoords.x = frac(IN.TexCoords.x); + IN.TexCoords.y = frac(IN.TexCoords.y); + IN.TexCoords.z = frac(IN.TexCoords.z); + + IN.TexCoords /= 4.0; + float material = floor(IN.Alpha); + float y = floor(material / 4.0); + //float x = material - y; + float x = fmod(material,4.0); + //x = 1.0 - x; + float2 offset = float2(x,y); + offset /= 4.0; + + float3 colourMapValueXY = tex2D(colourMap, IN.TexCoords.xy + offset).rgb * abs(IN.Normal.z); + float3 colourMapValueYZ = tex2D(colourMap, IN.TexCoords.yz + offset).rgb * abs(IN.Normal.x); + float3 colourMapValueXZ = tex2D(colourMap, IN.TexCoords.xz + offset).rgb * abs(IN.Normal.y); + + float3 colourMapValue = colourMapValueXY + colourMapValueYZ + colourMapValueXZ; + + //colourMapValue /= 3.0; + + return float4(colourMapValue*IN.Color.rgb,1.0); + //return float4(1.0,0.0,0.0,1.0); +} \ No newline at end of file diff --git a/media/materials/programs/TextureAtlasVertexProgram.cg b/media/materials/programs/TextureAtlasVertexProgram.cg new file mode 100644 index 00000000..8bc0a2d9 --- /dev/null +++ b/media/materials/programs/TextureAtlasVertexProgram.cg @@ -0,0 +1,138 @@ +struct a2v +{ + float4 Position : POSITION; //in object space + float3 Normal : NORMAL; + float Alpha : TEXCOORD0; +}; + +struct v2f +{ + float4 Position : POSITION; //in projection space + float4 Color : COLOR; + float4 TexCoords : TEXCOORD0; + float4 Normal : TEXCOORD1; + float Alpha : TEXCOORD2; +}; + +struct light +{ + float4 position; + float4 diffuseColour; + float4 attenuation; +}; + +v2f doWork(a2v IN, float4x4 world, float4x4 viewProj, float4 ambient, int iNoOfLights, light lights[4]) +{ + v2f OUT; + + OUT.Position = mul(world, IN.Position); + + float3 uVec; + float3 vVec; + + IN.Normal = normalize(IN.Normal); + + /*float absX = abs(IN.Normal.x); + float absY = abs(IN.Normal.y); + float absZ = abs(IN.Normal.z); + if((absZ <= absX) && (absZ <= absY)) + { + //OUT.TexCoords.xy = OUT.Position.xy /textureScale; + uVec = float3(-IN.Normal.y, IN.Normal.x,0); + } + else if((absY <= absX) && (absY <= absZ)) + { + //OUT.TexCoords.xy = OUT.Position.xz /textureScale; + uVec = float3(-IN.Normal.z, 0, IN.Normal.x); + } + else if((absX <= absZ) && (absX <= absY)) + { + // OUT.TexCoords.xy = OUT.Position.yz /textureScale; + uVec = float3(0, -IN.Normal.z, IN.Normal.y); + } + vVec = cross(IN.Normal, uVec); + OUT.TexCoords.x = dot(OUT.Position.xyz, uVec); + OUT.TexCoords.y = dot(OUT.Position.xyz, vVec); */ + + //OUT.TexCoords.xy = OUT.Position.xy * IN.Normal.z * IN.Normal.z + OUT.Position.xz * IN.Normal.y * IN.Normal.y + OUT.Position.yz * IN.Normal.x * IN.Normal.x; + + //OUT.TexCoords.xy /= textureScale; + + /*OUT.TexCoordsXY.xy = OUT.Position.xy; + OUT.TexCoordsYZ.xy = OUT.Position.yz; + OUT.TexCoordsXZ.xy = OUT.Position.xz; + + OUT.TexCoordsXY.xy /= textureScale; + OUT.TexCoordsYZ.xy /= textureScale; + OUT.TexCoordsXZ.xy /= textureScale;*/ + + OUT.Normal = float4(IN.Normal,0.0); + + OUT.TexCoords = OUT.Position; + + + //OUT.TexCoords.xy = OUT.Position.yz /textureScale; + /*OUT.TexCoordsXY.w = 1; + OUT.TexCoordsYZ.w = 1; + OUT.TexCoordsXZ.w = 1;*/ + + OUT.Color.rgba = float4(0.0,0.0,0.0,1.0); + + for(int lightCt = 0; lightCt < iNoOfLights; lightCt++) + { + float3 L = normalize(lights[lightCt].position.xyz - OUT.Position.xyz); + //Calculate attenuation factor. + float d = distance(lights[lightCt].position.xyz, OUT.Position.xyz); + float attenuationFactor = 1.0 / (lights[lightCt].attenuation.y + lights[lightCt].attenuation.z * d + lights[lightCt].attenuation.w * d * d); + // Calculate diffuse component + float LdotN = max(dot(L, IN.Normal) , 0); + OUT.Color.rgb += lights[lightCt].diffuseColour.rgb * LdotN * attenuationFactor; + } + + OUT.Color.rgb += ambient.rgb; + + OUT.Position = mul(viewProj, OUT.Position); + + OUT.Alpha = IN.Alpha; + + return OUT; +} + +v2f OneLight(a2v IN,uniform float4x4 world, uniform float4x4 viewProj, uniform float4 ambient, uniform light light0) +{ + light lights[4]; + lights[0] = light0; + + return doWork(IN, world, viewProj, ambient, 1, lights); +} + +v2f TwoLights(a2v IN,uniform float4x4 world, uniform float4x4 viewProj, uniform float4 ambient, uniform light light0, uniform light light1) +{ + light lights[4]; + lights[0] = light0; + lights[1] = light1; + + return doWork(IN, world, viewProj, ambient, 2, lights); +} + +v2f ThreeLights(a2v IN,uniform float4x4 world, uniform float4x4 viewProj, uniform float4 ambient, uniform light light0, uniform light light1, uniform light light2) +{ + light lights[4]; + lights[0] = light0; + lights[1] = light1; + lights[2] = light2; + + return doWork(IN, world, viewProj, ambient, 3, lights); +} + +v2f FourLights(a2v IN,uniform float4x4 world, uniform float4x4 viewProj, uniform float4 ambient, uniform light light0, uniform light light1, uniform light light2, uniform light light3) +{ + light lights[4]; + lights[0] = light0; + lights[1] = light1; + lights[2] = light2; + lights[3] = light3; + + return doWork(IN, world, viewProj, ambient, 4, lights); +} + diff --git a/media/materials/programs/Thermite.program b/media/materials/programs/Thermite.program index b56e240b..7e92a559 100644 --- a/media/materials/programs/Thermite.program +++ b/media/materials/programs/Thermite.program @@ -73,4 +73,18 @@ fragment_program ColourMap2DFragmentProgram cg source ColourMap2DFragmentProgram.cg entry_point main profiles ps_1_1 arbfp1 +} + +vertex_program TextureAtlasOneLightVertexProgram cg +{ + source TextureAtlasVertexProgram.cg + entry_point OneLight + profiles vs_1_1 arbvp1 +} + +fragment_program TextureAtlasFragmentProgram cg +{ + source TextureAtlasFragmentProgram.cg + entry_point main + profiles ps_1_1 arbfp1 } \ No newline at end of file diff --git a/media/materials/scripts/TextureAtlas.material b/media/materials/scripts/TextureAtlas.material new file mode 100644 index 00000000..d4e23e2c --- /dev/null +++ b/media/materials/scripts/TextureAtlas.material @@ -0,0 +1,28 @@ +material TextureAtlasMaterial +{ + technique + { + pass + { + vertex_program_ref TextureAtlasOneLightVertexProgram + { + param_named_auto world world_matrix + param_named_auto viewProj viewproj_matrix + param_named_auto ambient ambient_light_colour + param_named_auto light0.position light_position 0 + param_named_auto light0.diffuseColour light_diffuse_colour 0 + param_named_auto light0.attenuation light_attenuation 0 + } + + fragment_program_ref TextureAtlasFragmentProgram + { + } + + texture_unit + { + texture texture_atlas.png + filtering none + } + } + } +} diff --git a/source/IndexedSurfacePatch.cpp b/source/IndexedSurfacePatch.cpp index 6d1c5519..3a3bc990 100644 --- a/source/IndexedSurfacePatch.cpp +++ b/source/IndexedSurfacePatch.cpp @@ -4,6 +4,7 @@ namespace Ogre { IndexedSurfacePatch::IndexedSurfacePatch() { + memset(vertexIndices,0xFF,sizeof(vertexIndices)); //0xFF is -1 as two's complement - this may not be portable... } IndexedSurfacePatch::~IndexedSurfacePatch() @@ -12,24 +13,60 @@ namespace Ogre void IndexedSurfacePatch::addTriangle(const SurfaceVertex& v0,const SurfaceVertex& v1,const SurfaceVertex& v2) { - SurfaceVertexIterator v0Iter = m_listVertices.insert(v0).first; - SurfaceVertexIterator v1Iter = m_listVertices.insert(v1).first; - SurfaceVertexIterator v2Iter = m_listVertices.insert(v2).first; + long int index = vertexIndices[long int(v0.getPosition().x +0.5)][long int(v0.getPosition().y +0.5)][long int(v0.getPosition().z +0.5)]; + if(index == -1) + { + m_vecVertices.push_back(v0); + m_vecTriangleIndices.push_back(m_vecVertices.size()-1); + } + else + { + m_vecTriangleIndices.push_back(index); + } - m_vecTriangleIndices.push_back(v0Iter); - m_vecTriangleIndices.push_back(v1Iter); - m_vecTriangleIndices.push_back(v2Iter); + index = vertexIndices[long int(v1.getPosition().x +0.5)][long int(v1.getPosition().y +0.5)][long int(v1.getPosition().z +0.5)]; + if(index == -1) + { + m_vecVertices.push_back(v1); + m_vecTriangleIndices.push_back(m_vecVertices.size()-1); + } + else + { + m_vecTriangleIndices.push_back(index); + } + + index = vertexIndices[long int(v2.getPosition().x +0.5)][long int(v2.getPosition().y +0.5)][long int(v2.getPosition().z +0.5)]; + if(index == -1) + { + m_vecVertices.push_back(v2); + m_vecTriangleIndices.push_back(m_vecVertices.size()-1); + } + else + { + m_vecTriangleIndices.push_back(index); + } + + + /*m_vecVertices.push_back(v0); + m_vecTriangleIndices.push_back(m_vecVertices.size()-1); + m_vecVertices.push_back(v1); + m_vecTriangleIndices.push_back(m_vecVertices.size()-1); + m_vecVertices.push_back(v2); + m_vecTriangleIndices.push_back(m_vecVertices.size()-1);*/ } void IndexedSurfacePatch::fillVertexAndIndexData(std::vector& vecVertices, std::vector& vecIndices) { - vecVertices.resize(m_listVertices.size()); - std::copy(m_listVertices.begin(), m_listVertices.end(), vecVertices.begin()); + vecVertices.resize(m_vecVertices.size()); + std::copy(m_vecVertices.begin(), m_vecVertices.end(), vecVertices.begin()); - for(std::vector::iterator iterVertices = m_vecTriangleIndices.begin(); iterVertices != m_vecTriangleIndices.end(); ++iterVertices) + vecIndices.resize(m_vecTriangleIndices.size()); + std::copy(m_vecTriangleIndices.begin(), m_vecTriangleIndices.end(), vecIndices.begin()); + + /*for(std::vector::iterator iterVertices = m_vecTriangleIndices.begin(); iterVertices != m_vecTriangleIndices.end(); ++iterVertices) { std::vector::iterator iterVertex = lower_bound(vecVertices.begin(), vecVertices.end(), **iterVertices); vecIndices.push_back(iterVertex - vecVertices.begin()); - } + }*/ } } \ No newline at end of file diff --git a/source/PolyVoxSceneManager.cpp b/source/PolyVoxSceneManager.cpp index 57ffe687..a571df0f 100644 --- a/source/PolyVoxSceneManager.cpp +++ b/source/PolyVoxSceneManager.cpp @@ -144,7 +144,7 @@ namespace Ogre //Generate the surface //std::vector< std::vector > vertexData; //std::vector< std::vector > indexData; - std::map mapSurfacePatch = generateMeshDataForRegion(regionX,regionY,regionZ); + std::map mapSurfacePatch = generateMeshDataForRegion(regionX,regionY,regionZ); //If a SceneNode doesn't exist in this position then create one. std::map::iterator iterSceneNode = sceneNodes.find(UIntVector3(regionX,regionY,regionZ)); @@ -162,7 +162,7 @@ namespace Ogre //For each surface attach it to the scene node. //for(uint meshCt = 1; meshCt < 256; ++meshCt) - for(std::map::iterator iterSurfacePatch = mapSurfacePatch.begin(); iterSurfacePatch != mapSurfacePatch.end(); ++iterSurfacePatch) + for(std::map::iterator iterSurfacePatch = mapSurfacePatch.begin(); iterSurfacePatch != mapSurfacePatch.end(); ++iterSurfacePatch) { /*std::vector vertexData; std::vector indexData; @@ -349,9 +349,11 @@ namespace Ogre } } - std::map PolyVoxSceneManager::generateMeshDataForRegion(const uint regionX, const uint regionY, const uint regionZ) const + std::map PolyVoxSceneManager::generateMeshDataForRegion(const uint regionX, const uint regionY, const uint regionZ) const { - std::map surfacePatchMapResult; + std::map surfacePatchMapResult; + + surfacePatchMapResult.insert(std::make_pair(1,new IndexedSurfacePatch)); //LogManager::getSingleton().logMessage("Generating Mesh Data"); //First and last voxels in the region @@ -509,7 +511,7 @@ namespace Ogre const uchar material1 = vertMaterials[triTable[iCubeIndex][i+1]]; const uchar material2 = vertMaterials[triTable[iCubeIndex][i+2]]; - if(surfacePatchMapResult.find(material0) == surfacePatchMapResult.end()) + /*if(surfacePatchMapResult.find(material0) == surfacePatchMapResult.end()) { surfacePatchMapResult.insert(std::make_pair(material0,new IndexedSurfacePatch)); } @@ -520,20 +522,23 @@ namespace Ogre if(surfacePatchMapResult.find(material2) == surfacePatchMapResult.end()) { surfacePatchMapResult.insert(std::make_pair(material2,new IndexedSurfacePatch)); - } + }*/ - SurfaceVertex surfaceVertex0Alpha1(vertex0,1.0); - SurfaceVertex surfaceVertex1Alpha1(vertex1,1.0); - SurfaceVertex surfaceVertex2Alpha1(vertex2,1.0); + //float materialToUse = std::max(material0,std::max(material1,material2)); + + //If all the materials are the same, we just need one triangle for that material with all the alphas set high. if((material0 == material1) && (material1 == material2)) { - surfacePatchMapResult[material0]->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + SurfaceVertex surfaceVertex0Alpha1(vertex0,material0 + 0.1); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material1 + 0.1); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material2 + 0.1); + surfacePatchMapResult[1]->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); } //If there not all the same, we need one triangle for each unique material. //We'll also need some vertices with low alphas for blending. - else + /*else { SurfaceVertex surfaceVertex0Alpha0(vertex0,0.0); SurfaceVertex surfaceVertex1Alpha0(vertex1,0.0); @@ -560,18 +565,18 @@ namespace Ogre surfacePatchMapResult[material1]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha1, surfaceVertex2Alpha0); surfacePatchMapResult[material2]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha0, surfaceVertex2Alpha1); } - } + }*/ }//For each triangle }//For each cell //FIXME - can it happen that we have no vertices or triangles? Should exit early? - for(std::map::iterator iterPatch = surfacePatchMapResult.begin(); iterPatch != surfacePatchMapResult.end(); ++iterPatch) + for(std::map::iterator iterPatch = surfacePatchMapResult.begin(); iterPatch != surfacePatchMapResult.end(); ++iterPatch) { - SurfaceVertexIterator iterSurfaceVertex = iterPatch->second->getVerticesBegin(); - while(iterSurfaceVertex != iterPatch->second->getVerticesEnd()) + std::vector::iterator iterSurfaceVertex = iterPatch->second->m_vecVertices.begin(); + while(iterSurfaceVertex != iterPatch->second->m_vecVertices.end()) { Vector3 tempNormal = computeNormal((iterSurfaceVertex->getPosition() + offset).toOgreVector3()/2.0f, CENTRAL_DIFFERENCE); const_cast(*iterSurfaceVertex).setNormal(tempNormal); diff --git a/source/SurfacePatchRenderable.cpp b/source/SurfacePatchRenderable.cpp index 2c70464d..e7811fe7 100644 --- a/source/SurfacePatchRenderable.cpp +++ b/source/SurfacePatchRenderable.cpp @@ -1,13 +1,14 @@ #include "SurfacePatchRenderable.h" #include "SurfaceEdge.h" +#include "SurfaceVertex.h" #include "OgreVertexIndexData.h" #include namespace Ogre { - SurfacePatchRenderable::SurfacePatchRenderable(AbstractSurfacePatch* patchToRender, const String& material) + SurfacePatchRenderable::SurfacePatchRenderable(IndexedSurfacePatch* patchToRender, const String& material) { //Set up what we can of the vertex data mRenderOp.vertexData = new VertexData(); @@ -40,12 +41,12 @@ namespace Ogre delete mRenderOp.indexData; } - void SurfacePatchRenderable::updateWithNewSurfacePatch(AbstractSurfacePatch* patchToRender) - { + void SurfacePatchRenderable::updateWithNewSurfacePatch(IndexedSurfacePatch* patchToRender) + { setGeometry(patchToRender); } - void SurfacePatchRenderable::setGeometry(AbstractSurfacePatch* patchToRender) + void SurfacePatchRenderable::setGeometry(IndexedSurfacePatch* patchToRender) { std::vector vecVertices; std::vector vecIndices; diff --git a/source/VolumeSerializer.cpp b/source/VolumeSerializer.cpp index 7a052707..72df3a95 100644 --- a/source/VolumeSerializer.cpp +++ b/source/VolumeSerializer.cpp @@ -61,10 +61,10 @@ namespace Ogre volIter.setVoxelAt(x,y,z,value); /*if(z < 24) { - //if(x % 32 < 16) - volIter.setVoxelAt(x,y,z,4); - //else - //volIter.setVoxelAt(x,y,z,5); + if(x % 32 < 16) + volIter.setVoxelAt(x,y,z,5); + else + volIter.setVoxelAt(x,y,z,5); } else volIter.setVoxelAt(x,y,z,0);*/