// -*- C++ -*- #ifndef MBOSTOCK_MODEL_H #define MBOSTOCK_MODEL_H #include #include "physics/shape.h" #include "physics/vector.h" namespace mbostock { class Material; /** * A generic base class for OpenGL models. Provides a set of convenience * methods based on the Vector class. The constructor should not assume that * OpenGL is initialized; instead, use the initialize method. Note that a * model may be initialized multiple times if the OpenGL context is destroyed * and recreated, as is the case with resizing the window or toggling * fullscreen mode. */ class Model { public: virtual ~Model() {} /** Initializes any OpenGL state used by the model. */ virtual void initialize() {} /** Displays the model. */ virtual void display() = 0; protected: /** A convenience wrapper for glTranslatef. */ inline void glTranslatev(const Vector& v) const { glTranslatef(v.x, v.y, v.z); } /** A convenience wrapper for glRotatef. */ inline void glRotatev(float angle, const Vector& axis) const { glRotatef(angle, axis.x, axis.y, axis.z); } /** A convenience wrapper for glVertex3f. */ inline void glVertexv(const Vector& v) const { glVertex3f(v.x, v.y, v.z); } /** A convenience wrapper for glTexCoord2f. Uses the x and y coordinate. */ inline void glTexCoordv(const Vector& v) const { glTexCoord2f(v.x, v.y); } /** A convenience wrapper for glNormal3f. */ inline void glNormalv(const Vector& v) const { glNormal3f(v.x, v.y, v.z); } /** A convenience wrapper for glMaterialfv. */ inline void glMaterialv(GLenum face, GLenum pname, const Vector& v) const { GLfloat params[] = { v.x, v.y, v.z, 1.f }; glMaterialfv(face, pname, params); } /** A convenience wrapper for glColor3f. */ inline void glColorv(const Vector& v) const { glColor3f(v.x, v.y, v.z); } }; /** * A model for Wedge. A separate material may be specified for the top face of * the wedge. */ class WedgeModel : public Model { public: WedgeModel(const Wedge& wedge); virtual void display(); void setMaterial(const Material& m); void setTopMaterial(const Material& m); inline const Material& material() const { return *material_; } const Material& topMaterial() const; private: const Wedge& wedge_; const Material* material_; const Material* topMaterial_; }; /** * A model for AxisAlignedBox. A separate material may be specified for the * top face of the box. In addition, the texture may be oriented along either * the X or Z axis, and the texture may be offset (e.g., for escalatars). */ class AxisAlignedBoxModel : public Model { public: AxisAlignedBoxModel(const AxisAlignedBox& box); virtual void display(); enum Orientation { POSITIVE_X, NEGATIVE_X, POSITIVE_Z, NEGATIVE_Z }; void setMaterial(const Material& m); void setTopMaterial(const Material& m); void setTexOffset(float u, float v); void setTexOrientation(Orientation orientation); inline const Material& material() const { return *material_; } const Material& topMaterial() const; private: const AxisAlignedBox& box_; const Material* material_; const Material* topMaterial_; Orientation orientation_; float u_, v_; }; /** * A model for Box. A separate material may be specified for the top face of * the box. */ class BoxModel : public Model { public: BoxModel(const Box& box); virtual void display(); void setMaterial(const Material& m); void setTopMaterial(const Material& m); inline const Material& material() const { return *material_; } const Material& topMaterial() const; private: const Box& box_; const Material* material_; const Material* topMaterial_; }; /** * A model for Quad. The texture coordinates may be specified explicitly, or * they will be inferred from the vertex coordinates. */ class QuadModel : public Model { public: QuadModel(const Quad& quad); virtual void display(); void setMaterial(const Material& m); void setTexCoords(const Vector& t0, const Vector& t1, const Vector& t2, const Vector& t3); inline const Material& material() const { return *material_; } private: void displaySide(bool front); const Quad& quad_; const Material* material_; Vector texCoords_[4]; }; /** * A model for Triangle. The texture coordinates may be specified explicitly, * or they will be inferred from the vertex coordinates. */ class TriangleModel : public Model { public: TriangleModel(const Triangle& triangle); virtual void display(); void setMaterial(const Material& m); void setTexCoords(const Vector& t0, const Vector& t1, const Vector& t2); inline const Material& material() const { return *material_; } private: void displaySide(bool front); const Triangle& triangle_; const Material* material_; Vector texCoords_[3]; }; /** * A cylinder model. A separate material may be specified for the end caps. An * additional Y-axis is required to orient the texture on the cylinder's * surface; this axis must be orthogonal to the main axis of the cylinder. A * reference to the Y-axis vector is retained so that changes to the Y-axis * will be propagated to the displayed model. */ class CylinderModel : public Model { public: CylinderModel(const Cylinder& cylinder, const Vector& y); virtual ~CylinderModel(); virtual void initialize(); virtual void display(); void setMaterial(const Material& m); void setCapMaterial(const Material& m); inline const Material& material() const { return *material_; } const Material& capMaterial() const; private: float* orientation(); const Cylinder& cylinder_; const Vector& y_; const Material* material_; const Material* capMaterial_; GLUquadric* quadric_; float orientation_[16]; }; /** A model for Sphere. */ class SphereModel : public Model { public: SphereModel(const Sphere& sphere); virtual ~SphereModel(); virtual void initialize(); virtual void display(); void setMaterial(const Material& m); inline const Material& material() const { return *material_; } private: float* orientation(); const Sphere& sphere_; const Material* material_; GLUquadric* quadric_; float orientation_[16]; }; class Models { public: static Model* teapot(); static Model* icosahedron(); static Model* compile(Model* model); private: Models(); }; } #endif