#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() { 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; 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()); //normal Vec cur = rotate_xyz(*initpoints.at(1) - *position); Vec prev = rotate_xyz(*initpoints.at(0) - *position); Vec next = rotate_xyz(*initpoints.at(2) - *position); prev = prev - cur; next = next - cur; normal = prev.cross(next).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(); } /* * 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(diff); } } //additional rotation in arcs void Poly::rotate(Vec rot) { rotation->add(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); 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); glBegin (GL_POLYGON); for ( std::vector<Vec*>::size_type i = 0; i < vcount; i++ ) { /* face normal */ //glNormal3fv(normal->c); /* TODO: vertex normal */ 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); } } glNormal3fv(n.c); color->drawColor(); glVertex3fv((*initpoints.at(i) - *position).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); } void Poly::setColor(Color c) { color = c.clone(); } Color* Poly::getColor() { return color; } void Poly::setDelta(float d) { delta = d; }