From 25aefe01ef7dbdb603c51411e04b0d6a6107684f Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Mon, 21 Sep 2009 18:34:49 -0600 Subject: [PATCH] refactoring the scene class --- src/Character.cc | 44 +-- src/Character.hh | 6 +- src/Hud.hh | 4 +- src/Moof/Aabb.cc | 6 +- src/Moof/Aabb.hh | 12 +- src/Moof/Cullable.hh | 7 +- src/Moof/Drawable.hh | 2 +- src/Moof/Entity.hh | 10 +- src/Moof/Frustum.hh | 4 +- src/Moof/Mippleton.hh | 11 +- src/Moof/Octree.cc | 12 +- src/Moof/Octree.hh | 22 +- src/Moof/Plane.hh | 4 +- src/Moof/Rectangle.hh | 4 +- src/Moof/RigidBody.hh | 4 +- src/Moof/Scene.cc | 711 ++++++++++++++++-------------------------- src/Moof/Scene.hh | 96 +++++- src/Moof/Sound.hh | 2 +- src/Moof/Sphere.cc | 6 +- src/Moof/Sphere.hh | 4 +- src/Moof/Video.hh | 3 +- src/YoinkApp.cc | 21 +- src/YoinkApp.hh | 2 +- 23 files changed, 456 insertions(+), 541 deletions(-) diff --git a/src/Character.cc b/src/Character.cc index 4ce1105..ac5f8bc 100644 --- a/src/Character.cc +++ b/src/Character.cc @@ -40,7 +40,7 @@ Character::Character(const std::string& name) : current.inverseMass = 1.0 / current.mass; // gravity - //current.force = Mf::Vector2(0.0, -120.0); + current.force = Mf::Vector2(0.0, -120.0); // starting position current.position = Mf::Vector2(64.0, 64.0); @@ -57,22 +57,15 @@ void Character::update(Mf::Scalar t, Mf::Scalar dt) { previous = current; - Mf::Scalar epsilon = 100.0; + Mf::Vector2 x = current.position - Mf::Vector2(500.0, 200.0); + Mf::Scalar mag = x.length(); + Mf::Scalar d = 50.0; - //current.momentum = Mf::Vector2(0.0, -120.0); - current.momentum = -5 * (current.position - Mf::Vector2(500.0, 200.0)) + current.force = -5 * (current.position - Mf::Vector2(500.0, 200.0)) - 2.0 * current.velocity; current.recalculate(); std::cout << "force: " << current.momentum << std::endl; - //if (std::abs(current.force[0]) < epsilon && std::abs(current.force[1]) < epsilon && - //std::abs(current.velocity[0]) < epsilon && std::abs(current.velocity[1]) < epsilon) - //{ - //current.force = Mf::Vector2(0.0, 0.0); - //current.velocity = Mf::Vector2(0.0, 0.0); - //current.momentum = Mf::Vector2(0.0, 0.0); - //} - Mf::integrate(current, t, dt); animation_.update(t, dt); @@ -104,38 +97,38 @@ void Character::handleEvent(const Mf::Event& event) case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_a) { - current.force += left; + userForce += left; } else if (event.key.keysym.sym == SDLK_d) { - current.force += right; + userForce += right; } else if (event.key.keysym.sym == SDLK_s) { - current.force += down; + userForce += down; } else if (event.key.keysym.sym == SDLK_w) { - current.force += up; + userForce += up; } break; case SDL_KEYUP: if (event.key.keysym.sym == SDLK_a) { - current.force -= left; + userForce -= left; } else if (event.key.keysym.sym == SDLK_d) { - current.force -= right; + userForce -= right; } else if (event.key.keysym.sym == SDLK_s) { - current.force -= down; + userForce -= down; } else if (event.key.keysym.sym == SDLK_w) { - current.force -= up; + userForce -= up; } break; } @@ -169,6 +162,17 @@ void Character::draw(Mf::Scalar alpha) const glTexCoord2f(coords[6], coords[7]); glVertex3(state.position[0]-s, state.position[1]+s, z); glEnd(); + + glColor3f(0.0f, 0.0f, 0.0f); + Mf::Texture::resetBind(); + + glBegin(GL_TRIANGLES); + glVertex3(480.0, 190.0, 64.0); + glVertex3(520.0, 190.0, 64.0); + glVertex3(500.0, 210.0, 64.0); + glEnd(); + + glColor3f(1.0f, 1.0f, 1.0f); } diff --git a/src/Character.hh b/src/Character.hh index 00e5a4b..0a3f9f4 100644 --- a/src/Character.hh +++ b/src/Character.hh @@ -143,6 +143,8 @@ private: static const Mf::Scalar z = 96.0; + Mf::Vector2 userForce; + Mf::Tilemap tilemap_; Mf::Animation animation_; @@ -150,13 +152,13 @@ private: public: - inline static CharacterP alloc(const std::string& name) + static CharacterP alloc(const std::string& name) { return CharacterP(new Character(name)); } Character(const std::string& name); - inline virtual ~Character() {} + virtual ~Character() {} void update(Mf::Scalar t, Mf::Scalar dt); void handleEvent(const Mf::Event& event); diff --git a/src/Hud.hh b/src/Hud.hh index 813e67f..8fec549 100644 --- a/src/Hud.hh +++ b/src/Hud.hh @@ -71,13 +71,13 @@ public: Hud(); - inline void setBar1Progress(Mf::Scalar progress) + void setBar1Progress(Mf::Scalar progress) { // pass through bar1_.setProgress(progress); } - inline void setBar2Progress(Mf::Scalar progress) + void setBar2Progress(Mf::Scalar progress) { // pass through bar2_.setProgress(progress); diff --git a/src/Moof/Aabb.cc b/src/Moof/Aabb.cc index 842d9d8..df09cdd 100644 --- a/src/Moof/Aabb.cc +++ b/src/Moof/Aabb.cc @@ -27,7 +27,7 @@ *******************************************************************************/ #include "Aabb.hh" -#include "Camera.hh" +#include "Frustum.hh" #include "OpenGL.hh" #include "Texture.hh" @@ -138,9 +138,9 @@ void Aabb::draw(Scalar alpha) const glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } -bool Aabb::isVisible(const Camera& cam) const +bool Aabb::isVisible(const Frustum& frustum) const { - return cam.getFrustum().contains(*this); + return frustum.contains(*this); } diff --git a/src/Moof/Aabb.hh b/src/Moof/Aabb.hh index 457d198..0f7bbb9 100644 --- a/src/Moof/Aabb.hh +++ b/src/Moof/Aabb.hh @@ -64,7 +64,7 @@ struct Aabb : public Cullable, public Drawable init(a, b); } - inline void init(const Vector3& a, const Vector3& b) + void init(const Vector3& a, const Vector3& b) { if (a[0] < b[0]) { @@ -98,7 +98,7 @@ struct Aabb : public Cullable, public Drawable } } - inline Vector3 getCenter() const + Vector3 getCenter() const { return Vector3((min[0] + max[0]) / 2.0, (min[1] + max[1]) / 2.0, @@ -107,7 +107,7 @@ struct Aabb : public Cullable, public Drawable void getOctant(Aabb& octant, int num) const; - inline Plane getPlaneXY() const + Plane getPlaneXY() const { Plane plane; plane.normal = Vector3(0.0, 0.0, 1.0); @@ -115,7 +115,7 @@ struct Aabb : public Cullable, public Drawable return plane; } - inline Plane getPlaneXZ() const + Plane getPlaneXZ() const { Plane plane; plane.normal = Vector3(0.0, 1.0, 0.0); @@ -123,7 +123,7 @@ struct Aabb : public Cullable, public Drawable return plane; } - inline Plane getPlaneYZ() const + Plane getPlaneYZ() const { Plane plane; plane.normal = Vector3(1.0, 0.0, 0.0); @@ -136,7 +136,7 @@ struct Aabb : public Cullable, public Drawable void encloseVertices(const Vector3 vertices[], unsigned count); void draw(Scalar alpha = 0.0) const; - bool isVisible(const Camera& cam) const; + bool isVisible(const Frustum& frustum) const; }; diff --git a/src/Moof/Cullable.hh b/src/Moof/Cullable.hh index b25840e..64b43eb 100644 --- a/src/Moof/Cullable.hh +++ b/src/Moof/Cullable.hh @@ -33,7 +33,7 @@ namespace Mf { -class Camera; +class Frustum; /** * Interface for anything that can be culled. @@ -42,10 +42,11 @@ class Camera; class Cullable { public: - inline virtual ~Cullable() {} + virtual ~Cullable() {} - inline virtual bool isVisible(const Camera& cam) const + virtual bool isVisible(const Frustum& frustum) const { + // unless determined otherwise, assume visible return true; } }; diff --git a/src/Moof/Drawable.hh b/src/Moof/Drawable.hh index 5cfd628..61283fa 100644 --- a/src/Moof/Drawable.hh +++ b/src/Moof/Drawable.hh @@ -42,7 +42,7 @@ namespace Mf { class Drawable { public: - inline virtual ~Drawable() {} + virtual ~Drawable() {} virtual void draw(Scalar alpha) const = 0; }; diff --git a/src/Moof/Entity.hh b/src/Moof/Entity.hh index 33efcc9..310e0a1 100644 --- a/src/Moof/Entity.hh +++ b/src/Moof/Entity.hh @@ -43,7 +43,7 @@ namespace Mf { class Entity; typedef boost::shared_ptr EntityP; -class Camera; +class Frustum; /** @@ -51,10 +51,10 @@ class Camera; * specified size. */ -class Entity : public Drawable, public Cullable +class Entity : public Cullable, public Drawable { public: - inline virtual ~Entity() {} + virtual ~Entity() {} const Aabb& getAabb() const { @@ -66,9 +66,9 @@ public: return sphere_; } - virtual void drawIfVisible(Scalar alpha, const Camera& cam) const + void drawIfVisible(Scalar alpha, const Frustum& frustum) const { - if (isVisible(cam)) draw(alpha); + if (isVisible(frustum)) draw(alpha); } protected: diff --git a/src/Moof/Frustum.hh b/src/Moof/Frustum.hh index 0d08831..87e654f 100644 --- a/src/Moof/Frustum.hh +++ b/src/Moof/Frustum.hh @@ -52,11 +52,11 @@ public: } Collision; Frustum() {} - inline Frustum(const Matrix4& modelview, const Matrix4& projection) + Frustum(const Matrix4& modelview, const Matrix4& projection) { init(modelview, projection); } - inline Frustum(const Matrix4& modelview, Scalar fovy, Scalar aspect, + Frustum(const Matrix4& modelview, Scalar fovy, Scalar aspect, Scalar abutting, Scalar distant) { init(modelview, fovy, aspect, abutting, distant); diff --git a/src/Moof/Mippleton.hh b/src/Moof/Mippleton.hh index cde68d2..7ad1782 100644 --- a/src/Moof/Mippleton.hh +++ b/src/Moof/Mippleton.hh @@ -57,7 +57,7 @@ class Mippleton static PtrMap ptrs_; std::string name_; - inline static T* retain(const std::string& name) + static T* retain(const std::string& name) { typename PtrMap::iterator it = ptrs_.find(name); @@ -74,12 +74,12 @@ class Mippleton } } - inline static void release(T* obj) + static void release(T* obj) { releaseByName(obj->name_); } - inline static void releaseByName(const std::string& name) + static void releaseByName(const std::string& name) { typename PtrMap::iterator it; @@ -91,15 +91,16 @@ class Mippleton } public: + explicit Mippleton(const std::string& name) : name_(name) {} - inline const std::string& getName() const + const std::string& getName() const { return name_; } - inline static boost::shared_ptr getInstance(const std::string& name) + static boost::shared_ptr getInstance(const std::string& name) { return boost::shared_ptr(retain(name), &release); } diff --git a/src/Moof/Octree.cc b/src/Moof/Octree.cc index 9bb04e8..062788d 100644 --- a/src/Moof/Octree.cc +++ b/src/Moof/Octree.cc @@ -26,7 +26,7 @@ *******************************************************************************/ -#include "Camera.hh" +#include "Frustum.hh" #include "Log.hh" #include "Octree.hh" @@ -238,17 +238,17 @@ void Octree::draw(Scalar alpha, OctreeNodeP node) } } -void Octree::drawIfVisible(Scalar alpha, const Camera& cam, OctreeNodeP node) +void Octree::drawIfVisible(Scalar alpha, const Frustum& frustum, OctreeNodeP node) { ASSERT(node.valid() && "invalid node passed"); // try to cull by sphere Frustum::Collision collision = - cam.getFrustum().contains(node->getSphere()); + frustum.contains(node->getSphere()); if (collision == Frustum::OUTSIDE) return; // try to cull by aabb - collision = cam.getFrustum().contains(node->getAabb()); + collision = frustum.contains(node->getAabb()); if (collision == Frustum::OUTSIDE) return; @@ -258,7 +258,7 @@ void Octree::drawIfVisible(Scalar alpha, const Camera& cam, OctreeNodeP node) } else // collision == Frustum::INTERSECT { - node->drawIfVisible(alpha, cam); + node->drawIfVisible(alpha, frustum); } if (tree_.children(node) > 0) @@ -280,7 +280,7 @@ void Octree::drawIfVisible(Scalar alpha, const Camera& cam, OctreeNodeP node) OctreeNodeP child = tree_.child(node, i); ASSERT(child.valid() && "expected valid child node"); - drawIfVisible(alpha, cam, child); + drawIfVisible(alpha, frustum, child); } } } diff --git a/src/Moof/Octree.hh b/src/Moof/Octree.hh index ade0a02..186961f 100644 --- a/src/Moof/Octree.hh +++ b/src/Moof/Octree.hh @@ -47,7 +47,7 @@ namespace Mf { -class Camera; +class Frustum; struct OctreeNode; @@ -88,13 +88,13 @@ struct OctreeNode : public Entity aabb_.draw(); // temporary } - void drawIfVisible(Scalar alpha, const Camera& cam) const + void drawIfVisible(Scalar alpha, const Frustum& frustum) const { std::list::const_iterator it; for (it = objects.begin(); it != objects.end(); ++it) { - (*it)->drawIfVisible(alpha, cam); + (*it)->drawIfVisible(alpha, frustum); } if (!objects.empty()) @@ -102,11 +102,11 @@ struct OctreeNode : public Entity } - bool isVisible(const Camera& cam) const + bool isVisible(const Frustum& frustum) const { - if (sphere_.isVisible(cam)) + if (sphere_.isVisible(frustum)) { - return aabb_.isVisible(cam); + return aabb_.isVisible(frustum); } return false; @@ -133,20 +133,20 @@ class Octree void addChild(OctreeNodeP node, int index); void draw(Scalar alpha, OctreeNodeP node); - void drawIfVisible(Scalar alpha, const Camera& cam, OctreeNodeP node); + void drawIfVisible(Scalar alpha, const Frustum& frustum, OctreeNodeP node); stlplus::ntree tree_; public: - inline void print(OctreeNodeP node) + void print(OctreeNodeP node) { //logDebug("-----"); //logDebug("depth to node: %d", tree_.depth(node)); //logDebug("size of node: %d", tree_.size(node)); } - inline static OctreeP alloc(const OctreeNode& rootNode) + static OctreeP alloc(const OctreeNode& rootNode) { return OctreeP(new Octree(rootNode)); } @@ -163,9 +163,9 @@ public: OctreeNodeP reinsert(EntityP entity, OctreeNodeP node); - void drawIfVisible(Scalar alpha, const Camera& cam) + void drawIfVisible(Scalar alpha, const Frustum& frustum) { - drawIfVisible(alpha, cam, tree_.root()); + drawIfVisible(alpha, frustum, tree_.root()); } void sort(); diff --git a/src/Moof/Plane.hh b/src/Moof/Plane.hh index 4739bb8..06e4abd 100644 --- a/src/Moof/Plane.hh +++ b/src/Moof/Plane.hh @@ -78,12 +78,12 @@ struct Plane /** * Determine the shortest distance between a point and the plane. */ - inline Scalar getDistanceToPoint(const Vector3& point) const + Scalar getDistanceToPoint(const Vector3& point) const { return cml::dot(point, normal) + d; } - inline Halfspace intersects(const Vector3& point) const + Halfspace intersects(const Vector3& point) const { Scalar distance = getDistanceToPoint(point); diff --git a/src/Moof/Rectangle.hh b/src/Moof/Rectangle.hh index 97bb44a..634491c 100644 --- a/src/Moof/Rectangle.hh +++ b/src/Moof/Rectangle.hh @@ -60,7 +60,7 @@ struct Rectangle init(a, b); } - inline void init(const Vector2& a, const Vector2& b) + void init(const Vector2& a, const Vector2& b) { if (a[0] < b[0]) { @@ -84,7 +84,7 @@ struct Rectangle } } - inline Vector2 getCenter() const + Vector2 getCenter() const { return Vector2((min[0] + max[0]) / 2.0, (min[1] + max[1]) / 2.0); diff --git a/src/Moof/RigidBody.hh b/src/Moof/RigidBody.hh index 11c6354..501f7c9 100644 --- a/src/Moof/RigidBody.hh +++ b/src/Moof/RigidBody.hh @@ -44,7 +44,7 @@ template class RigidBody { public: - inline virtual ~RigidBody() {} + virtual ~RigidBody() {} virtual void update(Scalar t, Scalar dt) { @@ -52,7 +52,7 @@ public: currentState_.integrate(t, dt); } - inline T getInterpolatedState(Scalar alpha) const + T getInterpolatedState(Scalar alpha) const { return currentState_.interpolate(alpha, prevState_); } diff --git a/src/Moof/Scene.cc b/src/Moof/Scene.cc index 4547268..418c051 100644 --- a/src/Moof/Scene.cc +++ b/src/Moof/Scene.cc @@ -35,8 +35,6 @@ #include "Entity.hh" #include "Log.hh" #include "Math.hh" -#include "Mippleton.hh" -#include "OpenGL.hh" #include "Scene.hh" #include "Serializable.hh" #include "Tilemap.hh" @@ -45,540 +43,383 @@ namespace Mf { -class Scene::Impl : public Mippleton +static void loadBox(Aabb& theBox, SerializableP obj) { - class Quad : public Entity - { - public: - Quad(const Vector3 vertices[4], const std::string& texture, - Tilemap::Index tileIndex) : - tilemap_(texture), - detail_(0), - blending_(false), - fog_(false) - { - for (int i = 0, num = 0; i < 4; ++i) - { - for (int j = 0; j < 3; ++j, ++num) - { - vertices_[num] = vertices[i][j]; - } - } - - if (!tilemap_.getTileCoords(tileIndex, texCoords_)) - { - logWarning("no index %d in texture %s", tileIndex, - texture.c_str()); - - texCoords_[0] = texCoords_[1] = - texCoords_[3] = texCoords_[6] = 0.0; - texCoords_[2] = texCoords_[4] = - texCoords_[5] = texCoords_[7] = 1.0; - } - - aabb_.encloseVertices(vertices, 4); - sphere_.point = aabb_.getCenter(); - sphere_.radius = (aabb_.min - sphere_.point).length(); - } - - void setDetail(long detail) - { - detail_ = detail; - } - - void setBlending(bool blending) - { - blending_ = blending; - } - - void setFog(bool fog) - { - fog_ = fog; - } - - void draw(Scalar alpha = 0.0) const - { - if (blending_) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - if (fog_) - { - glEnable(GL_FOG); - glFogi(GL_FOG_MODE, GL_LINEAR); - } - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - tilemap_.bind(); - - glVertexPointer(3, GL_SCALAR, 0, vertices_); - glTexCoordPointer(2, GL_SCALAR, 0, texCoords_); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + Serializable::Array numbers; - glDisable(GL_BLEND); - glDisable(GL_FOG); - } + if (obj->get(numbers) && numbers.size() == 6) + { + Serializable::Float num; + + if (numbers[0]->getNumber(num)) theBox.min[0] = Scalar(num); + if (numbers[1]->getNumber(num)) theBox.min[1] = Scalar(num); + if (numbers[2]->getNumber(num)) theBox.min[2] = Scalar(num); + if (numbers[3]->getNumber(num)) theBox.max[0] = Scalar(num); + if (numbers[4]->getNumber(num)) theBox.max[1] = Scalar(num); + if (numbers[5]->getNumber(num)) theBox.max[2] = Scalar(num); + } +} - bool isVisible(const Camera& cam) const - { - return sphere_.isVisible(cam); - } - private: - Scalar vertices_[12]; - Scalar texCoords_[8]; - - Tilemap tilemap_; +static void loadTilemap(SerializableP root, const Matrix4& transform, + const std::string& texture, OctreeP octree) +{ + Serializable::Map rootObj; + Serializable::Map::iterator it; - long detail_; - bool blending_; - bool fog_; - }; + if (!root->get(rootObj)) + { + logError("invalid tilemap instruction"); + return; + } + long width = 1; + long height = 1; + std::vector< std::vector > indices; - static void loadBox(Aabb& theBox, SerializableP obj) + if ((it = rootObj.find("width")) != rootObj.end()) { - Serializable::Array numbers; - - if (obj->get(numbers) && numbers.size() == 6) - { - Serializable::Float num; - - if (numbers[0]->getNumber(num)) theBox.min[0] = Scalar(num); - if (numbers[1]->getNumber(num)) theBox.min[1] = Scalar(num); - if (numbers[2]->getNumber(num)) theBox.min[2] = Scalar(num); - if (numbers[3]->getNumber(num)) theBox.max[0] = Scalar(num); - if (numbers[4]->getNumber(num)) theBox.max[1] = Scalar(num); - if (numbers[5]->getNumber(num)) theBox.max[2] = Scalar(num); - } + (*it).second->get(width); } - -public: - Impl(const std::string& name) : - Mippleton(name) + else { - loadFromFile(); + logError("missing required field width for tilemap instruction"); + return; } + Serializable::Array tiles; - void loadInstructions(SerializableP root) + if ((it = rootObj.find("tiles")) != rootObj.end() && + (*it).second->get(tiles) && + tiles.size() % width == 0) { - Serializable::Array rootObj; - Serializable::Array::iterator it; + Serializable::Array::iterator jt; + int w, h; - if (!root->get(rootObj)) - { - logError("scene instructions must be an array"); - return; - } + height = tiles.size() / width; + indices.resize(height); - Matrix4 transform; - std::string texture; + // the indices are stored upside-down in the scene file so that they + // are easier to edit as text, so we'll need to load them last row + // first - for (it = rootObj.begin(); it != rootObj.end(); ++it) + for (h = height - 1, jt = tiles.begin(); jt != tiles.end(); --h) { - std::string instruction; + std::vector row; - if ((*it)->get(instruction)) + for (w = 0; w < width && jt != tiles.end(); ++w, ++jt) { - if (instruction == "reset_transform") - { - transform.identity(); - } - else if (instruction == "translate") - { - Serializable::Array values; - - ++it; - if ((*it)->get(values)) - { - Vector3 vec; - - for (size_t i = 0; i < values.size(); ++i) - { - Serializable::Float value; - - if (values[i]->getNumber(value)) - { - vec[i] = value; - } - } + Serializable::Integer index; - Matrix4 translation; - cml::matrix_translation(translation, vec); - transform = translation * transform; - } - } - else if (instruction == "scale") + if ((*jt)->get(index)) { - Serializable::Array values; - - ++it; - if ((*it)->get(values)) - { - if (values.size() == 1) - { - Serializable::Float value = 1.0; + row.push_back(Tilemap::Index(index)); + } + } - values[0]->getNumber(value); + indices[h] = row; + } + } + else + { + logError("invalid tiles in tilemap instruction"); + return; + } - Matrix4 scaling; - cml::matrix_uniform_scale(scaling, - Scalar(value)); - transform = scaling * transform; - } - else if (values.size() == 3) - { - Vector3 vec; + Vector4 vertices[height+1][width+1]; - for (size_t i = 0; i < values.size(); ++i) - { - Serializable::Float value; + Matrix4 transposedTransform = transform; + transposedTransform.transpose(); - if (values[i]->getNumber(value)) - { - vec[i] = value; - } - } + for (int h = 0; h <= height; ++h) + { + for (int w = 0; w <= width; ++w) + { + vertices[h][w] = Vector4(Scalar(w), Scalar(h), 0.0, 1.0) * + transposedTransform; + } + } - Matrix4 scaling; - cml::matrix_scale(scaling, vec); - transform = scaling * transform; - } - } - } - else if (instruction == "rotate") - { - Serializable::Array values; + for (int h = 0; h < height; ++h) + { + for (int w = 0; w < width; ++w) + { + if (indices[h][w] == Tilemap::NO_TILE) continue; - ++it; - if ((*it)->get(values)) - { - if (values.size() == 2) - { - std::string axis; - size_t index = 0; - Serializable::Float value = 0.0; + Vector3 quadVertices[4]; - if (values[0]->get(axis)) - { - if (axis == "x") index = 0; - else if (axis == "y") index = 1; - else if (axis == "z") index = 2; + demoteVector(quadVertices[0], vertices[h][w]); + demoteVector(quadVertices[1], vertices[h][w+1]); + demoteVector(quadVertices[2], vertices[h+1][w+1]); + demoteVector(quadVertices[3], vertices[h+1][w]); - values[1]->getNumber(value); - } + Quad* quad = new Quad(quadVertices, texture, indices[h][w]); + boost::shared_ptr quadPtr(quad); - cml::matrix_rotate_about_world_axis(transform, - index, cml::rad(Scalar(value))); - } - } - } - else if (instruction == "texture") - { - ++it; - (*it)->get(texture); - } - else if (instruction == "tilemap") - { - ++it; - loadTilemap(*it, transform, texture); - } - else if (instruction == "billboard") - { - ++it; - loadBillboard(*it, transform, texture); - } - } + octree->insert(quadPtr); } } +} +static void loadBillboard(SerializableP root, const Matrix4& transform, + const std::string& texture, OctreeP octree) +{ + Serializable::Map rootObj; + Serializable::Map::iterator it; - void loadTilemap(SerializableP root, const Matrix4& transform, - const std::string& texture) - { - Serializable::Map rootObj; - Serializable::Map::iterator it; + Tilemap::Index index = 0; + long width = 1; + bool blending = false; + bool fog = false; - if (!root->get(rootObj)) + if (root->get(rootObj)) + { + if ((it = rootObj.find("tile")) != rootObj.end()) { - logError("invalid tilemap instruction"); - return; + Serializable::Integer value; + if ((*it).second->get(value)) + { + index = Tilemap::Index(value); + } } - long width = 1; - long height = 1; - std::vector< std::vector > indices; - - if ((it = rootObj.find("width")) != rootObj.end()) + if ((it = rootObj.find("u_scale")) != rootObj.end()) { (*it).second->get(width); } - else + + if ((it = rootObj.find("blend")) != rootObj.end()) { - logError("missing required field width for tilemap instruction"); - return; + (*it).second->get(blending); } - Serializable::Array tiles; - - if ((it = rootObj.find("tiles")) != rootObj.end() && - (*it).second->get(tiles) && - tiles.size() % width == 0) + if ((it = rootObj.find("fog")) != rootObj.end()) { - Serializable::Array::iterator jt; - int w, h; - - height = tiles.size() / width; - indices.resize(height); + (*it).second->get(fog); + } + } - // the indices are stored upside-down in the scene file so that they - // are easier to edit as text, so we'll need to load them last row - // first - for (h = height - 1, jt = tiles.begin(); jt != tiles.end(); --h) - { - std::vector row; + Vector4 vertices[2][width+1]; - for (w = 0; w < width && jt != tiles.end(); ++w, ++jt) - { - Serializable::Integer index; + Matrix4 transposedTransform = transform; + transposedTransform.transpose(); - if ((*jt)->get(index)) - { - row.push_back(Tilemap::Index(index)); - } - } + Scalar xf; + Scalar increment = 1.0 / Scalar(width); - indices[h] = row; - } - } - else + for (int h = 0; h <= 1; ++h) + { + xf = 0.0; + for (int w = 0; w <= width; ++w, xf += increment) { - logError("invalid tiles in tilemap instruction"); - return; + vertices[h][w] = Vector4(xf, Scalar(h), 0.0, 1.0) * + transposedTransform; } + } - Vector4 vertices[height+1][width+1]; + for (int w = 0; w < width; ++w) + { + Vector3 quadVertices[4]; - Matrix4 transposedTransform = transform; - transposedTransform.transpose(); + demoteVector(quadVertices[0], vertices[0][w]); + demoteVector(quadVertices[1], vertices[0][w+1]); + demoteVector(quadVertices[2], vertices[1][w+1]); + demoteVector(quadVertices[3], vertices[1][w]); - for (int h = 0; h <= height; ++h) - { - for (int w = 0; w <= width; ++w) - { - vertices[h][w] = Vector4(Scalar(w), Scalar(h), 0.0, 1.0) * - transposedTransform; - } - } + Quad* quad = new Quad(quadVertices, texture, index); + quad->setBlending(blending); + quad->setFog(fog); - for (int h = 0; h < height; ++h) - { - for (int w = 0; w < width; ++w) - { - if (indices[h][w] == Tilemap::NO_TILE) continue; + boost::shared_ptr quadPtr(quad); - Vector3 quadVertices[4]; + octree->insert(quadPtr); + } +} - demoteVector(quadVertices[0], vertices[h][w]); - demoteVector(quadVertices[1], vertices[h][w+1]); - demoteVector(quadVertices[2], vertices[h+1][w+1]); - demoteVector(quadVertices[3], vertices[h+1][w]); - Quad* quad = new Quad(quadVertices, texture, indices[h][w]); - boost::shared_ptr quadPtr(quad); +static void loadInstructions(SerializableP root, OctreeP octree) +{ + Serializable::Array rootObj; + Serializable::Array::iterator it; - octree->insert(quadPtr); - } - } + if (!root->get(rootObj)) + { + logError("scene instructions must be an array"); + return; } - void loadBillboard(SerializableP root, const Matrix4& transform, - const std::string& texture) - { - Serializable::Map rootObj; - Serializable::Map::iterator it; + Matrix4 transform; + std::string texture; - Tilemap::Index index = 0; - long width = 1; - bool blending = false; - bool fog = false; + for (it = rootObj.begin(); it != rootObj.end(); ++it) + { + std::string instruction; - if (root->get(rootObj)) + if ((*it)->get(instruction)) { - if ((it = rootObj.find("tile")) != rootObj.end()) + if (instruction == "reset_transform") { - Serializable::Integer value; - if ((*it).second->get(value)) - { - index = Tilemap::Index(value); - } + transform.identity(); } - - if ((it = rootObj.find("u_scale")) != rootObj.end()) + else if (instruction == "translate") { - (*it).second->get(width); - } + Serializable::Array values; - if ((it = rootObj.find("blend")) != rootObj.end()) - { - (*it).second->get(blending); - } - - if ((it = rootObj.find("fog")) != rootObj.end()) - { - (*it).second->get(fog); - } - } - - - Vector4 vertices[2][width+1]; + ++it; + if ((*it)->get(values)) + { + Vector3 vec; - Matrix4 transposedTransform = transform; - transposedTransform.transpose(); + for (size_t i = 0; i < values.size(); ++i) + { + Serializable::Float value; - Scalar xf; - Scalar increment = 1.0 / Scalar(width); + if (values[i]->getNumber(value)) + { + vec[i] = value; + } + } - for (int h = 0; h <= 1; ++h) - { - xf = 0.0; - for (int w = 0; w <= width; ++w, xf += increment) - { - vertices[h][w] = Vector4(xf, Scalar(h), 0.0, 1.0) * - transposedTransform; + Matrix4 translation; + cml::matrix_translation(translation, vec); + transform = translation * transform; + } } - } - - for (int w = 0; w < width; ++w) - { - Vector3 quadVertices[4]; - - demoteVector(quadVertices[0], vertices[0][w]); - demoteVector(quadVertices[1], vertices[0][w+1]); - demoteVector(quadVertices[2], vertices[1][w+1]); - demoteVector(quadVertices[3], vertices[1][w]); - - Quad* quad = new Quad(quadVertices, texture, index); - quad->setBlending(blending); - quad->setFog(fog); + else if (instruction == "scale") + { + Serializable::Array values; - boost::shared_ptr quadPtr(quad); + ++it; + if ((*it)->get(values)) + { + if (values.size() == 1) + { + Serializable::Float value = 1.0; - octree->insert(quadPtr); - } - } + values[0]->getNumber(value); + Matrix4 scaling; + cml::matrix_uniform_scale(scaling, + Scalar(value)); + transform = scaling * transform; + } + else if (values.size() == 3) + { + Vector3 vec; - void loadFromFile() - { - std::string filePath = Scene::getPath(getName()); + for (size_t i = 0; i < values.size(); ++i) + { + Serializable::Float value; - Deserializer deserializer(filePath, true); - SerializableP root = deserializer.deserialize(); + if (values[i]->getNumber(value)) + { + vec[i] = value; + } + } - Serializable::Map rootObj; - Serializable::Map::iterator it; + Matrix4 scaling; + cml::matrix_scale(scaling, vec); + transform = scaling * transform; + } + } + } + else if (instruction == "rotate") + { + Serializable::Array values; - if (!root || !root->get(rootObj)) - { - logError("no root map in scene file"); - return; - } + ++it; + if ((*it)->get(values)) + { + if (values.size() == 2) + { + std::string axis; + size_t index = 0; + Serializable::Float value = 0.0; - if ((it = rootObj.find("playfield_bounds")) != rootObj.end()) - { - loadBox(playfieldBounds, (*it).second); - } - if ((it = rootObj.find("maximum_bounds")) != rootObj.end()) - { - loadBox(maximumBounds, (*it).second); - } - else - { - logError("missing required maximum bounds"); - return; - } + if (values[0]->get(axis)) + { + if (axis == "x") index = 0; + else if (axis == "y") index = 1; + else if (axis == "z") index = 2; - // create the tree to store the quads - octree = Octree::alloc(maximumBounds); + values[1]->getNumber(value); + } - if ((it = rootObj.find("instructions")) != rootObj.end()) - { - loadInstructions((*it).second); + cml::matrix_rotate_about_world_axis(transform, + index, cml::rad(Scalar(value))); + } + } + } + else if (instruction == "texture") + { + ++it; + (*it)->get(texture); + } + else if (instruction == "tilemap") + { + ++it; + loadTilemap(*it, transform, texture, octree); + } + else if (instruction == "billboard") + { + ++it; + loadBillboard(*it, transform, texture, octree); + } } - - - - octree->sort(); } +} - void draw(Scalar alpha, const Camera& cam) const - { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - octree->drawIfVisible(alpha, cam); +static std::string getPath(const std::string& name) +{ + return Resource::getPath("scenes/" + name + ".json"); +} - //glDisableClientState(GL_VERTEX_ARRAY); - //glDisableClientState(GL_TEXTURE_COORD_ARRAY); +OctreeP loadScene(const std::string& name) +{ + std::string filePath = getPath(name); - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + Deserializer deserializer(filePath, true); + SerializableP root = deserializer.deserialize(); - //Texture::resetBind(); - //glColor3f(0.0f, 1.0f, 0.0f); - //playfieldBounds.draw(); - //glColor3f(0.0f, 0.0f, 1.0f); - //maximumBounds.draw(); + Serializable::Map rootObj; + Serializable::Map::iterator it; - //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + if (!root || !root->get(rootObj)) + { + logError("no root map in scene file"); + return OctreeP(); } - Aabb playfieldBounds; Aabb maximumBounds; - OctreeP octree; -}; - - -Scene::Scene(const std::string& name) : - // pass through - impl_(Scene::Impl::getInstance(name)) {} - - -void Scene::draw(Scalar alpha, const Camera& cam) const -{ - // pass through - impl_->draw(alpha, cam); -} - -void Scene::refresh() -{ - //impl_->objects.clear(); - impl_->loadFromFile(); -} + if ((it = rootObj.find("playfield_bounds")) != rootObj.end()) + { + loadBox(playfieldBounds, (*it).second); + } + if ((it = rootObj.find("maximum_bounds")) != rootObj.end()) + { + loadBox(maximumBounds, (*it).second); + } + else + { + logError("missing required maximum bounds"); + return OctreeP(); + } + // create the tree to store the quads + OctreeP octree = Octree::alloc(maximumBounds); -OctreeP Scene::getOctree() const -{ - // pass through - return impl_->octree; -} + if ((it = rootObj.find("instructions")) != rootObj.end()) + { + loadInstructions((*it).second, octree); + } -/** - * Specialized search location for scene files. They can be found in the - * "scenes" subdirectory of any of the searched directories. - */ + octree->sort(); -std::string Scene::getPath(const std::string& name) -{ - return Resource::getPath("scenes/" + name + ".json"); + return octree; } diff --git a/src/Moof/Scene.hh b/src/Moof/Scene.hh index f0e829d..107e993 100644 --- a/src/Moof/Scene.hh +++ b/src/Moof/Scene.hh @@ -34,39 +34,107 @@ #include #include +#include #include #include +#include namespace Mf { -class Scene; -typedef boost::shared_ptr SceneP; +OctreeP loadScene(const std::string& name); -class Camera; - -class Scene : public Resource +class Quad : public Entity { - class Impl; - boost::shared_ptr impl_; + Scalar vertices_[12]; + Scalar texCoords_[8]; + + Tilemap tilemap_; + + long detail_; + bool blending_; + bool fog_; public: - inline static SceneP alloc(const std::string& name) + Quad(const Vector3 vertices[4], const std::string& texture, + Tilemap::Index tileIndex) : + tilemap_(texture), + detail_(0), + blending_(false), + fog_(false) + { + for (int i = 0, num = 0; i < 4; ++i) + { + for (int j = 0; j < 3; ++j, ++num) + { + vertices_[num] = vertices[i][j]; + } + } + + if (!tilemap_.getTileCoords(tileIndex, texCoords_)) + { + logWarning("no index %d in texture %s", tileIndex, + texture.c_str()); + + texCoords_[0] = texCoords_[1] = + texCoords_[3] = texCoords_[6] = 0.0; + texCoords_[2] = texCoords_[4] = + texCoords_[5] = texCoords_[7] = 1.0; + } + + aabb_.encloseVertices(vertices, 4); + sphere_.point = aabb_.getCenter(); + sphere_.radius = (aabb_.min - sphere_.point).length(); + } + + void setDetail(long detail) + { + detail_ = detail; + } + + void setBlending(bool blending) + { + blending_ = blending; + } + + void setFog(bool fog) { - return SceneP(new Scene(name)); + fog_ = fog; } - Scene(const std::string& name); + void draw(Scalar alpha = 0.0) const + { + if (blending_) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + if (fog_) + { + glEnable(GL_FOG); + glFogi(GL_FOG_MODE, GL_LINEAR); + } + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + tilemap_.bind(); - void draw(Scalar alpha, const Camera& cam) const; - void refresh(); + glVertexPointer(3, GL_SCALAR, 0, vertices_); + glTexCoordPointer(2, GL_SCALAR, 0, texCoords_); - OctreeP getOctree() const; + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - static std::string getPath(const std::string& name); + glDisable(GL_BLEND); + glDisable(GL_FOG); + } + + bool isVisible(const Frustum& frustum) const + { + return sphere_.isVisible(frustum); + } }; diff --git a/src/Moof/Sound.hh b/src/Moof/Sound.hh index 32f4c87..4f65582 100644 --- a/src/Moof/Sound.hh +++ b/src/Moof/Sound.hh @@ -55,7 +55,7 @@ class Sound : public Resource public: - inline static SoundP alloc(const std::string& name) + static SoundP alloc(const std::string& name) { return SoundP(new Sound(name)); } diff --git a/src/Moof/Sphere.cc b/src/Moof/Sphere.cc index d8d089d..9729832 100644 --- a/src/Moof/Sphere.cc +++ b/src/Moof/Sphere.cc @@ -26,7 +26,7 @@ *******************************************************************************/ -#include "Camera.hh" +#include "Frustum.hh" #include "OpenGL.hh" #include "Sphere.hh" @@ -44,9 +44,9 @@ void Sphere::draw(Scalar alpha) const // TODO } -bool Sphere::isVisible(const Camera& cam) const +bool Sphere::isVisible(const Frustum& frustum) const { - return cam.getFrustum().contains(*this); + return frustum.contains(*this); } diff --git a/src/Moof/Sphere.hh b/src/Moof/Sphere.hh index 8a9d5e6..7f7a763 100644 --- a/src/Moof/Sphere.hh +++ b/src/Moof/Sphere.hh @@ -56,7 +56,7 @@ struct Sphere : public Cullable, public Drawable point(x, y, z), radius(r) {} - inline void init(const Vector3& p, Scalar r) + void init(const Vector3& p, Scalar r) { point = p; radius = r; @@ -65,7 +65,7 @@ struct Sphere : public Cullable, public Drawable void encloseVertices(const Vector3 vertices[], unsigned count); void draw(Scalar alpha = 0.0) const; - bool isVisible(const Camera& cam) const; + bool isVisible(const Frustum& frustum) const; }; diff --git a/src/Moof/Video.hh b/src/Moof/Video.hh index 4be691d..0dca8bb 100644 --- a/src/Moof/Video.hh +++ b/src/Moof/Video.hh @@ -88,8 +88,7 @@ private: public: - inline static VideoP alloc(const std::string& caption, - const std::string& icon) + static VideoP alloc(const std::string& caption, const std::string& icon) { return VideoP(new Video(caption, icon)); } diff --git a/src/YoinkApp.cc b/src/YoinkApp.cc index 6cddf1a..597a74f 100644 --- a/src/YoinkApp.cc +++ b/src/YoinkApp.cc @@ -122,8 +122,8 @@ YoinkApp::YoinkApp(int argc, char* argv[]) : Mf::Scalar b[2] = {1.0, 0.0}; fadeIn.init(b, 1.0); - testScene = Mf::Scene::alloc("Test"); - heroine->treeNode = testScene->getOctree()->insert(heroine); + octree = Mf::loadScene("Test"); + heroine->treeNode = octree->insert(heroine); } YoinkApp::~YoinkApp() @@ -174,7 +174,7 @@ void YoinkApp::contextRecreated(const Mf::Notification* note) void YoinkApp::update(Mf::Scalar t, Mf::Scalar dt) { - //dt *= 0.1; + dt *= 0.7; music.update(t, dt); fadeIn.update(dt); @@ -182,8 +182,8 @@ void YoinkApp::update(Mf::Scalar t, Mf::Scalar dt) heroine->update(t, dt); // reinsert heroine - heroine->treeNode = testScene->getOctree()->reinsert(heroine, heroine->treeNode); - testScene->getOctree()->print(heroine->treeNode); + heroine->treeNode = octree->reinsert(heroine, heroine->treeNode); + octree->print(heroine->treeNode); //camera.lookAt(heroine->getSphere().point); camera.setPosition(Mf::Vector3(-heroine->current.position[0], -heroine->current.position[1], -256)); @@ -203,7 +203,11 @@ void YoinkApp::draw(Mf::Scalar alpha) // DRAW THE SCENE Mf::Texture::resetBind(); - testScene->draw(alpha, camera); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + octree->drawIfVisible(alpha, camera.getFrustum()); //heroine->draw(alpha); heroine->getAabb().draw(); @@ -258,11 +262,6 @@ void YoinkApp::handleEvent(const Mf::Event& event) punchSound.play(); break; } - else if (event.key.keysym.sym == SDLK_r) - { - testScene->refresh(); - break; - } else if (event.key.keysym.sym == SDLK_t) { Mf::dispatcher::dispatch("video.context_recreated"); diff --git a/src/YoinkApp.hh b/src/YoinkApp.hh index b24eff7..950d319 100644 --- a/src/YoinkApp.hh +++ b/src/YoinkApp.hh @@ -75,7 +75,7 @@ private: Mf::Lerp fadeIn; Mf::Camera camera; - Mf::SceneP testScene; + Mf::OctreeP octree; Hud hud; }; -- 2.45.2