Initial commit.

This commit is contained in:
Mike Bostock 2012-12-14 09:47:48 -08:00
commit 44b5f2392f
98 changed files with 11750 additions and 0 deletions

607
model.cpp Normal file
View file

@ -0,0 +1,607 @@
// -*- C++ -*-
#include <GLUT/glut.h>
#include <OpenGL/glu.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include "material.h"
#include "model.h"
using namespace mbostock;
WedgeModel::WedgeModel(const Wedge& wedge)
: wedge_(wedge), material_(&Materials::blank()), topMaterial_(NULL) {
}
void WedgeModel::setMaterial(const Material& m) {
material_ = &m;
}
void WedgeModel::setTopMaterial(const Material& m) {
topMaterial_ = &m;
}
const Material& WedgeModel::topMaterial() const {
return (topMaterial_ == NULL) ? *material_ : *topMaterial_;
}
void WedgeModel::display() {
Vector size = wedge_.x2() - wedge_.x0();
/* Top. */
((topMaterial_ != NULL) ? topMaterial_ : material_)->bind();
glBegin(GL_QUADS);
glNormalv(wedge_.top().normal());
glTexCoord2f(0, 0);
glVertexv(wedge_.x0());
glTexCoord2f(sqrtf(size.x * size.x + size.y * size.y), 0);
glVertexv(wedge_.x1());
glTexCoord2f(sqrtf(size.x * size.x + size.y * size.y), size.z);
glVertexv(wedge_.x2());
glTexCoord2f(0, size.z);
glVertexv(wedge_.x3());
glEnd();
material_->bind();
glBegin(GL_QUADS);
/* Right. */
glNormalv(wedge_.right().normal());
glTexCoord2f(size.z, size.y);
glVertexv(wedge_.x2());
glTexCoord2f(0, size.y);
glVertexv(wedge_.x1());
glTexCoord2f(0, 0);
glVertexv(wedge_.x4());
glTexCoord2f(size.z, 0);
glVertexv(wedge_.x5());
/* Bottom. */
glNormalv(wedge_.bottom().normal());
glTexCoord2f(0, 0);
glVertexv(wedge_.x0());
glTexCoord2f(0, size.z);
glVertexv(wedge_.x3());
glTexCoord2f(size.x, size.z);
glVertexv(wedge_.x5());
glTexCoord2f(size.x, 0);
glVertexv(wedge_.x4());
glEnd();
glBegin(GL_TRIANGLES);
/* Front. */
glNormalv(wedge_.front().normal());
glTexCoord2f(size.x, size.y);
glVertexv(wedge_.x1());
glTexCoord2f(0, 0);
glVertexv(wedge_.x0());
glTexCoord2f(size.x, 0);
glVertexv(wedge_.x4());
/* Back. */
glNormalv(wedge_.back().normal());
glTexCoord2f(0, 0);
glVertexv(wedge_.x3());
glTexCoord2f(size.x, size.y);
glVertexv(wedge_.x2());
glTexCoord2f(size.x, 0);
glVertexv(wedge_.x5());
glEnd();
}
AxisAlignedBoxModel::AxisAlignedBoxModel(const AxisAlignedBox& box)
: box_(box), material_(&Materials::blank()), topMaterial_(NULL),
orientation_(POSITIVE_X), u_(0.f), v_(0.f) {
}
void AxisAlignedBoxModel::setMaterial(const Material& m) {
material_ = &m;
}
void AxisAlignedBoxModel::setTopMaterial(const Material& m) {
topMaterial_ = &m;
}
const Material& AxisAlignedBoxModel::topMaterial() const {
return (topMaterial_ == NULL) ? *material_ : *topMaterial_;
}
void AxisAlignedBoxModel::display() {
Vector size = box_.x7() - box_.x0();
Vector t4, t5, t6, t7;
switch (orientation_) {
case POSITIVE_X: {
t4 = Vector(size.x + u_, 0, v_);
t5 = Vector(u_, 0, v_);
t6 = Vector(u_, 0, size.z + v_);
t7 = Vector(size.x + u_, 0, size.z + v_);
break;
}
case POSITIVE_Z: {
t5 = Vector(v_, 0, u_);
t6 = Vector(size.z + v_, 0, u_);
t7 = Vector(size.z + v_, 0, size.x + u_);
t4 = Vector(v_, 0, size.x + u_);
break;
}
case NEGATIVE_X: {
t4 = Vector(-u_, 0, v_);
t5 = Vector(size.x - u_, 0, v_);
t6 = Vector(size.x - u_, 0, size.z + v_);
t7 = Vector(-u_, 0, size.z + v_);
break;
}
case NEGATIVE_Z: {
t5 = Vector(size.z - v_, 0, -u_);
t6 = Vector(-v_, 0, -u_);
t7 = Vector(-v_, 0, size.x - u_);
t4 = Vector(size.z - v_, 0, size.x - u_);
break;
}
}
Vector y(0, size.y, 0);
Vector t0 = t5 + y;
Vector t1 = t4 + y;
Vector t2 = t7 + y;
Vector t3 = t6 + y;
/* Top. */
((topMaterial_ != NULL) ? topMaterial_ : material_)->bind();
glBegin(GL_QUADS);
glNormal3f(0.f, 1.f, 0.f);
glTexCoord2f(t4.x, t4.z);
glVertexv(box_.x4());
glTexCoord2f(t5.x, t5.z);
glVertexv(box_.x5());
glTexCoord2f(t6.x, t6.z);
glVertexv(box_.x6());
glTexCoord2f(t7.x, t7.z);
glVertexv(box_.x7());
glEnd();
material_->bind();
glBegin(GL_QUADS);
/* Bottom. */
glNormal3f(0.f, -1.f, 0.f);
glTexCoord2f(t0.x, t0.z);
glVertexv(box_.x0());
glTexCoord2f(t1.x, t1.z);
glVertexv(box_.x1());
glTexCoord2f(t2.x, t2.z);
glVertexv(box_.x2());
glTexCoord2f(t3.x, t3.z);
glVertexv(box_.x3());
/* Front. */
glNormal3f(0.f, 0.f, 1.f);
glTexCoord2f(t7.x, t7.y);
glVertexv(box_.x7());
glTexCoord2f(t6.x, t6.y);
glVertexv(box_.x6());
glTexCoord2f(t3.x, t3.y);
glVertexv(box_.x3());
glTexCoord2f(t2.x, t2.y);
glVertexv(box_.x2());
/* Back. */
glNormal3f(0.f, 0.f, -1.f);
glTexCoord2f(t5.x, t5.y);
glVertexv(box_.x5());
glTexCoord2f(t4.x, t4.y);
glVertexv(box_.x4());
glTexCoord2f(t1.x, t1.y);
glVertexv(box_.x1());
glTexCoord2f(t0.x, t0.y);
glVertexv(box_.x0());
/* Left. */
glNormal3f(-1.f, 0.f, 0.f);
glTexCoord2f(t6.z, t6.y);
glVertexv(box_.x6());
glTexCoord2f(t5.z, t5.y);
glVertexv(box_.x5());
glTexCoord2f(t0.z, t0.y);
glVertexv(box_.x0());
glTexCoord2f(t3.z, t3.y);
glVertexv(box_.x3());
/* Right. */
glNormal3f(1.f, 0.f, 0.f);
glTexCoord2f(t4.z, t4.y);
glVertexv(box_.x4());
glTexCoord2f(t7.z, t7.y);
glVertexv(box_.x7());
glTexCoord2f(t2.z, t2.y);
glVertexv(box_.x2());
glTexCoord2f(t1.z, t1.y);
glVertexv(box_.x1());
glEnd();
}
void AxisAlignedBoxModel::setTexOffset(float u, float v) {
u_ = u;
v_ = v;
}
void AxisAlignedBoxModel::setTexOrientation(Orientation orientation) {
orientation_ = orientation;
}
BoxModel::BoxModel(const Box& box)
: box_(box), material_(&Materials::blank()), topMaterial_(NULL) {
}
void BoxModel::setMaterial(const Material& m) {
material_ = &m;
}
void BoxModel::setTopMaterial(const Material& m) {
topMaterial_ = &m;
}
const Material& BoxModel::topMaterial() const {
return (topMaterial_ == NULL) ? *material_ : *topMaterial_;
}
void BoxModel::display() {
Vector size(
(box_.x1() - box_.x0()).length(),
(box_.x5() - box_.x0()).length(),
(box_.x3() - box_.x0()).length());
Vector t4(size.x, 0, 0);
Vector t5(0, 0, 0);
Vector t6(0, 0, size.z);
Vector t7(size.x, 0, size.z);
Vector y(0, size.y, 0);
Vector t0 = t5 + y;
Vector t1 = t4 + y;
Vector t2 = t7 + y;
Vector t3 = t6 + y;
/* Top. */
((topMaterial_ != NULL) ? topMaterial_ : material_)->bind();
glBegin(GL_QUADS);
glNormalv(box_.top().normal());
glTexCoord2f(t4.x, t4.z);
glVertexv(box_.x4());
glTexCoord2f(t5.x, t5.z);
glVertexv(box_.x5());
glTexCoord2f(t6.x, t6.z);
glVertexv(box_.x6());
glTexCoord2f(t7.x, t7.z);
glVertexv(box_.x7());
glEnd();
material_->bind();
glBegin(GL_QUADS);
/* Bottom. */
glNormalv(box_.bottom().normal());
glTexCoord2f(t0.x, t0.z);
glVertexv(box_.x0());
glTexCoord2f(t1.x, t1.z);
glVertexv(box_.x1());
glTexCoord2f(t2.x, t2.z);
glVertexv(box_.x2());
glTexCoord2f(t3.x, t3.z);
glVertexv(box_.x3());
/* Front. */
glNormalv(box_.front().normal());
glTexCoord2f(t7.x, t7.y);
glVertexv(box_.x7());
glTexCoord2f(t6.x, t6.y);
glVertexv(box_.x6());
glTexCoord2f(t3.x, t3.y);
glVertexv(box_.x3());
glTexCoord2f(t2.x, t2.y);
glVertexv(box_.x2());
/* Back. */
glNormalv(box_.back().normal());
glTexCoord2f(t5.x, t5.y);
glVertexv(box_.x5());
glTexCoord2f(t4.x, t4.y);
glVertexv(box_.x4());
glTexCoord2f(t1.x, t1.y);
glVertexv(box_.x1());
glTexCoord2f(t0.x, t0.y);
glVertexv(box_.x0());
/* Left. */
glNormalv(box_.left().normal());
glTexCoord2f(t6.z, t6.y);
glVertexv(box_.x6());
glTexCoord2f(t5.z, t5.y);
glVertexv(box_.x5());
glTexCoord2f(t0.z, t0.y);
glVertexv(box_.x0());
glTexCoord2f(t3.z, t3.y);
glVertexv(box_.x3());
/* Right. */
glNormalv(box_.right().normal());
glTexCoord2f(t4.z, t4.y);
glVertexv(box_.x4());
glTexCoord2f(t7.z, t7.y);
glVertexv(box_.x7());
glTexCoord2f(t2.z, t2.y);
glVertexv(box_.x2());
glTexCoord2f(t1.z, t1.y);
glVertexv(box_.x1());
glEnd();
}
QuadModel::QuadModel(const Quad& quad)
: quad_(quad), material_(&Materials::blank()) {
float x = (quad_.x1() - quad_.x0()).length();
float y = (quad_.x3() - quad_.x0()).length();
if (x < y) {
texCoords_[0] = Vector(0, 0);
texCoords_[1] = Vector(0, x);
texCoords_[2] = Vector(y, x);
texCoords_[3] = Vector(y, 0);
} else {
texCoords_[0] = Vector(0, 0);
texCoords_[1] = Vector(x, 0);
texCoords_[2] = Vector(x, y);
texCoords_[3] = Vector(0, y);
}
}
void QuadModel::setMaterial(const Material& m) {
material_ = &m;
}
void QuadModel::setTexCoords(const Vector& t0, const Vector& t1,
const Vector& t2, const Vector& t3) {
texCoords_[0] = t0;
texCoords_[1] = t1;
texCoords_[2] = t2;
texCoords_[3] = t3;
}
void QuadModel::display() {
material_->bind();
displaySide(true);
glFrontFace(GL_CW);
displaySide(false);
glFrontFace(GL_CCW);
}
void QuadModel::displaySide(bool front) {
glBegin(GL_QUADS);
glNormalv(front ? quad_.normal() : -quad_.normal());
glTexCoordv(texCoords_[0]);
glVertexv(quad_.x0());
glTexCoordv(texCoords_[1]);
glVertexv(quad_.x1());
glTexCoordv(texCoords_[2]);
glVertexv(quad_.x2());
glTexCoordv(texCoords_[3]);
glVertexv(quad_.x3());
glEnd();
}
TriangleModel::TriangleModel(const Triangle& triangle)
: triangle_(triangle), material_(&Materials::blank()) {
float x = (triangle_.x1() - triangle_.x0()).length();
float y = (triangle_.x2() - triangle_.x0()).length();
texCoords_[0] = Vector(0, 0);
texCoords_[1] = Vector(x, 0);
texCoords_[2] = Vector(x, y);
}
void TriangleModel::setMaterial(const Material& m) {
material_ = &m;
}
void TriangleModel::setTexCoords(const Vector& t0, const Vector& t1,
const Vector& t2) {
texCoords_[0] = t0;
texCoords_[1] = t1;
texCoords_[2] = t2;
}
void TriangleModel::display() {
material_->bind();
displaySide(true);
glFrontFace(GL_CW);
displaySide(false);
glFrontFace(GL_CCW);
}
void TriangleModel::displaySide(bool front) {
glBegin(GL_TRIANGLES);
glNormalv(front ? triangle_.normal() : -triangle_.normal());
glTexCoordv(texCoords_[0]);
glVertexv(triangle_.x0());
glTexCoordv(texCoords_[1]);
glVertexv(triangle_.x1());
glTexCoordv(texCoords_[2]);
glVertexv(triangle_.x2());
glEnd();
}
CylinderModel::CylinderModel(const Cylinder& cylinder, const Vector& y)
: cylinder_(cylinder), y_(y),
material_(&Materials::blank()), capMaterial_(NULL),
quadric_(NULL) {
for (int i = 0; i < 15; i++) {
orientation_[i] = 0.f;
}
orientation_[15] = 1.f;
}
CylinderModel::~CylinderModel() {
if (quadric_ != NULL) {
gluDeleteQuadric(quadric_);
}
}
void CylinderModel::initialize() {
if (quadric_ != NULL) {
gluDeleteQuadric(quadric_);
}
quadric_ = gluNewQuadric();
}
float* CylinderModel::orientation() {
const Vector& z = cylinder_.z();
const Vector& y = y_;
const Vector& x = y.cross(z);
orientation_[0] = x.x; orientation_[1] = x.y; orientation_[2] = x.z;
orientation_[4] = y.x; orientation_[5] = y.y; orientation_[6] = y.z;
orientation_[8] = z.x; orientation_[9] = z.y; orientation_[10] = z.z;
return orientation_;
}
void CylinderModel::setMaterial(const Material& m) {
material_ = &m;
}
void CylinderModel::setCapMaterial(const Material& m) {
capMaterial_ = &m;
}
const Material& CylinderModel::capMaterial() const {
return (capMaterial_ == NULL) ? *material_ : *capMaterial_;
}
void CylinderModel::display() {
float r = cylinder_.radius();
float l = cylinder_.length();
int slices = std::max(16, (int) roundf(64 * r * r));
int loops = 1;
int stacks = 1;
glPushMatrix();
glTranslatev(cylinder_.x0());
glMultMatrixf(orientation());
gluQuadricTexture(quadric_, GL_TRUE);
material_->bind();
gluCylinder(quadric_, r, r, l, slices, stacks);
glPushMatrix();
glRotatef(180.f, 0.f, 1.f, 0.f);
((capMaterial_ != NULL) ? capMaterial_ : material_)->bind();
gluDisk(quadric_, 0.f, r, slices, loops);
glPopMatrix();
glTranslatef(0.f, 0.f, l);
gluDisk(quadric_, 0.f, r, slices, loops);
gluQuadricTexture(quadric_, GL_FALSE);
glPopMatrix();
}
SphereModel::SphereModel(const Sphere& sphere)
: sphere_(sphere), material_(&Materials::blank()), quadric_(NULL) {
}
SphereModel::~SphereModel() {
if (quadric_ != NULL) {
gluDeleteQuadric(quadric_);
}
}
void SphereModel::initialize() {
if (quadric_ != NULL) {
gluDeleteQuadric(quadric_);
}
quadric_ = gluNewQuadric();
}
void SphereModel::setMaterial(const Material& m) {
material_ = &m;
}
void SphereModel::display() {
float r2 = sphere_.radius() * sphere_.radius();
int slices = std::max(16, (int) roundf(32 * r2));
int stacks = std::max(4, (int) roundf(8 * r2));
material_->bind();
glPushMatrix();
glTranslatev(sphere_.x());
gluQuadricTexture(quadric_, GL_TRUE);
gluSphere(quadric_, sphere_.radius(), slices, stacks);
gluQuadricTexture(quadric_, GL_FALSE);
glPopMatrix();
}
static Model* teapotModel_ = NULL;
static Model* icosahedronModel_ = NULL;
class TeapotModel : public Model {
public:
virtual void display() {
glFrontFace(GL_CW);
glutSolidTeapot(1.f);
glFrontFace(GL_CCW);
}
};
class IcosahedronModel : public Model {
public:
virtual void display() {
glutSolidIcosahedron();
}
};
class DisplayListModel : public Model {
public:
DisplayListModel(Model* model)
: model_(model), displayList_(GL_NONE) {
}
virtual ~DisplayListModel() {
if (displayList_ != GL_NONE) {
glDeleteLists(displayList_, 1);
}
delete model_;
}
virtual void initialize() {
if (displayList_ != GL_NONE) {
glDeleteLists(displayList_, 1);
}
displayList_ = glGenLists(1);
glNewList(displayList_, GL_COMPILE);
model_->initialize();
model_->display();
glEndList();
}
virtual void display() {
glCallList(displayList_);
}
private:
Model* model_;
GLuint displayList_;
};
Model* Models::compile(Model* model) {
return new DisplayListModel(model);
}
Model* Models::teapot() {
if (teapotModel_ == NULL) {
teapotModel_ = new TeapotModel();
}
return teapotModel_;
}
Model* Models::icosahedron() {
if (icosahedronModel_ == NULL) {
icosahedronModel_ = new IcosahedronModel();
}
return icosahedronModel_;
}