Commit 038b8c37 authored by Pierre Kraemer's avatar Pierre Kraemer

surface render: boundary + cage generation voxellisation update

parent 130a4ba4
......@@ -42,3 +42,4 @@ TARGET_LINK_LIBRARIES( SCHNAppsD
ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/Plugins PluginsD)
ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/../../SCHNAppsPlugins ExtPluginsD)
......@@ -86,7 +86,7 @@
<item row="2" column="0" colspan="2">
<widget class="Line" name="line"/>
</item>
<item row="8" column="0" colspan="2">
<item row="9" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -131,6 +131,13 @@
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<widget class="QCheckBox" name="check_renderBoundary">
<property name="text">
<string>render boundary</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
......
......@@ -41,6 +41,7 @@ struct MapParameters
bool renderVertices;
bool renderEdges;
bool renderFaces;
bool renderBoundary;
FaceShadingStyle faceStyle;
};
......@@ -86,6 +87,7 @@ private slots:
void vboAdded(Utils::VBO* vbo);
void vboRemoved(Utils::VBO* vbo);
public slots:
// slots for Python calls
void changePositionVBO(const QString& view, const QString& map, const QString& vbo);
......@@ -95,6 +97,7 @@ public slots:
void changeRenderEdges(const QString& view, const QString& map, bool b);
void changeRenderFaces(const QString& view, const QString& map, bool b);
void changeFacesStyle(const QString& view, const QString& map, MapParameters::FaceShadingStyle style);
void changeRenderBoundary(const QString& view, const QString& map, bool b);
protected:
Surface_Render_DockTab* m_dockTab;
......
......@@ -36,6 +36,7 @@ private slots:
void renderEdgesChanged(bool b);
void renderFacesChanged(bool b);
void faceStyleChanged(QAbstractButton* b);
void renderBoundaryChanged(bool b);
private:
void addPositionVBO(QString name);
......
......@@ -25,8 +25,6 @@ bool Surface_Render_Plugin::enable()
m_phongShader->setShininess(80.0f) ;
m_simpleColorShader = new CGoGN::Utils::ShaderSimpleColor();
CGoGN::Geom::Vec4f c(0.1f, 0.1f, 0.1f, 1.0f);
m_simpleColorShader->setColor(c);
m_pointSprite = new CGoGN::Utils::PointSprite();
......@@ -79,6 +77,8 @@ void Surface_Render_Plugin::drawMap(View* view, MapHandlerGen* map)
if(p.renderEdges)
{
glLineWidth(1.0f);
CGoGN::Geom::Vec4f c(0.1f, 0.1f, 0.1f, 1.0f);
m_simpleColorShader->setColor(c);
m_simpleColorShader->setAttributePosition(p.positionVBO);
map->draw(m_simpleColorShader, CGoGN::Algo::Render::GL2::LINES);
}
......@@ -105,6 +105,14 @@ void Surface_Render_Plugin::drawMap(View* view, MapHandlerGen* map)
}
glDisable(GL_POLYGON_OFFSET_FILL);
}
if(p.renderBoundary)
{
glLineWidth(5.0f);
CGoGN::Geom::Vec4f c(0.8f, 0.8f, 0.1f, 1.0f);
m_simpleColorShader->setColor(c);
m_simpleColorShader->setAttributePosition(p.positionVBO);
map->draw(m_simpleColorShader, CGoGN::Algo::Render::GL2::BOUNDARY);
}
}
}
......@@ -300,6 +308,21 @@ void Surface_Render_Plugin::changeFacesStyle(const QString& view, const QString&
}
}
void Surface_Render_Plugin::changeRenderBoundary(const QString& view, const QString& map, bool b)
{
View* v = m_schnapps->getView(view);
MapHandlerGen* m = m_schnapps->getMap(map);
if(v && m)
{
h_viewParameterSet[v][m].renderBoundary = b;
if(v->isSelectedView())
{
if(v->isLinkedToMap(m)) v->updateGL();
if(m->isSelectedMap()) m_dockTab->updateMapParameters();
}
}
}
#ifndef DEBUG
Q_EXPORT_PLUGIN2(Surface_Render_Plugin, Surface_Render_Plugin)
#else
......
......@@ -24,6 +24,7 @@ Surface_Render_DockTab::Surface_Render_DockTab(SCHNApps* s, Surface_Render_Plugi
connect(check_renderEdges, SIGNAL(toggled(bool)), this, SLOT(renderEdgesChanged(bool)));
connect(check_renderFaces, SIGNAL(toggled(bool)), this, SLOT(renderFacesChanged(bool)));
connect(group_faceShading, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(faceStyleChanged(QAbstractButton*)));
connect(check_renderBoundary, SIGNAL(toggled(bool)), this, SLOT(renderBoundaryChanged(bool)));
}
......@@ -131,6 +132,20 @@ void Surface_Render_DockTab::faceStyleChanged(QAbstractButton* b)
}
}
void Surface_Render_DockTab::renderBoundaryChanged(bool b)
{
if(!b_updatingUI)
{
View* view = m_schnapps->getSelectedView();
MapHandlerGen* map = m_schnapps->getSelectedMap();
if(view && map)
{
m_plugin->h_viewParameterSet[view][map].renderBoundary = b;
view->updateGL();
}
}
}
......
......@@ -42,3 +42,4 @@ TARGET_LINK_LIBRARIES( SCHNApps
ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/Plugins Plugins)
ADD_SUBDIRECTORY(${SCHNApps_ROOT_DIR}/../../SCHNAppsPlugins ExtPlugins)
......@@ -116,6 +116,7 @@ public:
m_render->setPrimitiveDirty(Algo::Render::GL2::POINTS);
m_render->setPrimitiveDirty(Algo::Render::GL2::LINES);
m_render->setPrimitiveDirty(Algo::Render::GL2::TRIANGLES);
m_render->setPrimitiveDirty(Algo::Render::GL2::BOUNDARY);
}
for(unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit)
......
......@@ -32,6 +32,7 @@
#include <utility>
#include "Algo/Geometry/normal.h"
#include "Topology/generic/autoAttributeHandler.h"
namespace CGoGN
{
......
#ifndef MATRICE_H
#define MATRICE_H
#include <vector>
#include <map>
#include <stack>
#include "Geometry/bounding_box.h"
#include "Geometry/vector_gen.h"
#include "Algo/MC/image.h"
#include "types.h"
#include <vector>
#include <stack>
#include <map>
namespace CGoGN {
namespace Algo {
namespace Surface {
namespace Modelisation {
struct PFP: public PFP_STANDARD
{
// definition of the map
typedef EmbeddedMap2 MAP ;
typedef VEC3 VEC3;
};
template <typename T>
int sign(T val) {
return (T(0) < val) - (val < T(0));
}
template <typename T>
void swapMax(T& min, T& max) {
if(min>max) {
std::swap(min, max);
}
}
template <unsigned int DIM, typename T>
void swapVectorMax(Geom::Vector<DIM, T>& min, Geom::Vector<DIM, T>& max) {
if(min.dimension()==max.dimension()) {
for(unsigned int i=0; i<min.dimension(); i++) {
swapMax(min[i], max[i]);
}
}
}
class Voxellisation {
public:
Voxellisation(unsigned int taille_x, unsigned int taille_y, unsigned int taille_z, Geom::BoundingBox<Geom::Vec3f> bb)
: m_taille_x(taille_x+2), m_taille_y(taille_y+2), m_taille_z(taille_z+2),
m_bb_min(bb.min()), m_bb_max(bb.max()), m_data(m_taille_x*m_taille_y*m_taille_z, 0),
m_indexes(), m_sommets(), m_faces()
{
m_size = 0;
}
void removeVoxel(int x, int y, int z) {
if(this->m_data[(x+1) + (y+1)*m_taille_x + (z+1)*m_taille_x*m_taille_y]!=0) {
this->m_data[(x+1) + (y+1)*m_taille_x + (z+1)*m_taille_x*m_taille_y] = 0;
--m_size;
}
}
void addVoxel(int x, int y, int z, int type=1) {
if(this->m_data[(x+1) + (y+1)*m_taille_x + (z+1)*m_taille_x*m_taille_y]==0) {
this->m_data[(x+1) + (y+1)*m_taille_x + (z+1)*m_taille_x*m_taille_y] = type;
++m_size;
}
}
void addVoxel(Geom::Vec3i a, int type=1) {
if(this->m_data[(a[0]+1) + (a[1]+1)*m_taille_x + (a[2]+1)*m_taille_x*m_taille_y]==0) {
this->m_data[(a[0]+1) + (a[1]+1)*m_taille_x + (a[2]+1)*m_taille_x*m_taille_y] = type;
++m_size;
}
}
int getVoxel(int x, int y, int z) {
return m_data[(x+1) + (y+1)*m_taille_x + (z+1)*m_taille_x*m_taille_y];
}
void clear() {
m_size = 0;
m_data.clear();
m_data = std::vector<int>(m_taille_x*m_taille_y*m_taille_z, 0);
m_indexes.clear();
m_sommets.clear();
m_faces.clear();
}
int getTailleX() {
return m_taille_x;
}
int getTailleY() {
return m_taille_y;
}
int getTailleZ() {
return m_taille_z;
}
int size() {
return m_size;
}
void check(int type=1) {
int voxels = 0;
for(int i=0; i<m_taille_x; ++i) {
for(int j=0; j<m_taille_y; ++j) {
for(int k=0; k<m_taille_z; ++k) {
voxels += m_data[i+ j*m_taille_x + k*m_taille_x*m_taille_y]==type?1:0;
}
}
}
CGoGNout << "Il y a " << voxels << " voxel(s)" << CGoGNendl;
}
/*
* Fonction qui part d'un des sommets de la bounding box et qui va marquer les pixels non déjà marqués comme faisant partie de l'extérieur
* Utilisation de algorithme de croissance de région
*/
void marqueVoxelsExterieurs() {
CGoGNout << "Marquage des voxels extérieurs.." << CGoGNflush;
std::stack<Geom::Vec3i>* pile = new std::stack<Geom::Vec3i>();
Geom::Vec3i voxel_courant;
//Marquage du contour extérieur
for(int j=0; j<m_taille_y; ++j) {
for(int k=0; k<m_taille_z; ++k) {
m_data[j*m_taille_x + k*m_taille_x*m_taille_y] = 2;
m_data[m_taille_x-1 + j*m_taille_x + k*m_taille_x*m_taille_y] = 2;
}
}
for(int i=0; i<m_taille_x; ++i) {
for(int k=0; k<m_taille_z; ++k) {
m_data[i + k*m_taille_x*m_taille_y] = 2;
m_data[i + (m_taille_y-1)*m_taille_x +k*m_taille_x*m_taille_y] = 2;
}
}
for(int i=0; i<m_taille_x; ++i) {
for(int j=0; j<m_taille_y; ++j) {
m_data[i + j*m_taille_x] = 2;
m_data[i + j*m_taille_x + (m_taille_z-1)*m_taille_x*m_taille_y] = 2;
}
}
if(getVoxel(0,0,0)==0)
pile->push(Geom::Vec3i(0,0,0));
else if(getVoxel(getTailleX()-2,0,0)==0)
pile->push(Geom::Vec3i(getTailleX()-2,0,0));
else if(getVoxel(0,getTailleY()-2,0)==0)
pile->push(Geom::Vec3i(0,getTailleY()-2,0));
else if(getVoxel(0,0,getTailleZ()-2)==0)
pile->push(Geom::Vec3i(0,0,getTailleZ()-2));
else if(getVoxel(getTailleX()-2,getTailleY()-2,0)==0)
pile->push(Geom::Vec3i(getTailleX()-2,getTailleY()-2,0));
else if(getVoxel(getTailleX()-2,0,getTailleZ()-2)==0)
pile->push(Geom::Vec3i(getTailleX()-2,0,getTailleZ()-2));
else if(getVoxel(0,getTailleY()-2,getTailleZ()-2)==0)
pile->push(Geom::Vec3i(0,getTailleY()-2,getTailleZ()-2));
else if(getVoxel(getTailleX()-2,getTailleY()-2,getTailleZ()-2)==0)
pile->push(Geom::Vec3i(getTailleX()-2,getTailleY()-2,getTailleZ()-2));
while(!pile->empty()) {
//Tant qu'il y a des voxels à traiter
voxel_courant = pile->top();
pile->pop();
addVoxel(voxel_courant,2);
if(getVoxel(voxel_courant[0]+1,voxel_courant[1], voxel_courant[2])==0)
pile->push(Geom::Vec3i(voxel_courant[0]+1, voxel_courant[1], voxel_courant[2]));
if(getVoxel(voxel_courant[0]-1, voxel_courant[1], voxel_courant[2])==0)
pile->push(Geom::Vec3i(voxel_courant[0]-1, voxel_courant[1], voxel_courant[2]));
if(getVoxel(voxel_courant[0], voxel_courant[1]+1, voxel_courant[2])==0)
pile->push(Geom::Vec3i(voxel_courant[0],voxel_courant[1]+1,voxel_courant[2]));
if(getVoxel(voxel_courant[0],voxel_courant[1]-1,voxel_courant[2])==0)
pile->push(Geom::Vec3i(voxel_courant[0],voxel_courant[1]-1,voxel_courant[2]));
if(getVoxel(voxel_courant[0],voxel_courant[1],voxel_courant[2]+1)==0)
pile->push(Geom::Vec3i(voxel_courant[0],voxel_courant[1],voxel_courant[2]+1));
if(getVoxel(voxel_courant[0],voxel_courant[1],voxel_courant[2]-1)==0)
pile->push(Geom::Vec3i(voxel_courant[0],voxel_courant[1],voxel_courant[2]-1));
}
delete pile;
CGoGNout << ".. fait" << CGoGNendl;
}
void extractionBord() {
CGoGNout << "Extraction du bord.." << CGoGNflush;
int x, y, z;
float transfo_x = (m_bb_max[0]-m_bb_min[0])/(m_taille_x-2);
float transfo_y = (m_bb_max[1]-m_bb_min[1])/(m_taille_y-2);
float transfo_z = (m_bb_max[2]-m_bb_min[2])/(m_taille_z-2);
std::map<int,int>::iterator index_sommet;
for(int i=0; i<m_taille_x-2; ++i) {
for(int j=0; j<m_taille_y-2; ++j) {
for(int k=0; k<m_taille_z-2; ++k) {
if(getVoxel(i,j,k)==1) {
//Si le voxel courant intersecte le bord du maillage de base
if(getVoxel(i-1,j,k)==2) {
//Si le voxel de gauche est un voxel de l'extérieur
//Sommets formant la face : 8, 5, 4, 1
x = i-1; y = j; z = k;
for(int l=0; l<4; ++l) {
switch(l) {
case 0 :
++x;
break;
case 1 :
++z;
break;
case 2 :
++y;
break;
case 3 :
--z;
break;
}
if((index_sommet=m_indexes.find(x + y*m_taille_x + z*m_taille_x*m_taille_y))==m_indexes.end()) {
//Si le sommet n'a pas encore été ajouté
m_indexes[x + y*m_taille_x + z*m_taille_x*m_taille_y] = m_sommets.size(); //On précise l'index du nouveau sommet
m_sommets.push_back(Geom::Vec3f(m_bb_min[0]+x*transfo_x, m_bb_min[1]+y*transfo_y, m_bb_min[2]+z*transfo_z)); //On ajoute le sommet avec ses coordonnées réelles
}
if(index_sommet==m_indexes.end()) {
m_faces.push_back(m_sommets.size()-1); //On ajoute le sommet au tableau renseignant les faces
}
else {
m_faces.push_back(index_sommet->second); //On ajoute le sommet au tableau renseignant les faces
}
}
}
if(getVoxel(i+1,j,k)==2) {
//Si le voxel de droite est un voxel de l'extérieur
//Sommets formant la face : 7, 2, 3, 6
x = i+1; y = j; z = k;
for(int l=0; l<4; ++l) {
switch(l) {
case 1 :
++y;
break;
case 2 :
++z;
break;
case 3 :
--y;
break;
}
if((index_sommet=m_indexes.find(x + y*m_taille_x + z*m_taille_x*m_taille_y))==m_indexes.end()) {
//Si le sommet n'a pas encore été ajouté
m_indexes[x + y*m_taille_x + z*m_taille_x*m_taille_y] = m_sommets.size(); //On précise l'index du nouveau sommet
m_sommets.push_back(Geom::Vec3f(m_bb_min[0]+x*transfo_x, m_bb_min[1]+y*transfo_y, m_bb_min[2]+z*transfo_z)); //On ajoute le sommet avec ses coordonnées réelles
}
if(index_sommet==m_indexes.end()) {
m_faces.push_back(m_sommets.size()-1); //On ajoute le sommet au tableau renseignant les faces
}
else {
m_faces.push_back(index_sommet->second); //On ajoute le sommet au tableau renseignant les faces
}
}
}
if(getVoxel(i,j-1,k)==2) {
//Si le voxel en dessous est un voxel de l'extérieur
//Sommets formant la face : 8, 7, 6, 5
x = i; y = j-1; z = k;
for(int l=0; l<4; ++l) {
switch(l) {
case 0 :
++y;
break;
case 1 :
++x;
break;
case 2 :
++z;
break;
case 3 :
--x;
break;
}
if((index_sommet=m_indexes.find(x + y*m_taille_x + z*m_taille_x*m_taille_y))==m_indexes.end()) {
//Si le sommet n'a pas encore été ajouté
m_indexes[x + y*m_taille_x + z*m_taille_x*m_taille_y] = m_sommets.size(); //On précise l'index du nouveau sommet
m_sommets.push_back(Geom::Vec3f(m_bb_min[0]+x*transfo_x, m_bb_min[1]+y*transfo_y, m_bb_min[2]+z*transfo_z)); //On ajoute le sommet avec ses coordonnées réelles
}
if(index_sommet==m_indexes.end()) {
m_faces.push_back(m_sommets.size()-1); //On ajoute le sommet au tableau renseignant les faces
}
else {
m_faces.push_back(index_sommet->second); //On ajoute le sommet au tableau renseignant les faces
}
}
}
if(getVoxel(i,j+1,k)==2) {
//Si le voxel au dessus est un voxel de l'extérieur
//Sommets formant la face : 1, 4, 3, 2
x = i; y = j+1; z = k;
for(int l=0; l<4; ++l) {
switch(l) {
case 1 :
++z;
break;
case 2 :
++x;
break;
case 3 :
--z;
break;
}
if((index_sommet=m_indexes.find(x + y*m_taille_x + z*m_taille_x*m_taille_y))==m_indexes.end()) {
//Si le sommet n'a pas encore été ajouté
m_indexes[x + y*m_taille_x + z*m_taille_x*m_taille_y] = m_sommets.size(); //On précise l'index du nouveau sommet
m_sommets.push_back(Geom::Vec3f(m_bb_min[0]+x*transfo_x, m_bb_min[1]+y*transfo_y, m_bb_min[2]+z*transfo_z)); //On ajoute le sommet avec ses coordonnées réelles
}
if(index_sommet==m_indexes.end()) {
m_faces.push_back(m_sommets.size()-1); //On ajoute le sommet au tableau renseignant les faces
}
else {
m_faces.push_back(index_sommet->second); //On ajoute le sommet au tableau renseignant les faces
}
}
}
if(getVoxel(i,j,k-1)==2) {
//Si le voxel derrière est un voxel de l'extérieur
//Sommets formant la face : 8, 1, 2 ,7
x = i; y = j; z = k-1;
for(int l=0; l<4; ++l) {
switch(l) {
case 0 :
++z;
break;
case 1 :
++y;
break;
case 2 :
++x;
break;
case 3 :
--y;
break;
}
if((index_sommet=m_indexes.find(x + y*m_taille_x + z*m_taille_x*m_taille_y))==m_indexes.end()) {
//Si le sommet n'a pas encore été ajouté
m_indexes[x + y*m_taille_x + z*m_taille_x*m_taille_y] = m_sommets.size(); //On précise l'index du nouveau sommet
m_sommets.push_back(Geom::Vec3f(m_bb_min[0]+x*transfo_x, m_bb_min[1]+y*transfo_y, m_bb_min[2]+z*transfo_z)); //On ajoute le sommet avec ses coordonnées réelles
}
if(index_sommet==m_indexes.end()) {
m_faces.push_back(m_sommets.size()-1); //On ajoute le sommet au tableau renseignant les faces
}
else {
m_faces.push_back(index_sommet->second); //On ajoute le sommet au tableau renseignant les faces
}
}
}
if(getVoxel(i,j,k+1)==2) {
//Si le voxel devant est un voxel de l'extérieur
//Sommets formant la face : 5, 6, 3, 4
x = i; y = j; z = k+1;
for(int l=0; l<4; ++l) {
switch(l) {
case 1 :
++x;
break;
case 2 :
++y;
break;
case 3 :
--x;
break;
}
if((index_sommet=m_indexes.find(x + y*m_taille_x + z*m_taille_x*m_taille_y))==m_indexes.end()) {
//Si le sommet n'a pas encore été ajouté
m_indexes[x + y*m_taille_x + z*m_taille_x*m_taille_y] = m_sommets.size(); //On précise l'index du nouveau sommet
m_sommets.push_back(Geom::Vec3f(m_bb_min[0]+x*transfo_x, m_bb_min[1]+y*transfo_y, m_bb_min[2]+z*transfo_z)); //On ajoute le sommet avec ses coordonnées réelles
}
if(index_sommet==m_indexes.end()) {
m_faces.push_back(m_sommets.size()-1); //On ajoute le sommet au tableau renseignant les faces
}
else {
m_faces.push_back(index_sommet->second); //On ajoute le sommet au tableau renseignant les faces
}
}
}
}
}
}
}
CGoGNout << ".. fait. " << m_faces.size()/4. << " faces représentant le bord." << CGoGNendl;
}
int getNbSommets() { return m_sommets.size(); }
int getNbFaces() { return m_faces.size()/4; }
private:
int m_size;
int m_taille_x;
int m_taille_y;
int m_taille_z;
Geom::Vec3f m_bb_min;
Geom::Vec3f m_bb_max;
std::vector<int> m_data; //Vecteur renseignant l'ensemble des voxels entourant le maillage
std::map<int,int> m_indexes; //Hashmap qui permet de vérifier si un sommet a déjà été ajouté à la liste des sommets
public:
std::vector<Geom::Vec3f> m_sommets; //Vecteur renseignant les coordonnées réelles des sommets de la surface
std::vector<int> m_faces; //Vecteur renseignant les sommets attribués à chaque face
Voxellisation(Geom::Vec3i resolutions= Geom::Vec3i(), Geom::BoundingBox<Geom::Vec3f> bb=Geom::BoundingBox<PFP::VEC3>())
: m_taille_x(resolutions[0]+2), m_taille_y(resolutions[1]+2), m_taille_z(resolutions[2]+2),
m_bb_min(bb.min()), m_bb_max(bb.max()), m_data(m_taille_x*m_taille_y*m_taille_z, 0),
m_indexes(), m_sommets(), m_faces(), m_transfo(3)
{
m_size = 0;
m_dilatations = 0;
m_transfo[0] = (m_bb_max[0]-m_bb_min[0])/(m_taille_x-2);
m_transfo[1] = (m_bb_max[1]-m_bb_min[1])/(m_taille_y-2);
m_transfo[2] = (m_bb_max[2]-m_bb_min[2])/(m_taille_z-2);
}
void removeVoxel(int x, int y, int z) {
if(x>=0 && y>=0 && z>=0 && x<m_taille_x-1 && y<m_taille_y-1 && z<m_taille_z-1) {
if(this->m_data[(x+1) + (y+1)*m_taille_x + (z+1)*m_taille_x*m_taille_y]!=0) --m_size;
this->m_data[(x+1) + (y+1)*m_taille_x + (z+1)*m_taille_x*m_taille_y] = 0;
}
}
void addVoxel(int x, int y, int z, int type=1) {
if(x>=-1 && y>=-1 && z>=-1 && x<m_taille_x-1 && y<m_taille_y-1 && z<m_taille_z-1) {
if(this->m_data[(x+1) + (y+1)*m_taille_x + (z+1)*m_taille_x*m_taille_y]==0 && type==1) ++m_size;
this->m_data[(x+1) + (y+1)*m_taille_x + (z+1)*m_taille_x*m_taille_y] = type;
}
}
void addVoxelRaw(int x, int y, int z, int type=1) {
if(x>=0 && y>=0 && z>=0 && x<m_taille_x && y<m_taille_y && z<m_taille_z) {
if(this->m_data[x + y*m_taille_x + z*m_taille_x*m_taille_y]==0 && type==1) ++m_size;
this->m_data[x + y*m_taille_x + z*m_taille_x*m_taille_y] = type;
}
}
void addVoxel(Geom::Vec3i a, int type=1) {
if(a[0]>=-1 && a[1]>=-1 && a[2]>=-1 && a[0]<m_taille_x-1 && a[1]<m_taille_y-1 && a[2]<m_taille_z-1) {
if(this->m_data[(a[0]+1) + (a[1]+1)*m_taille_x + (a[2]+1)*m_taille_x*m_taille_y]==0 && type==1) ++m_size;
this->m_data[(a[0]+1) + (a[1]+1)*m_taille_x + (a[2]+1)*m_taille_x*m_taille_y] = type;
}
}
void addVoxelRaw(Geom::Vec3i a, int type=1) {
if(a[0]>=0 && a[1]>=0 && a[2]>=0 && a[0]<m_taille_x && a[1]<m_taille_y && a[2]<m_taille_z) {
if(this->m_data[a[0] + a[1]*m_taille_x + a[2]*m_taille_x*m_taille_y]==0 && type==1) ++m_size;