Polygon to triangles

Published July 16, 1999 by Unknown Author, posted by Myopic Rhino
Do you see issues with this article? Let us know.
Advertisement
/*
* poly_tri.c
*
* Program to take a polygon definition and convert it into triangles
* that may then be rendered by the standard triangle rendering
* algorithms. This assumes all transformations have been performed
* already and cuts them up into optimal triangles based on their
* screen-space representation.
*
* Copyright (c) 1988, Evans & Sutherland Computer Corporation
*
* Permission to use all or part of this program without fee is
* granted provided that it is not used or distributed for direct
* commercial gain, the above copyright notice appears, and
* notice is given that use is by permission of Evans & Sutherland
* Computer Corporation.
*
* Written by Reid Judd and Scott R. Nelson at
* Evans & Sutherland Computer Corporation (January, 1988)
*
* To use this program, either write your own "draw_triangle" routine
* that can draw triangles from the definitions below, or modify the
* code to call your own triangle or polygon rendering code. Call
* "draw_poly" from your main program.
*/

#include


/* A single vertex */

typedef struct {
int color; /* RGB */
float x;
float y;
float z;
} vertex;


/* A triangle made up of three vertices */

typedef vertex triangle[3];


#define V_MAX 100 /* Maximum number of vertices allowed (arbitrary) */

#define BIG 1.0e30 /* A number bigger than we expect to find here */

#define COUNTER_CLOCKWISE 0
#define CLOCKWISE 1



/*
* orientation
*
* Return either clockwise or counter_clockwise for the orientation
* of the polygon.
*/

int orientation( n, v )
int n; /* Number of vertices */
vertex v[]; /* The vertex list */
{
float area;
int i;

/* Do the wrap-around first */
area = v[n-1].x * v[0].y - v[0].x * v[n-1].y;

/* Compute the area (times 2) of the polygon */
for (i = 0; i < n-1; i++)
area += v.x * v[i+1].y - v[i+1].x * v.y;

if (area >= 0.0)
return COUNTER_CLOCKWISE;
else
return CLOCKWISE;
} /* End of orientation */



/*
* determinant
*
* Computes the determinant of the three points.
* Returns whether the triangle is clockwise or counter-clockwise.
*/

int determinant( p1, p2, p3, v )
int p1, p2, p3; /* The vertices to consider */
vertex v[]; /* The vertex list */
{
float x1, x2, x3, y1, y2, y3;
float determ;

x1 = v[p1].x;
y1 = v[p1].y;
x2 = v[p2].x;
y2 = v[p2].y;
x3 = v[p3].x;
y3 = v[p3].y;

determ = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
if (determ >= 0.0)
return COUNTER_CLOCKWISE;
else
return CLOCKWISE;
} /* End of determinant */



/*
* distance2
*
* Returns the square of the distance between the two points
*/

float distance2( x1, y1, x2, y2 )
float x1, y1, x2, y2;
{
float xd, yd; /* The distances in X and Y */
float dist2; /* The square of the actual distance */

xd = x1 - x2;
yd = y1 - y2;
dist2 = xd * xd + yd * yd;

return dist2;
} /* End of distance2 */



/*
* no_interior
*
* Returns 1 if no other point in the vertex list is inside
* the triangle specified by the three points. Returns
* 0 otherwise.
*/

int no_interior( p1, p2, p3, v, vp, n, poly_or )
int p1, p2, p3; /* The vertices to consider */
vertex v[]; /* The vertex list */
int vp[]; /* The vertex pointers (which are left) */
int n; /* Number of vertices */
int poly_or; /* Polygon orientation */
{
int i; /* Iterative counter */
int p; /* The test point */

for (i = 0; i < n; i++) {
p = vp; /* The point to test */
if ((p == p1) || (p == p2) || (p == p3))
continue; /* Don't bother checking against yourself */
if ( (determinant( p2, p1, p, v ) == poly_or)
|| (determinant( p1, p3, p, v ) == poly_or)
|| (determinant( p3, p2, p, v ) == poly_or) ) {
continue; /* This point is outside */
} else {
return 0; /* The point is inside */
}
}
return 1; /* No points inside this triangle */
} /* End of no_interior */



