home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Photo CD Demo 1
/
Demo.bin
/
graphtal
/
plane.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-22
|
5KB
|
215 lines
/*
* Plane.C - methods for plane manipulations.
*
* Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
* All rights reserved.
*
* This software may be freely copied, modified, and redistributed
* provided that this copyright notice is preserved on all copies.
*
* You may not distribute this software, in whole or in part, as part of
* any commercial product without the express consent of the authors.
*
* There is no warranty or other guarantee of fitness of this software
* for any purpose. It is provided solely "as is".
*
*/
#include "Plane.h"
//___________________________________________________________ Plane
Plane::Plane(const Vector& position, const Vector& normal)
: pos(position), n(normal)
{
if (n.normalize() == 0)
n.normalize();
D = pos^n;
}
GeoObject* Plane::create(const Vector& position, const Vector& normal)
{
if (equal(normal.sqr(), 0))
return NULL;
return new Plane(position, normal);
}
/*
* intersect plane with ray.
*/
int Plane::intersect(const Ray& ray, real minDist, real& maxDist)
{
intersectionTests++;
real t = n^ray.getDir();
if (fabs(t) < minDist)
return FALSE;
t = (D - (ray.getOrig()^n))/t;
if (t > minDist && t < maxDist) {
maxDist = t;
intersections++;
return TRUE;
}
return FALSE;
}
/*
* calculate plane normal
*/
Vector Plane::normal(const Vector&) const
{
return n;
}
/*
* tesselate splits a plane into a polygon (I know it's impossible).
* It is done by intersecting the plane with the bounding volume. The
* resulting polygon is the visible part of the plane within the bounding
* volume.
*/
PolygonList* Plane::tesselate(const BoundingBox& bbox)
{
int i;
BoundingBox tbbox(bbox);
if (trans != NULL)
tbbox = bbox.transform(*itrans);
/*
* compute the points on the bounding volume
*/
Vector bottom[4];
bottom[0] = Vector(tbbox.xmin(), tbbox.ymin(), tbbox.zmin());
bottom[1] = Vector(tbbox.xmax(), tbbox.ymin(), tbbox.zmin());
bottom[2] = Vector(tbbox.xmax(), tbbox.ymax(), tbbox.zmin());
bottom[3] = Vector(tbbox.xmin(), tbbox.ymax(), tbbox.zmin());
Vector top[4];
top[0] = Vector(tbbox.xmin(), tbbox.ymin(), tbbox.zmax());
top[1] = Vector(tbbox.xmax(), tbbox.ymin(), tbbox.zmax());
top[2] = Vector(tbbox.xmax(), tbbox.ymax(), tbbox.zmax());
top[3] = Vector(tbbox.xmin(), tbbox.ymax(), tbbox.zmax());
Polygon* p = new Polygon(4);
PolygonList* polys = NULL;
Vector iPoint;
int pointsOnPlane;
for (i=0; i<4; i++) {
if (pointsOnPlane=intersectPlaneWithSegment(bottom[i], top[i], iPoint)) {
if (pointsOnPlane == 2) {
p->addVertex(bottom[i]);
p->addVertex(top[i]);
}
else
p->addVertex(iPoint);
}
}
for (i=0; i<4 && p->numVertices() < 4; i++) {
if (pointsOnPlane=intersectPlaneWithSegment(top[i], top[(i+1)%4], iPoint)) {
if (pointsOnPlane == 2) {
p->addVertex(top[i]);
p->addVertex(top[(i+1)%4]);
}
else
p->addVertex(iPoint);
}
}
for (i=0; i<4 && p->numVertices() < 4; i++) {
if (pointsOnPlane=intersectPlaneWithSegment(bottom[i], bottom[(i+1)%4], iPoint)) {
if (pointsOnPlane == 2) {
p->addVertex(bottom[i]);
p->addVertex(bottom[(i+1)%4]);
}
else
p->addVertex(iPoint);
}
}
if (p->numVertices() < 3) {
delete p;
p = NULL;
}
else if (p->numVertices() == 4) {
Vector p1 = p->vertex(0), p2 = p->vertex(1),
p3 = p->vertex(2), p4 = p->vertex(3);
/*
* check if any two edges intersects
* -> if yes, swap the corresponding points
*/
if (!equal(((p2-p1)*(p4-p3)).sqr(),0)) {
Polygon* swapedP = new Polygon(p1, p2, p4, p3);
delete p;
p = swapedP;
}
else if (!equal(((p4-p1)*(p2-p3)).sqr(),0)) {
Polygon* swapedP = new Polygon(p2, p1, p3, p4);
delete p;
p = swapedP;
}
}
if (p != NULL) {
if (trans != NULL)
p->transform(*trans);
polys = new PolygonList(1);
polys->append(p);
}
return polys;
}
/*
* Intersect segment p1,p2 with the plane. The return values are
* 0 (no intersection), 1 (one intersection) or 2 (segment is on the plane).
*/
int Plane::intersectPlaneWithSegment(const Vector& p1, const Vector& p2, Vector& h)
{
/*
* calculate distance to plane for points p1, p2
*/
real d1 = (p1 - pos)^n;
real d2 = (p2 - pos)^n;
/*
* Test if one (both) endpoint(s) of the segment is one the plane.
*/
if (equal(d1, 0)) {
if (equal(d2,0))
return 2;
else {
h = p1;
return 1;
}
}
else if (equal(d2, 0)) {
h = p2;
return 1;
}
/*
* If the point p1 and p2 are on the same side of the plane,
* no intersection is possible.
*/
if ((d1 < 0 && d2 < 0) || (d1 > 0 && d2 > 0))
return 0;
Vector dir = p2-p1; dir.normalize();
real t = n^dir;
h = p1 + ((D-(p1^n))/t)*dir;
return 1;
}