add Triangulator

This commit is contained in:
David Rose 2007-01-19 21:25:40 +00:00
parent 61ef8d64e2
commit a2a49aa9fb
15 changed files with 2687 additions and 79 deletions

View File

@ -30,9 +30,12 @@
perlinNoise2.h perlinNoise2.I \
perlinNoise3.h perlinNoise3.I \
plane.h plane_src.I plane_src.cxx \
plane_src.h rotate_to.h rotate_to_src.cxx \
plane_src.h \
randomizer.h randomizer.I \
rotate_to.h rotate_to_src.cxx \
stackedPerlinNoise2.h stackedPerlinNoise2.I \
stackedPerlinNoise3.h stackedPerlinNoise3.I
stackedPerlinNoise3.h stackedPerlinNoise3.I \
triangulator.h triangulator.I
#define INCLUDED_SOURCES \
boundingHexahedron.cxx boundingLine.cxx \
@ -47,8 +50,10 @@
perlinNoise.cxx \
perlinNoise2.cxx \
perlinNoise3.cxx \
randomizer.cxx \
stackedPerlinNoise2.cxx \
stackedPerlinNoise3.cxx \
triangulator.cxx \
plane.cxx rotate_to.cxx
#define INSTALL_HEADERS \
@ -67,9 +72,13 @@
perlinNoise2.h perlinNoise2.I \
perlinNoise3.h perlinNoise3.I \
plane.h plane_src.I plane_src.cxx \
plane_src.h rotate_to.h rotate_to_src.cxx \
plane_src.h \
randomizer.h randomizer.I \
rotate_to.h rotate_to_src.cxx \
stackedPerlinNoise2.h stackedPerlinNoise2.I \
stackedPerlinNoise3.h stackedPerlinNoise3.I
stackedPerlinNoise3.h stackedPerlinNoise3.I \
triangulator.h triangulator.I
#define IGATESCAN all
@ -79,7 +88,7 @@
#begin test_bin_target
#define TARGET test_mathutil
#define LOCAL_LIBS \
mathutil
mathutil pipeline
#define OTHER_LIBS $[OTHER_LIBS] pystub
#define SOURCES \
@ -87,3 +96,15 @@
#end test_bin_target
#begin test_bin_target
#define TARGET test_tri
#define LOCAL_LIBS \
mathutil pipeline
#define OTHER_LIBS $[OTHER_LIBS] pystub
#define SOURCES \
test_tri.cxx
#end test_bin_target

View File

@ -6,3 +6,4 @@
#include "finiteBoundingVolume.cxx"
#include "geometricBoundingVolume.cxx"
#include "omniBoundingVolume.cxx"
#include "config_mathutil.cxx"

View File

@ -1,4 +1,3 @@
#include "config_mathutil.cxx"
#include "fftCompressor.cxx"
#include "linmath_events.cxx"
#include "look_at.cxx"
@ -7,6 +6,8 @@
#include "perlinNoise2.cxx"
#include "perlinNoise3.cxx"
#include "plane.cxx"
#include "randomizer.cxx"
#include "rotate_to.cxx"
#include "stackedPerlinNoise2.cxx"
#include "stackedPerlinNoise3.cxx"
#include "triangulator.cxx"

View File

