/**********************************************************************
MeshGenerator - Class to generate meshes from volumetric data
Copyright (C) 2008-2009 by Marcus D. Hanwell
This file is part of the Avogadro molecular editor project.
For more information, see
Avogadro is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
Avogadro is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
**********************************************************************/
#ifndef MESHGENERATOR_H
#define MESHGENERATOR_H
#include
#include
#include
#include
namespace Avogadro {
class Cube;
class Mesh;
/**
* @class MeshGenerator meshgenerator.h
* @brief Class that can generate Mesh objects from Cube objects.
* @author Marcus D. Hanwell
*
* This class implements a method of generating an isosurface Mesh from
* volumetric data using the marching cubes algorithm. In the case of the
* MeshGenerator class it expects a Cube as an input and an isosurface value.
* The tables and the basic code is taken from the public domain code written
* by Cory Bloyd (marchingsource.cpp) and available at,
* http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/
*
* You must first initialize the class and then call run() to actually
* polygonize the isosurface. Connect to the classes finished() signal to
* do something once the polygonization is complete.
*/
class A_EXPORT MeshGenerator : public QThread
{
public:
/**
* Constructor.
*/
explicit MeshGenerator(QObject *parent = 0);
/**
* Constructor. Can be used to initialize the MeshGenerator.
* @param cube The source Cube with the volumetric data.
* @param mesh The Mesh that will hold the isosurface.
* @param iso The iso value of the surface.
* @return True if the MeshGenerator was successfully initialized.
*/
MeshGenerator(const Cube *cube, Mesh *mesh, float iso,
bool reverse = false, QObject *parent = 0);
/**
* Destructor.
*/
~MeshGenerator();
/**
* Initialization function, set up the MeshGenerator ready to find an
* isosurface of the supplied Cube.
* @param cube The source Cube with the volumetric data.
* @param mesh The Mesh that will hold the isosurface.
* @param iso The iso value of the surface.
*/
bool initialize(const Cube *cube, Mesh *mesh, float iso,
bool reverse = false);
/**
* Use this function to begin Mesh generation. Uses an asynchronous thread,
* and so avoids locking the user interface while the isosurface is found.
*/
void run();
/**
* @return The Cube being used by the class.
*/
const Cube * cube() const { return m_cube; }
/**
* @return The Mesh being generated by the class.
*/
Mesh * mesh() const { return m_mesh; }
/**
* Clears the contents of the MeshGenerator.
*/
void clear();
protected:
/**
* Get the normal to the supplied point. This operation is quite expensive
* and so should be avoided wherever possible.
* @param pos The position of the vertex whose normal is needed.
* @return The normal vector for the supplied point.
*/
Eigen::Vector3f normal(const Eigen::Vector3f &pos);
/**
* Get the offset, i.e. the approximate point of intersection of the surface
* between two points.
* @param val1 The position of the vertex whose normal is needed.
* @return The normal vector for the supplied point.
*/
float offset(float val1, float val2);
unsigned long duplicate(const Eigen::Vector3i &c,
const Eigen::Vector3f &pos);
/**
* Perform a marching cubes step on a single cube.
*/
bool marchingCube(const Eigen::Vector3i &pos);
float m_iso; /**< The value of the isosurface. */
bool m_reverseWinding; /**< Whether the winding and normals are reversed */
const Cube *m_cube; /**< The cube that we are generating a Mesh from. */
Mesh *m_mesh; /**< The mesh that is being generated. */
float m_stepSize; /**< The step size of the cube. */
Eigen::Vector3f m_min; /**< The minimum point in the cube. */
Eigen::Vector3i m_dim; /**< The dimensions of the cube. */
std::vector m_vertices, m_normals;
std::vector m_indices;
/**
* These are the tables of constants for the marching cubes and tetrahedra
* algorithms. They are taken from the public domain source at
* http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/
*/
static const float a2fVertexOffset[8][3];
static const int a2iVertexOffset[8][3];
static const int a2iEdgeConnection[12][2];
static const float a2fEdgeDirection[12][3];
static const int a2iTetrahedronEdgeConnection[6][2];
static const int a2iTetrahedronsInACube[6][4];
static const long aiTetrahedronEdgeFlags[16];
static const int a2iTetrahedronTriangles[16][7];
static const long aiCubeEdgeFlags[256];
static const int a2iTriangleConnectionTable[256][16];
};
} // End namespace Avogadro
#endif