Created
November 5, 2017 01:10
-
-
Save haleyjd/e560e4c4756149da13f9538f3404b9ca to your computer and use it in GitHub Desktop.
node build geometry file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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