Skip to content

Instantly share code, notes, and snippets.

@haleyjd
Created November 5, 2017 01:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haleyjd/e560e4c4756149da13f9538f3404b9ca to your computer and use it in GitHub Desktop.
Save haleyjd/e560e4c4756149da13f9538f3404b9ca to your computer and use it in GitHub Desktop.
node build geometry file
//
// CS 4143
// Final Project
// James Haley
//
// Geometric primitives for BSPGEN
//
#include "math.h"
#include "geometry.h"
#include "bsp.h"
// T_Point methods
//
// T_Point::operator []
//
// Convenience method to retrieve point/vector coordinates
//
double &T_Point::operator [](int i)
{
switch(i % 3)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
}
// dummy return for compiler
return x;
}
//
// T_Point::operator |
//
// Implements vector dot product operation
//
// Note: | has an appropriate relationship to other operators for
// dot product mathematical precedence, and is not already
// signficantly overloaded.
//
inline double T_Point::operator |(const T_Point &pt2) const
{
return (x * pt2.x) + (y * pt2.y) + (z * pt2.z);
}
//
// T_Point::operator *
//
// Implements vector cross product
//
inline T_Point T_Point::operator *(const T_Point &pt2) const
{
return T_Point((y * pt2.z) - (z * pt2.y),
(x * pt2.z) - (z * pt2.x),
(x * pt2.y) - (y * pt2.x));
}
//
// T_Point::operator *
//
// Implements vector scalar multiplication
//
inline T_Point T_Point::operator *(double s) const
{
return T_Point(x*s, y*s, z*s);
}
//
// T_Point::operator +
//
// Implements vector addition
//
inline T_Point T_Point::operator +(const T_Point &pt2) const
{
return T_Point(x + pt2.x, y + pt2.y, z + pt2.z);
}
//
// T_Point::operator -
//
// Implements vector subtraction
//
inline T_Point T_Point::operator -(const T_Point &pt2) const
{
return T_Point(x - pt2.x, y - pt2.y, z - pt2.z);
}
//
// T_Point::normalize
//
// Returns a copy of this vector, normalized
//
inline T_Point T_Point::normalize() const
{
double magnitude = sqrt(pow(x,2) + pow(y,2) + pow(z,2));
return T_Point(x / magnitude, y / magnitude, z / magnitude);
}
// T_Plane methods
//
// T_Plane::classifyPoint
//
// point-on-plane-side algorithm
//
// Note: Numerical stability may be an issue. It is suggested to
// use an epsilon value to give the plane "thickness," however, I
// have not encountered an explanation of exactly how to do this,
// so I am avoiding it for now.
//
inline double T_Plane::classifyPoint(T_Point &pt) const
{
return (a * pt[0]) + (b * pt[1]) + (c * pt[2]) + d;
}
//
// T_Plane::classifyPolygon
//
// polygon-on-plane-side algorithm
//
// Walks around the edge of the polygon considering each vertex
// with the classifyPoint method. If any of the vertex counts at
// the end is equal to the number of vertices, the polygon is
// definitely on one side of or coincident to the plane. Otherwise,
// it must be intersected.
//
int T_Plane::classifyPolygon(T_Polygon &poly) const
{
double side;
int count = poly.getNumVertices();
int frontCount = 0;
int backCount = 0;
int onCount = 0;
T_Point pt;
for(int i = 0; i < count; i++)
{
// retrieve and classify each vertex of the polygon
pt = poly[i];
side = classifyPoint(pt);
if(side < 0.0) // point is behind plane
backCount++;
else if(side > 0.0) // point is in front of plane
frontCount++;
else // point is on plane
onCount++;
}
// determine position of polygon
if(backCount == count || backCount + onCount == count)
return PC_BEHIND;
else if(frontCount == count || frontCount + onCount == count)
return PC_INFRONT;
else if(onCount == count)
return PC_ON;
else
return PC_INTERSECT;
}
// T_Polygon methods
//
// T_Polygon constructor
//
// Takes list of T_Points
//
T_Polygon::T_Polygon(int numPts, T_Point *points)
{
if(numPts <= 2 || numPts >= MAXVERTICES)
{
BSPGen_Error("Error: bad vertex count for polygon");
}
for(int i = 0; i < numPts; i++)
{
vertices[i][0] = points[i][0];
vertices[i][1] = points[i][1];
vertices[i][2] = points[i][2];
}
numVertices = numPts;
// calculate polygon normal
// v1 = vector from vertex 0 to vertex 1
T_Vector v1 = vertices[1] - vertices[0];
// v2 = vector from vertex 0 to vertex N - 1
T_Vector v2 = vertices[numVertices - 1] - vertices[0];
// perform cross product and normalize the result
normal = (v1 * v2).normalize();
}
//
// T_Polygon constructor
//
// Takes 2D array of double values
//
T_Polygon::T_Polygon(int numPts, double points[][3])
{
if(numPts <= 2 || numPts >= MAXVERTICES)
{
BSPGen_Error("Error: bad vertex count for polygon");
}
for(int i = 0; i < numPts; i++)
{
vertices[i][0] = points[i][0];
vertices[i][1] = points[i][1];
vertices[i][2] = points[i][2];
}
numVertices = numPts;
// calculate polygon normal
// v1 = vector from vertex 0 to vertex 1
T_Vector v1 = vertices[1] - vertices[0];
// v2 = vector from vertex 0 to vertex N - 1
T_Vector v2 = vertices[numVertices - 1] - vertices[0];
// perform cross product and normalize the result
normal = (v1 * v2).normalize();
}
//
// T_Polygon::operator []
//
// Convenience method for retrieving the vertices of a polygon.
// Can be used with T_Point::operator [] to provide direct
// 2D indexing.
//
T_Point &T_Polygon::operator [](int i)
{
if(i < 0 || i >= numVertices)
{
BSPGen_Error("Error: polygon vertex index out of range");
}
return vertices[i];
}
//
// T_Polygon::split
//
// This function produces two polygons, the result of splitting
// this polygon with the given plane. The polygon and plane must be
// checked before-hand, since if they do not actually intersect, a
// zero-size polygon will be constructed.
//
void T_Polygon::split(T_Plane &part, T_Polygon **front, T_Polygon **back)
{
int count = numVertices;
int out_c = 0;
int in_c = 0;
T_Point ptA, ptB, outpts[MAXVERTICES], inpts[MAXVERTICES];
double sideA, sideB;
// retrieve last vertex of this polygon
ptA = vertices[count - 1];
// classify the last vertex with respect to the plane
sideA = part.classifyPoint(ptA);
for(int i = -1; ++i < count;)
{
// retrieve and classify each vertex of polygon in turn
ptB = vertices[i];
sideB = part.classifyPoint(ptB);
// handle the various cases to look for an intersection
// point
if(sideB > 0)
{
if(sideA < 0)
{
// compute the intersection point of the vector
// from point A to point B with the partition plane
// compute side vector
T_Vector v = ptB - ptA;
// simple ray-plane intersection:
// opposite-signed distance between point and plane
// divided by dot-product of plane normal and the
// side vector
double sect =
-part.classifyPoint(ptA) / (part.getNormal() | v);
// add intersection point sect units from ptA along the
// side vector as a vertex in both polygons
outpts[out_c++] = inpts[in_c++] = ptA + (v * sect);
}
// add this vertex to the front polygon
outpts[out_c++] = ptB;
}
else if(sideB < 0)
{
if(sideA > 0)
{
T_Vector v = ptB - ptA;
double sect =
-part.classifyPoint(ptA) / (part.getNormal() | v);
// add intersection point as vertex in both polygons
outpts[out_c++] = inpts[in_c++] = ptA + (v * sect);
}
// add this vertex to the back polygon
inpts[in_c++] = ptB;
}
else // vertex is exactly on the partitioning plane!
{
// add vertex to both polygons
outpts[out_c++] = inpts[in_c++] = ptB;
}
// swap vertex 1 and sideA values with the current vertex to
// compare with next vertex
ptA = ptB;
sideA = sideB;
} // end for
// construct the new polygons
*front = new T_Polygon(out_c, outpts);
(*front)->setColor(color[0], color[1], color[2]);
*back = new T_Polygon(in_c, inpts);
(*back)->setColor(color[0], color[1], color[2]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment