1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
#ifndef SUBDIV_ALGORITHMS_H
#define SUBDIV_ALGORITHMS_H
// K-3D
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/** \file
\brief Declares subdivision rendering algorithms
\author Bart Janssens <bart.janssens@lid.kviv.be>
*/
#include <k3dsdk/mesh.h>
#include <map>
#include <set>
namespace subdiv
{
/// Catmull-Clark subdivision algorithm
void catmull_clark(const unsigned long Levels, const k3d::mesh& Input, k3d::mesh& Output, const bool ignore_selection = true);
/// Process SDS creases and corners
void crease(const k3d::mesh& Input, k3d::mesh& Output);
/// Return the sharpness of an edge
double get_sharpness(const k3d::split_edge& Edge);
/// Return the centroid of the face Edge belongs to
k3d::vector3 get_centroid(const k3d::split_edge& Edge);
/// Provide methods to split faces and edges
class splitter
{
typedef std::set<k3d::split_edge*> edgeset;
typedef std::map<k3d::split_edge*, k3d::face*> edge_face_map;
typedef std::map<k3d::split_edge*, double> edge_double_map;
typedef std::map<k3d::point*, std::pair<k3d::point*, k3d::point*> > point_map;
public:
/// Create a new splitter
splitter(k3d::polyhedron& Polyhedron, k3d::mesh::points_t& Points) : m_Polyhedron(Polyhedron), m_Points(Points), m_f(0.0)
{
for (unsigned long i = 0; i < Polyhedron.faces.size(); ++i)
m_face_starts[Polyhedron.faces[i]->first_edge] = Polyhedron.faces[i];
}
/// Convert sharpness to factor
static double sharpness_to_factor(const double sharpness)
{
if (sharpness <= 0.0)
return 0.0;
if (sharpness < 1.0)
return 0.5 - 0.1*sharpness;
return 0.4/sharpness;
}
/// Split an edge, adding a point at fraction f near the edge vertex. Return a pointer to the newly created edge, or 0 if the function failed.
k3d::split_edge* split_edge(k3d::split_edge& Edge, const double factor);
/// Split a face, ading an edge parallel to Edge at fraction f distance from that edge. Return a pointer to the new edge, or 0 if the function failed. isFaceStart is true if Edge or Edge.face_clockwise is the first edge of a face.
k3d::split_edge* split_face_along_edge(k3d::split_edge& Edge, const double factor, const k3d::vector3& centroid);
private:
/// Find the counter-clockwise edge on a face
k3d::split_edge* counter_clockwise(k3d::split_edge& Edge);
/// Find out if any of the edges in Edges are the start of an edge. Linear search, so may be slow
bool is_face(k3d::split_edge& Edge);
/// add a new face
void add_face(k3d::split_edge& Edge);
/// Detach the starting point of a parallel split face, where Edge points to the to be detached vertex. Note my complete failure to come up with a decent explanation of what this function actually does.
k3d::split_edge* detach_edge_vertex(k3d::split_edge& Edge, const k3d::vector3& centroid);
/// Detach the starting point of a parallel split face, where the detached vertex belongs to Edge.
k3d::split_edge* detach_edge_novertex(k3d::split_edge& Edge, const k3d::vector3& centroid);
/// Adapt the factor on an edge that has been split before
double adapt_factor(k3d::split_edge& Edge, const double factor);
edgeset m_split_edges;
edge_double_map m_parallel_edges;
edge_face_map m_face_starts;
// Keep track of the factor an edge was split at, to recalculate the factor when the edge is split again.
edge_double_map m_last_factor;
point_map m_other_points;
k3d::polyhedron& m_Polyhedron;
k3d::mesh::points_t& m_Points;
double m_f;
};
} // namespace subdiv
#endif // SUBDIV_ALGORITHMS_H
|