#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; scaleFactor = 1.0f; position = new Vec(0,0,0); center = new Vec(0,0,0); rotation = new Vec(0,0,0); material = new Material(); normal = new Vec(0,0,0); } Poly::Poly(std::vector<Vec*> & _points) { Poly(_points, Material()); //TODO: this wont work. segmentation fault. material->ptdump("b"); } Poly::Poly(std::vector<Vec*> & _points, Color _color) { delta = 0.0f; scaleFactor = 1.0f; drawNormals = false; position = new Vec(0,0,0); rotation = new Vec(0,0,0); center = new Vec(0,0,0); normal = new Vec(0,0,0); material = new Material(_color); for (std::vector<Vec*>::size_type i = 0 ; i < _points.size(); i++ ) { addPoint(_points.at(i)); } //setCenter(calcCenter()); } Poly::Poly(std::vector<Vec*> & _points, Material _material) { delta = 0.0f; scaleFactor = 1.0f; drawNormals = false; position = new Vec(0,0,0); rotation = new Vec(0,0,0); material = _material.clone(); center = new Vec(0,0,0); normal = new Vec(0,0,0); 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 material; delete normal; } /* * set the position where the (rotation-)center of * the polygon is located */ void Poly::setCenter(Vec c) { delete center; center = c.clone(); } void Poly::setCenter(Vec* c) { delete center; center = 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) { delete position; position = newcenter.clone(); } void Poly::setPosition(Vec* newcenter) { delete position; position = newcenter->clone(); } void Poly::setRotation(Vec rot) { delete rotation; rotation = rot.clone(); } void Poly::setRotation(Vec* rot) { delete rotation; rotation = rot->clone(); } //additional rotation in arcs void Poly::rotate(Vec rot) { rotation->add((Vec)rot); } 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 on origin //glTranslatef(-center->x(), -center->y(), -center->z()); glTranslatef(center->x(), center->y(), center->z()); //move to origin 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); //move to origin //glTranslatef(position->x(), position->y(), position->z()); //center on origin glTranslatef(center->x(), center->y(), center->z()); //scale glScalef(scaleFactor, scaleFactor, scaleFactor); 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); } material->draw(); 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]\n", whitespace.c_str(), initpoints.size(), position->x(), position->y(), position->z(), rotation->x(), rotation->y(), rotation->z() ); 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) { delete material; material = new Material(c, Color(0,0,0)); } void Poly::setColor(Color* c) { delete material; Color sc = *c; material = new Material(sc, Color(0,0,0)); } Material* Poly::getMaterial() { return material; } void Poly::setMaterial(Material *m){ delete material; material = m->clone(); } void Poly::setMaterial(Material m){ delete material; material = m.clone(); } 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->setMaterial(material); np->setPosition(position); np->setCenter(center); np->setRotation(rotation); np->scale(scaleFactor); return np; } void Poly::translate(Vec d) { position->add((Vec)d); } void Poly::scale(float f) { scaleFactor *= f; }