/*
* draw_poly
*
* Call this procedure with a polygon, this divides it into triangles
* and calls the triangle routine once for each triangle.
*
* Note that this does not work for polygons with holes or self
* penetrations.
*/

draw_poly( n, v )
int n; /* Number of vertices in triangle */
vertex v[]; /* The vertex list (implicit closure) */
{
int prev, cur, next; /* Three points currently being considered */
int vp[V_MAX]; /* Pointers to vertices still left */
int count; /* How many vertices left */
int min_vert; /* Vertex with minimum distance */
int i; /* Iterative counter */
float dist; /* Distance across this one */
float min_dist; /* Minimum distance so far */
int poly_orientation; /* Polygon orientation */
triangle t; /* Triangle structure */

if (n > V_MAX) {
fprintf( stderr, "Error, more than %d vertices.\n", V_MAX);
return;
}

poly_orientation = orientation( n, v );

for (i = 0; i < n; i++)
vp = i; /* Put vertices in order to begin */

/* Slice off clean triangles until nothing remains */

count = n;
while (count > 3) {
min_dist = BIG; /* A real big number */
min_vert = 0; /* Just in case we don't find one... */
for (cur = 0; cur < count; cur++) {
prev = cur - 1;
next = cur + 1;
if (cur == 0) /* Wrap around on the ends */
prev = count - 1;
else if (cur == count - 1)
next = 0;
/* Pick out shortest distance that forms a good triangle */
if ( (determinant( vp[prev], vp[cur], vp[next], v ) == poly_orientation)
/* Same orientation as polygon */
&& no_interior( vp[prev], vp[cur], vp[next], v, vp, count, poly_orientation )
/* No points inside */
&& ((dist = distance2( v[vp[prev]].x, v[vp[prev]].y,
v[vp[next]].x, v[vp[next]].y )) < min_dist) )
/* Better than any so far */
{
min_dist = dist;
min_vert = cur;
}
} /* End of for each vertex (cur) */

/* The following error should "never happen". */
if (min_dist == BIG)
fprintf( stderr, "Error: Didn't find a triangle.\n" );

prev = min_vert - 1;
next = min_vert + 1;
if (min_vert == 0) /* Wrap around on the ends */
prev = count - 1;
else if (min_vert == count - 1)
next = 0;

/* Output this triangle */

t[0].x = v[vp[prev]].x;
t[0].y = v[vp[prev]].y;
t[0].z = v[vp[prev]].z;
t[0].color = v[vp[prev]].color;
t[1].x = v[vp[min_vert]].x;
t[1].y = v[vp[min_vert]].y;
t[1].z = v[vp[min_vert]].z;
t[1].color = v[vp[min_vert]].color;
t[2].x = v[vp[next]].x;
t[2].y = v[vp[next]].y;
t[2].z = v[vp[next]].z;
t[2].color = v[vp[next]].color;

draw_triangle( t );

/* Remove the triangle from the polygon */

count -= 1;
for (i = min_vert; i < count; i++)
vp = vp[i+1];
}

/* Output the final triangle */

t[0].x = v[vp[0]].x;
t[0].y = v[vp[0]].y;
t[0].z = v[vp[0]].z;
t[0].color = v[vp[0]].color;
t[1].x = v[vp[1]].x;
t[1].y = v[vp[1]].y;
t[1].z = v[vp[1]].z;
t[1].color = v[vp[1]].color;
t[2].x = v[vp[2]].x;
t[2].y = v[vp[2]].y;
t[2].z = v[vp[2]].z;
t[2].color = v[vp[2]].color;

draw_triangle( t );

} /* End of draw_poly */

/* End of poly_tri.c */
Cancel Save
0 Likes 0 Comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement