// -*- C++ -*- #include #include #include "fan.h" #include "material.h" #include "physics/particle.h" #include "physics/shape.h" using namespace mbostock; namespace mbostock { class StaticFanModel : public Model { public: StaticFanModel(float r); virtual ~StaticFanModel(); virtual void initialize(); virtual void display(); void setMaterial(const Material& m); private: void displayBlades(); const Material* material_; AxisAlignedBox bladeBox_; AxisAlignedBoxModel bladeModel_; GLUquadric* quadric_; float r_; }; } StaticFanModel::StaticFanModel(float r) : material_(&Materials::blank()), bladeBox_(Vector(0.f, 0.f, 0.f), Vector(r, r / 10.f, r / 20.f)), bladeModel_(bladeBox_), quadric_(NULL), r_(r) { } StaticFanModel::~StaticFanModel() { if (quadric_ != NULL) { gluDeleteQuadric(quadric_); } } void StaticFanModel::setMaterial(const Material& m) { material_ = &m; bladeModel_.setMaterial(m); } void StaticFanModel::initialize() { if (quadric_ != NULL) { gluDeleteQuadric(quadric_); } quadric_ = gluNewQuadric(); bladeModel_.initialize(); } void StaticFanModel::display() { float axleLength = r_ / 10.f * 1.5; float axleRadius = r_ / 20.f; material_->bind(); glPushMatrix(); glTranslatef(0.f, 0.f, axleLength); gluSphere(quadric_, axleRadius, 16, 16); glPopMatrix(); gluCylinder(quadric_, axleRadius, axleRadius, axleLength, 16, 4); gluQuadricOrientation(quadric_, GLU_INSIDE); gluDisk(quadric_, 0.f, axleRadius, 16, 4); gluQuadricOrientation(quadric_, GLU_OUTSIDE); displayBlades(); } void StaticFanModel::displayBlades() { int blades = 12; for (int i = 0, n = blades; i < n; i++) { glPushMatrix(); glRotatef(i * 360.f / n, 0.f, 0.f, 1.f); glRotatef(60.f, 1.f, 0.f, 0.f); bladeModel_.display(); glPopMatrix(); } } FanModel::FanModel(const Fan& fan) : fan_(fan), staticModel_(new StaticFanModel(fan.cylinder_.radius())), compiledModel_(Models::compile(staticModel_)) { for (int i = 0; i < 15; i++) { orientation_[i] = 0.f; } orientation_[15] = 1.f; } FanModel::~FanModel() { delete compiledModel_; } float* FanModel::orientation() { const Vector& z = fan_.cylinder_.z(); const Vector& n = (fabsf(z.z) > .5f) ? Vector::Y() : Vector::Z(); const Vector& x = n.cross(z); const Vector& y = -x.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 FanModel::setMaterial(const Material& m) { staticModel_->setMaterial(m); } void FanModel::initialize() { compiledModel_->initialize(); } void FanModel::display() { glPushMatrix(); glTranslatev(fan_.cylinder_.x0()); glMultMatrixf(orientation()); glRotatef(fan_.a_, 0.f, 0.f, 1.f); compiledModel_->display(); glPopMatrix(); } Fan::Fan(const Vector& x, const Vector& v, float r, float s) : cylinder_(x, x + v * (r / 10.f), r), s_(s * ParticleSimulator::timeStep()), a_(0.f), model_(*this) { } Model& Fan::model() { return model_; } const Shape& Fan::shape() const { return cylinder_; } void Fan::step(const ParticleSimulator& s) { a_ += s_; } void Fan::reset() { a_ = 0.f; }