#include <stdio.h> #include <math.h> #include <GL/gl.h> #include <GL/glu.h> #include "poly.h" #include <vector> #include <string> using namespace std; Poly::Poly() { drawNormals = false; delta = 0.0f; position = new Vec(0,0,0); rotation = new Vec(0,0,0); color = new Color(1,0,0); normal = new Vec(0,0,0); setCenter(Vec(0,0,0)); } Poly::Poly(std::vector<Vec*> & _points) { Poly(_points, Color(1,0,0)); } Poly::Poly(std::vector<Vec*> & _points, Color _color) { delta = 0.0f; drawNormals = false; position = new Vec(0,0,0); rotation = new Vec(0,0,0); color = _color.clone(); for (std::vector<Vec*>::size_type i = 0 ; i < _points.size(); i++ ) { addPoint(_points.at(i)); } setCenter(calcCenter()); } void Poly::calcNormal() { delete normal; /* calculate face normal */ Vec b = *initpoints.at(0)-*initpoints.at(1); Vec a = *initpoints.at(2)-*initpoints.at(1); normal = a.cross(b).normalize().clone(); } Poly::~Poly() { delete position; delete rotation; delete color; delete normal; } /* * set the position where the (rotation-)center of * the polygon is located */ void Poly::setCenter(Vec c) { position = c.clone(); } void Poly::setCenter(Vec* c) { position = c->clone(); } /* * initial rotation relative to rotation center */ Vec Poly::getInitRotation(Vec& v) { return Vec(atan2(v.y(), v.z()), atan2(v.x(), v.z()), atan2(v.y(), v.x())); } /* * calculate the center relative to all vertices. */ Vec Poly::calcCenter() { Vec s (0,0,0); if ( initpoints.size() == 0 ) { return s; } for ( std::vector<Vec*>::size_type i = 0; i < initpoints.size(); i++ ) { s = s + *(initpoints.at(i)); } return s / (float)initpoints.size(); } /* * reset the position of all vertices (ie. translate your * polygon to an absolute position) */ void Poly::setPosition(Vec newcenter) { Vec diff = newcenter - (*position); delete position; position = newcenter.clone(); for ( std::vector<Vec*>::size_type i = 0; i < initpoints.size(); i++ ) { initpoints.at(i)->add((Vec)diff); } } //additional rotation in arcs void Poly::rotate(Vec rot) { rotation->add((Vec)rot); } Vec Poly::rotate_x(Vec& c) { Vec initrot = getInitRotation(c); Vec rot = initrot + *rotation; float r = Vec(0, c.y(), c.z()).length(); return Vec (c.x(), r*cos(rot.x()), r*sin(rot.x())); } Vec Poly::rotate_y(Vec& c) { Vec initrot = getInitRotation(c); Vec rot = initrot + *rotation; float r = Vec(c.x(), 0, c.z()).length(); return Vec (r*sin(rot.y()), c.y(), r*cos(rot.y())); } Vec Poly::rotate_z(Vec& c) { Vec initrot = getInitRotation(c); Vec rot = initrot + *rotation; float r = Vec(c.x(), c.y(), 0).length(); return Vec (r*cos(rot.z()), r*sin(rot.z()), c.z()); } Vec Poly::rotate_xyz(Vec out) { Vec ret = rotate_x(out); ret = rotate_y(ret); ret = rotate_z(ret); return ret; } void Poly::draw() { Vec n = Vec(0.0f, 0.0f, 0.0f); Color nc = Color(1.0f, 0.0f, 1.0f); std::vector<Vec*>::size_type vcount = initpoints.size(); //save camera position glPushMatrix(); //center poly glTranslatef(-position->x(), -position->y(), -position->z()); //rotate poly glRotatef(rotation->x(), 1.0f, 0.0f, 0.0f); glRotatef(rotation->y(), 0.0f, 1.0f, 0.0f); glRotatef(rotation->z(), 0.0f, 0.0f, 1.0f); if ( drawNormals ) { /* draw face normal */ glBegin(GL_LINES); nc.drawColor(); glVertex3fv(calcCenter().c); glVertex3fv((calcCenter()+(*normal * 3.0f)).c); glEnd(); /* draw vertex normals */ for ( std::vector<Vec*>::size_type i = 0; i < vcount; i++ ) { if ( delta <= 0.0f ) { /* face normal */ glBegin(GL_LINES); nc.drawColor(); glVertex3fv((*initpoints.at(i)).c); glVertex3fv((*initpoints.at(i)+(*normal * 1.5f)).c); glEnd(); } else { /* vertex normal (delta) */ n.c[0] = 0.0f; n.c[1] = 0.0f; n.c[2] = 0.0f; n = n+*normal; for ( std::vector<SPoly*>::size_type j = 0; j < initpoints.at(i)->faces.size(); j++ ) { if ( ((Poly*)initpoints.at(i)->faces.at(j))->normal->angle(*normal) < delta ) { n = n+*(((Poly*)initpoints.at(i)->faces.at(j))->normal); } } n = n.normalize(); glBegin(GL_LINES); nc.drawColor(); glVertex3fv((*initpoints.at(i)).c); glVertex3fv((*initpoints.at(i)+(n * 1.5f)).c); glEnd(); } } } glBegin (GL_POLYGON); for ( std::vector<Vec*>::size_type i = 0; i < vcount; i++ ) { if ( delta <= 0.0f ) { /* face normal */ glNormal3fv(normal->c); } else { /* vertex normal (delta) */ n.c[0] = 0.0f; n.c[1] = 0.0f; n.c[2] = 0.0f; n = n+*normal; for ( std::vector<SPoly*>::size_type j = 0; j < initpoints.at(i)->faces.size(); j++ ) { if ( ((Poly*)initpoints.at(i)->faces.at(j))->normal->angle(*normal) < delta ) { n = n+*(((Poly*)initpoints.at(i)->faces.at(j))->normal); } } n = n.normalize(); glNormal3fv(n.c); } color->drawColor(); glVertex3fv((*initpoints.at(i)).c); } glEnd(); //restore camera position glPopMatrix(); } int Poly::numPoints() { return (int)initpoints.size(); } void Poly::vardump(std::string whitespace) { printf("%sPoly(%d points, center: [%f, %f, %f], rotation: [%f, %f, %f], color: [%f, %f, %f])\n", whitespace.c_str(), initpoints.size(), position->x(), position->y(), position->z(), rotation->x(), rotation->y(), rotation->z(), color->r, color->g, color->b ); for (std::vector<Vec*>::size_type i = 0 ; i < initpoints.size(); i++ ) { initpoints.at(i)->vardump(whitespace+" "); } } void Poly::addPoint(Vec* p) { p->registerFace(this); initpoints.push_back(p); if ( initpoints.size() > 2 ) { this->calcNormal(); } } void Poly::setColor(Color c) { color = c.clone(); } void Poly::setColor(Color* c) { color = c->clone(); } Color* Poly::getColor() { return color; } void Poly::setDelta(float d) { delta = d; } void Poly::showNormals() { drawNormals = true; } void Poly::hideNormals() { drawNormals = false; } Poly* Poly::clone() { Poly* np = new Poly(); for (std::vector<Vec*>::size_type i = 0 ; i < initpoints.size(); i++ ) { np->addPoint(initpoints.at(i)->clone()); } if ( drawNormals ) { np->showNormals(); } else { np->hideNormals(); } np->setDelta(delta); np->setCenter(position); np->setColor(color); return np; }