@ -39,51 +39,6 @@ lerp(double t, double a, double b) {
return a + t * (b - a);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise::random_int
// Access: Protected
// Description: Returns a random integer in the range [0, range).
////////////////////////////////////////////////////////////////////
INLINE int PerlinNoise::
random_int(int range) {
return (int)floor(random_real((double)range));
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise::random_real
// Access: Protected
// Description: Returns a random double in the range [0, range).
////////////////////////////////////////////////////////////////////
INLINE double PerlinNoise::
random_real(double range) {
return (range * _mersenne.get_uint31()) / ((double)0x80000000);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise::random_real_unit
// Access: Protected
// Description: Returns a random double in the range [-0.5, 0.5).
////////////////////////////////////////////////////////////////////
INLINE double PerlinNoise::
random_real_unit() {
return random_real(1.0f) - 0.5f;
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise::get_next_seed
// Access: Protected, Static
// Description: Returns a random seed value for the next global
// PerlinNoise object.
////////////////////////////////////////////////////////////////////
INLINE unsigned long PerlinNoise::
get_next_seed() {
if (!_got_first_seed) {
_next_seed = Mersenne((unsigned long)time(NULL));
_got_first_seed = true;
}
return _next_seed.get_uint31();
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise::get_seed
// Access: Published
@ -93,5 +48,5 @@ get_next_seed() {
////////////////////////////////////////////////////////////////////
INLINE unsigned long PerlinNoise::
get_seed() {
return _mersenne.get_uint31();
return _randomizer.get_seed();
}

View File

@ -18,9 +18,6 @@
#include "perlinNoise.h"
Mersenne PerlinNoise::_next_seed(0);
bool PerlinNoise::_got_first_seed = false;
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise::Constructor
// Access: Protected
@ -34,7 +31,7 @@ PerlinNoise::
PerlinNoise(int table_size, unsigned long seed) :
_table_size(table_size),
_table_size_mask(table_size - 1),
_mersenne(seed != 0 ? seed : get_next_seed())
_randomizer(seed)
{
// It is necessary for _table_size to be a power of 2.
#ifndef NDEBUG
@ -55,7 +52,7 @@ PerlinNoise(int table_size, unsigned long seed) :
_index.push_back(i);
}
for (i = 0; i < _table_size; ++i) {
int j = random_int(_table_size);
int j = _randomizer.random_int(_table_size);
nassertv(j >= 0 && j < _table_size);
int t = _index[i];
_index[i] = _index[j];
@ -79,7 +76,7 @@ PerlinNoise::
PerlinNoise(const PerlinNoise &copy) :
_table_size(copy._table_size),
_table_size_mask(copy._table_size_mask),
_mersenne(copy._mersenne),
_randomizer(copy._randomizer),
_index(copy._index)
{
}
@ -94,6 +91,6 @@ void PerlinNoise::
operator = (const PerlinNoise &copy) {
_table_size = copy._table_size;
_table_size_mask = copy._table_size_mask;
_mersenne = copy._mersenne;
_randomizer = copy._randomizer;
_index = copy._index;
}

View File

@ -23,7 +23,7 @@
#include "pvector.h"
#include "vector_int.h"
#include "luse.h"
#include "mersenne.h"
#include "randomizer.h"
////////////////////////////////////////////////////////////////////
// Class : PerlinNoise
@ -41,12 +41,6 @@ protected:
INLINE static double fade(double t);
INLINE static double lerp(double t, double a, double b);
INLINE int random_int(int range);
INLINE double random_real(double range);
INLINE double random_real_unit();
INLINE static unsigned long get_next_seed();
PUBLISHED:
INLINE unsigned long get_seed();
@ -54,9 +48,7 @@ protected:
int _table_size;
int _table_size_mask;
Mersenne _mersenne;
static Mersenne _next_seed;
static bool _got_first_seed;
Randomizer _randomizer;
typedef vector_int Index;
Index _index;

View File

@ -71,11 +71,11 @@ noise(const LVecBase2d &value) const {
////////////////////////////////////////////////////////////////////
void PerlinNoise2::
init_unscaled_xform() {
double rot = random_real(360.0f);
double rot = _randomizer.random_real(360.0f);
_unscaled_xform = LMatrix3d::rotate_mat(rot);
// And come up with a random translation too, just so the
// singularity at (0, 0) is also unpredicatable.
_unscaled_xform.set_row(2, LVecBase2d(random_real_unit(),
random_real_unit()));
_unscaled_xform.set_row(2, LVecBase2d(_randomizer.random_real_unit(),
_randomizer.random_real_unit()));
}

View File

@ -85,16 +85,16 @@ noise(const LVecBase3d &value) const {
////////////////////////////////////////////////////////////////////
void PerlinNoise3::
init_unscaled_xform() {
LRotationd rot(random_real_unit(),
random_real_unit(),
random_real_unit(),
random_real_unit());
LRotationd rot(_randomizer.random_real_unit(),
_randomizer.random_real_unit(),
_randomizer.random_real_unit(),
_randomizer.random_real_unit());
rot.normalize();
rot.extract_to_matrix(_unscaled_xform);
// And come up with a random translation too, just so the
// singularity at (0, 0, 0) is also unpredicatable.
_unscaled_xform.set_row(3, LVecBase3d(random_real_unit(),
random_real_unit(),
random_real_unit()));
_unscaled_xform.set_row(3, LVecBase3d(_randomizer.random_real_unit(),
_randomizer.random_real_unit(),
_randomizer.random_real_unit()));
}

View File

@ -0,0 +1,108 @@
// Filename: randomizer.I
// Created by: drose (18Jan07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: Randomizer::Constructor
// Access: Public
// Description: If seed is nonzero, it is used to define the tables;
// if it is zero a random seed is generated.
////////////////////////////////////////////////////////////////////
Randomizer::
Randomizer(unsigned long seed) :
_mersenne(seed != 0 ? seed : get_next_seed())
{
}
////////////////////////////////////////////////////////////////////
// Function: Randomizer::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
Randomizer::
Randomizer(const Randomizer &copy) :
_mersenne(copy._mersenne)
{
}
////////////////////////////////////////////////////////////////////
// Function: Randomizer::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void Randomizer::
operator = (const Randomizer &copy) {
_mersenne = copy._mersenne;
}
////////////////////////////////////////////////////////////////////
// Function: Randomizer::random_int
// Access: Public
// Description: Returns a random integer in the range [0, range).
////////////////////////////////////////////////////////////////////
INLINE int Randomizer::
random_int(int range) {
return (int)floor(random_real((double)range));
}
////////////////////////////////////////////////////////////////////
// Function: Randomizer::random_real
// Access: Public
// Description: Returns a random double in the range [0, range).
////////////////////////////////////////////////////////////////////
INLINE double Randomizer::
random_real(double range) {
return (range * _mersenne.get_uint31()) / ((double)0x80000000);
}
////////////////////////////////////////////////////////////////////
// Function: Randomizer::random_real_unit
// Access: Public
// Description: Returns a random double in the range [-0.5, 0.5).
////////////////////////////////////////////////////////////////////
INLINE double Randomizer::
random_real_unit() {
return random_real(1.0f) - 0.5f;
}
////////////////////////////////////////////////////////////////////
// Function: Randomizer::get_next_seed
// Access: Public, Static
// Description: Returns a random seed value for the next global
// Randomizer object.
////////////////////////////////////////////////////////////////////
INLINE unsigned long Randomizer::
get_next_seed() {
if (!_got_first_seed) {
_next_seed = Mersenne((unsigned long)time(NULL));
_got_first_seed = true;
}
return _next_seed.get_uint31();
}
////////////////////////////////////////////////////////////////////
// Function: Randomizer::get_seed
// Access: Public
// Description: Returns a unique seed value based on the seed value
// passed to this Randomizer object (and on its current
// state).
////////////////////////////////////////////////////////////////////
INLINE unsigned long Randomizer::
get_seed() {
return _mersenne.get_uint31();
}

View File

@ -0,0 +1,23 @@
// Filename: randomizer.cxx
// Created by: drose (18Jan07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "randomizer.h"
Mersenne Randomizer::_next_seed(0);
bool Randomizer::_got_first_seed = false;

View File

@ -0,0 +1,50 @@
// Filename: randomizer.h
// Created by: drose (18Jan07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef RANDOMIZER_H
#define RANDOMIZER_H
#include "pandabase.h"
#include "mersenne.h"
////////////////////////////////////////////////////////////////////
// Class : Randomizer
// Description : A handy class to return random numbers.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA Randomizer {
public:
INLINE Randomizer(unsigned long seed = 0);
INLINE Randomizer(const Randomizer &copy);
INLINE void operator = (const Randomizer &copy);
INLINE int random_int(int range);
INLINE double random_real(double range);
INLINE double random_real_unit();
INLINE static unsigned long get_next_seed();
INLINE unsigned long get_seed();
private:
Mersenne _mersenne;
static Mersenne _next_seed;
static bool _got_first_seed;
};
#include "randomizer.I"
#endif

View File

@ -0,0 +1,50 @@
// Filename: test_tri.cxx
// Created by: drose (19Jan07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "triangulator.h"
int main(int argc, char *argv[]) {
Triangulator t;
t.add_vertex(0, 0);
t.add_vertex(4, 0);
t.add_vertex(4, 4);
t.add_vertex(0, 4);
t.add_vertex(1, 1);
t.add_vertex(2, 1);
t.add_vertex(2, 2);
t.add_vertex(1, 2);
t.add_polygon_vertex(0);
t.add_polygon_vertex(1);
t.add_polygon_vertex(2);
t.add_polygon_vertex(3);
t.begin_hole();
t.add_hole_vertex(7);
t.add_hole_vertex(6);
t.add_hole_vertex(5);
t.add_hole_vertex(4);
t.triangulate();
return 0;
}

View File

@ -0,0 +1,71 @@
// Filename: triangulator.I
// Created by: drose (18Jan07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: Triangulator::add_vertex
// Access: Published
// Description: Adds a new vertex to the vertex pool. Returns the
// vertex index number.
////////////////////////////////////////////////////////////////////
INLINE int Triangulator::
add_vertex(double x, double y) {
return add_vertex(LPoint2d(x, y));
}
////////////////////////////////////////////////////////////////////
// Function: Triangulator::Triangle::Constructor
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
INLINE Triangulator::Triangle::
Triangle(Triangulator *t, int v0, int v1, int v2) :
_v0(t->vert[v0].user_i),
_v1(t->vert[v1].user_i),
_v2(t->vert[v2].user_i)
{
}
////////////////////////////////////////////////////////////////////
// Function: Triangulator::segment_t::Default Constructor
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
INLINE Triangulator::segment_t::
segment_t() {
}
////////////////////////////////////////////////////////////////////
// Function: Triangulator::segment_t::Constructor
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
INLINE Triangulator::segment_t::
segment_t(Triangulator *t, int v0_i, int v1_i, int prev, int next) :
is_inserted(false),
root0(0), root1(0),
next(next),
prev(prev),
v0_i(v0_i)
{
v0.x = t->_vertices[v0_i][0];
v0.y = t->_vertices[v0_i][1];
v1.x = t->_vertices[v1_i][0];
v1.y = t->_vertices[v1_i][1];
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,211 @@
// Filename: triangulator.h
// Created by: drose (17Jan07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef TRIANGULATOR_H
#define TRIANGULATOR_H
#include "pandabase.h"
#include "luse.h"
#include "vector_int.h"
////////////////////////////////////////////////////////////////////
// Class : Triangulator
// Description : This class can triangulate a convex or concave
// polygon, even one with holes. It is adapted from an
// algorithm published as:
//
// Narkhede A. and Manocha D., Fast polygon
// triangulation algorithm based on Seidel's Algorithm,
// UNC-CH, 1994.
//
// http://www.cs.unc.edu/~dm/CODE/GEM/chapter.html
//
// It works strictly on 2-d points. You'll have to
// convert your polygon into a plane if you have 3-d
// points.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA Triangulator {
PUBLISHED:
Triangulator();
void clear();
int add_vertex(const LPoint2d &point);
INLINE int add_vertex(double x, double y);
void clear_polygon();
void add_polygon_vertex(int index);
void begin_hole();
void add_hole_vertex(int index);
void triangulate();
int get_num_triangles() const;
int get_triangle_v0(int n) const;
int get_triangle_v1(int n) const;
int get_triangle_v2(int n) const;
private:
typedef pvector<LPoint2d> Vertices;
Vertices _vertices;
vector_int _polygon;
typedef pvector<vector_int> Holes;
Holes _holes;
class Triangle {
public:
INLINE Triangle(Triangulator *t, int v0, int v1, int v2);
int _v0, _v1, _v2;
};
typedef pvector<Triangle> Result;
Result _result;
typedef struct {
double x, y;
} point_t, vector_t;
struct segment_t {
INLINE segment_t();
INLINE segment_t(Triangulator *t, int v0_i, int v1_i, int prev, int next);
point_t v0, v1; /* two endpoints */
int is_inserted; /* inserted in trapezoidation yet ? */
int root0, root1; /* root nodes in Q */
int next; /* Next logical segment */
int prev; /* Previous segment */
int v0_i; // index to user's vertex number
};
typedef pvector<segment_t> Segments;
Segments seg;
vector_int permute;
int choose_idx;
/* Trapezoid attributes */
typedef struct {
int lseg, rseg; /* two adjoining segments */
point_t hi, lo; /* max/min y-values */
int u0, u1;
int d0, d1;
int sink; /* pointer to corresponding in Q */
int usave, uside; /* I forgot what this means */
int state;
} trap_t;
/* Node attributes for every node in the query structure */
typedef struct {
int nodetype; /* Y-node or S-node */
int segnum;
point_t yval;
int trnum;
int parent; /* doubly linked DAG */
int left, right; /* children */
} node_t;
typedef struct {
int vnum;
int next; /* Circularly linked list */
int prev; /* describing the monotone */
int marked; /* polygon */
} monchain_t;
typedef struct {
point_t pt;
int vnext[4]; /* next vertices for the 4 chains */
int vpos[4]; /* position of v in the 4 chains */
int nextfree;
int user_i; // index to user's vertex number
} vertexchain_t;
typedef pvector<node_t> QueryStructure;
QueryStructure qs;
typedef pvector<trap_t> TrapezoidStructure;
TrapezoidStructure tr;
/* Table to hold all the monotone */
/* polygons . Each monotone polygon */
/* is a circularly linked list */
pvector<monchain_t> mchain;
/* chain init. information. This */
/* is used to decide which */
/* monotone polygon to split if */
/* there are several other */
/* polygons touching at the same */
/* vertex */
pvector<vertexchain_t> vert;
/* contains position of any vertex in */
/* the monotone chain for the polygon */
vector_int mon;
vector_int visited;
void make_segment(const vector_int &range);
int choose_segment();
int math_logstar_n(int n);
int math_N(int n, int h);
int newnode();
int newtrap();
int _max(point_t *yval, point_t *v0, point_t *v1);
int _min(point_t *yval, point_t *v0, point_t *v1);
int _greater_than(point_t *v0, point_t *v1);
int _equal_to(point_t *v0, point_t *v1);
int _greater_than_equal_to(point_t *v0, point_t *v1);
int _less_than(point_t *v0, point_t *v1);
int init_query_structure(int segnum);
int is_left_of(int segnum, point_t *v);
int inserted(int segnum, int whichpt);
int locate_endpoint(point_t *v, point_t *vo, int r);
int merge_trapezoids(int segnum, int tfirst, int tlast, int side);
int add_segment(int segnum);
int find_new_roots(int segnum);
int construct_trapezoids(int nseg);
int inside_polygon(trap_t *t);
int newmon();
int new_chain_element();
double get_angle(point_t *vp0, point_t *vpnext, point_t *vp1);
int get_vertex_positions(int v0, int v1, int *ip, int *iq);
int make_new_monotone_poly(int mcur, int v0, int v1);
int monotonate_trapezoids(int n);
int traverse_polygon(int mcur, int trnum, int from, int dir);
void triangulate_monotone_polygons(int nvert, int nmonpoly);
void triangulate_single_polygon(int nvert, int posmax, int side);
friend class Triangle;
friend struct segment_t;
};
#include "triangulator.I"
#endif