X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FScene.cc;h=418c0512e3c690e4f29406181cac8346c67ada80;hp=85e5be75d9697a315e5aded091589e6ab3c8da58;hb=7e898e8ec0ff716e2fc722b883a626a6c346f107;hpb=72d4af22710317acffab861421c4364b1780b6fe diff --git a/src/Moof/Scene.cc b/src/Moof/Scene.cc index 85e5be7..418c051 100644 --- a/src/Moof/Scene.cc +++ b/src/Moof/Scene.cc @@ -26,7 +26,6 @@ *******************************************************************************/ -#include #include #include @@ -34,10 +33,8 @@ #include "Camera.hh" #include "Deserializer.hh" #include "Entity.hh" +#include "Log.hh" #include "Math.hh" -#include "Mippleton.hh" -#include "Octree.hh" -#include "OpenGL.hh" #include "Scene.hh" #include "Serializable.hh" #include "Tilemap.hh" @@ -46,366 +43,140 @@ namespace Mf { -class Scene::SceneImpl : 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_)) - { - std::cerr << "no coords for tile's texture" << std::endl; - } - - 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; - } + Serializable::Array numbers; - void draw(Scalar alpha = 0.0) const - { - if (blending_) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - 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); - - glDisable(GL_BLEND); - } + 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, SerializablePtr obj) + if ((it = rootObj.find("width")) != rootObj.end()) { - std::vector numbers; - - if (obj->get(numbers) && numbers.size() == 6) - { - double 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: - SceneImpl(const std::string& name) : - Mippleton(name) + else { - loadFromFile(); + logError("missing required field width for tilemap instruction"); + return; } + Serializable::Array tiles; - void loadInstructions(SerializablePtr root) + if ((it = rootObj.find("tiles")) != rootObj.end() && + (*it).second->get(tiles) && + tiles.size() % width == 0) { - std::vector rootObj; - std::vector::iterator it; + Serializable::Array::iterator jt; + int w, h; - if (!root->get(rootObj)) - { - std::cerr << "error loading scene instructions" << std::endl; - 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") - { - std::vector values; + Serializable::Integer index; - ++it; - if ((*it)->get(values)) - { - Vector3 vec; - - for (size_t i = 0; i < values.size(); ++i) - { - double value; - - if (values[i]->getNumber(value)) - { - vec[i] = value; - } - } - - Matrix4 translation; - cml::matrix_translation(translation, vec); - transform = translation * transform; - } - } - else if (instruction == "scale") + if ((*jt)->get(index)) { - std::vector values; - - ++it; - if ((*it)->get(values)) - { - if (values.size() == 1) - { - double value = 1.0; - - values[0]->getNumber(value); - - Matrix4 scaling; - cml::matrix_uniform_scale(scaling, - Scalar(value)); - transform = scaling * transform; - } - else if (values.size() == 3) - { - Vector3 vec; - - for (size_t i = 0; i < values.size(); ++i) - { - double value; - - if (values[i]->getNumber(value)) - { - vec[i] = value; - } - } - - Matrix4 scaling; - cml::matrix_scale(scaling, vec); - transform = scaling * transform; - } - } - } - else if (instruction == "rotate") - { - std::vector values; - - ++it; - if ((*it)->get(values)) - { - if (values.size() == 2) - { - std::string axis; - size_t index = 0; - double value = 0.0; - - if (values[0]->get(axis)) - { - if (axis == "x") index = 0; - else if (axis == "y") index = 1; - else if (axis == "z") index = 2; - - values[1]->getNumber(value); - } - - 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); + row.push_back(Tilemap::Index(index)); } } + + indices[h] = row; } } - - - void loadTilemap(SerializablePtr root, const Matrix4& transform, - const std::string& texture) + else { - std::map rootObj; - std::map::iterator it; - - if (!root->get(rootObj)) - { - std::cerr << "error loading scene tilemap object" << std::endl; - return; - } - - long width = 1; - long height = 1; - std::vector< std::vector > indices; - - if ((it = rootObj.find("width")) != rootObj.end()) - { - (*it).second->get(width); - } - else - { - std::cerr << "width is a required field of a tilemap" << std::endl; - return; - } - - std::vector tiles; - - if ((it = rootObj.find("tiles")) != rootObj.end() && - (*it).second->get(tiles) && - tiles.size() % width == 0) - { - std::vector::iterator jt; - int w, h; - - height = tiles.size() / width; - indices.resize(height); - - // 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; - - for (w = 0; w < width && jt != tiles.end(); ++w, ++jt) - { - long index; - - if ((*jt)->get(index)) - { - row.push_back(Tilemap::Index(index)); - } - } - - indices[h] = row; - } - } - else - { - std::cerr << "error loading tiles from tilemap object" << std::endl; - return; - } + logError("invalid tiles in tilemap instruction"); + return; + } - Vector4 vertices[height+1][width+1]; + Vector4 vertices[height+1][width+1]; - Matrix4 transposedTransform = transform; - transposedTransform.transpose(); + Matrix4 transposedTransform = transform; + transposedTransform.transpose(); - for (int h = 0; h <= height; ++h) + for (int h = 0; h <= height; ++h) + { + for (int w = 0; w <= width; ++w) { - for (int w = 0; w <= width; ++w) - { - vertices[h][w] = Vector4(Scalar(w), Scalar(h), 0.0, 1.0) * - transposedTransform; - } + vertices[h][w] = Vector4(Scalar(w), Scalar(h), 0.0, 1.0) * + transposedTransform; } + } - for (int h = 0; h < height; ++h) + for (int h = 0; h < height; ++h) + { + for (int w = 0; w < width; ++w) { - for (int w = 0; w < width; ++w) - { - if (indices[h][w] == Tilemap::NO_TILE) continue; + if (indices[h][w] == Tilemap::NO_TILE) continue; - Vector3 quadVertices[4]; + Vector3 quadVertices[4]; - 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]); + 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); + Quad* quad = new Quad(quadVertices, texture, indices[h][w]); + boost::shared_ptr quadPtr(quad); - //objects.push_back(quadPtr); - Octree::add(octree, quadPtr); - } + octree->insert(quadPtr); } } +} - void loadBillboard(SerializablePtr root, const Matrix4& transform, - const std::string& texture) - { - std::map rootObj; - std::map::iterator it; - - if (!root->get(rootObj)) - { - std::cerr << "error loading scene billboard object" << std::endl; - return; - } +static void loadBillboard(SerializableP root, const Matrix4& transform, + const std::string& texture, OctreeP octree) +{ + Serializable::Map rootObj; + Serializable::Map::iterator it; - Tilemap::Index index = 0; - long width = 1; - bool blending = false; - bool fog = false; + Tilemap::Index index = 0; + long width = 1; + bool blending = false; + bool fog = false; + if (root->get(rootObj)) + { if ((it = rootObj.find("tile")) != rootObj.end()) { - long value; + Serializable::Integer value; if ((*it).second->get(value)) { index = Tilemap::Index(value); @@ -426,161 +197,229 @@ public: { (*it).second->get(fog); } + } - Vector4 vertices[2][width+1]; + Vector4 vertices[2][width+1]; - Matrix4 transposedTransform = transform; - transposedTransform.transpose(); + Matrix4 transposedTransform = transform; + transposedTransform.transpose(); - Scalar xf; - Scalar increment = 1.0 / Scalar(width); + Scalar xf; + Scalar increment = 1.0 / Scalar(width); - for (int h = 0; h <= 1; ++h) + for (int h = 0; h <= 1; ++h) + { + xf = 0.0; + for (int w = 0; w <= width; ++w, xf += increment) { - xf = 0.0; - for (int w = 0; w <= width; ++w, xf += increment) - { - vertices[h][w] = Vector4(xf, Scalar(h), 0.0, 1.0) * - transposedTransform; - } + vertices[h][w] = Vector4(xf, Scalar(h), 0.0, 1.0) * + transposedTransform; } + } - for (int w = 0; w < width; ++w) - { - Vector3 quadVertices[4]; + 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]); + 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); + Quad* quad = new Quad(quadVertices, texture, index); + quad->setBlending(blending); + quad->setFog(fog); - boost::shared_ptr quadPtr(quad); + boost::shared_ptr quadPtr(quad); - //objects.push_back(quad_Ptr); - Octree::add(octree, quadPtr); - } + octree->insert(quadPtr); } +} - void loadFromFile() - { - std::string filePath = Scene::getPathToResource(getName()); +static void loadInstructions(SerializableP root, OctreeP octree) +{ + Serializable::Array rootObj; + Serializable::Array::iterator it; - Deserializer deserializer(filePath, true); - SerializablePtr root = deserializer.deserialize(); + if (!root->get(rootObj)) + { + logError("scene instructions must be an array"); + return; + } - std::map rootObj; - std::map::iterator it; + Matrix4 transform; + std::string texture; - if (!root || !root->get(rootObj)) - { - std::cerr << "error loading scene file" << std::endl; - return; - } + for (it = rootObj.begin(); it != rootObj.end(); ++it) + { + std::string instruction; - if ((it = rootObj.find("playfield_bounds")) != rootObj.end()) - { - loadBox(playfieldBounds, (*it).second); - } - if ((it = rootObj.find("maximum_bounds")) != rootObj.end()) + if ((*it)->get(instruction)) { - loadBox(maximumBounds, (*it).second); - } - else - { - std::cerr << "maximum bounds required in scene" << std::endl; - return; - } + if (instruction == "reset_transform") + { + transform.identity(); + } + else if (instruction == "translate") + { + Serializable::Array values; - //OctreeNode rootNode(maximumBounds); - octree = Octree::createNewNode(maximumBounds); + ++it; + if ((*it)->get(values)) + { + Vector3 vec; - if ((it = rootObj.find("instructions")) != rootObj.end()) - { - loadInstructions((*it).second); - } - } + for (size_t i = 0; i < values.size(); ++i) + { + Serializable::Float value; + if (values[i]->getNumber(value)) + { + vec[i] = value; + } + } - void draw(Scalar alpha, const Camera& cam) const - { - //QuadVector::const_iterator it; + Matrix4 translation; + cml::matrix_translation(translation, vec); + transform = translation * transform; + } + } + else if (instruction == "scale") + { + Serializable::Array values; - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + ++it; + if ((*it)->get(values)) + { + if (values.size() == 1) + { + Serializable::Float value = 1.0; - octree->drawIfVisible(alpha, cam); + values[0]->getNumber(value); - //int objectsDrawn = 0; + Matrix4 scaling; + cml::matrix_uniform_scale(scaling, + Scalar(value)); + transform = scaling * transform; + } + else if (values.size() == 3) + { + Vector3 vec; - //for (it = objects.begin(); it != objects.end(); ++it) - //{ - //if ((*it)->isVisible(cam)) - //{ - ////std::cout << "draw object"; - //(*it)->draw(); + for (size_t i = 0; i < values.size(); ++i) + { + Serializable::Float value; - //objectsDrawn++; - //} - //} + if (values[i]->getNumber(value)) + { + vec[i] = value; + } + } - //std::cout << objectsDrawn << std::endl; + Matrix4 scaling; + cml::matrix_scale(scaling, vec); + transform = scaling * transform; + } + } + } + else if (instruction == "rotate") + { + Serializable::Array values; - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + ++it; + if ((*it)->get(values)) + { + if (values.size() == 2) + { + std::string axis; + size_t index = 0; + Serializable::Float value = 0.0; - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + if (values[0]->get(axis)) + { + if (axis == "x") index = 0; + else if (axis == "y") index = 1; + else if (axis == "z") index = 2; - Texture::resetBind(); - glColor3f(0.0f, 1.0f, 0.0f); - playfieldBounds.draw(); - glColor3f(0.0f, 0.0f, 1.0f); - maximumBounds.draw(); + values[1]->getNumber(value); + } - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + 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); + } + } } +} - Aabb playfieldBounds; - Aabb maximumBounds; +static std::string getPath(const std::string& name) +{ + return Resource::getPath("scenes/" + name + ".json"); +} - //typedef std::vector< boost::shared_ptr > QuadVector; - //QuadVector objects; - OctreePtr octree; -}; +OctreeP loadScene(const std::string& name) +{ + std::string filePath = getPath(name); + Deserializer deserializer(filePath, true); + SerializableP root = deserializer.deserialize(); -Scene::Scene(const std::string& name) : - // pass through - impl_(Scene::SceneImpl::retain(name), &Scene::SceneImpl::release) {} + Serializable::Map rootObj; + Serializable::Map::iterator it; + if (!root || !root->get(rootObj)) + { + logError("no root map in scene file"); + return OctreeP(); + } -void Scene::draw(Scalar alpha, const Camera& cam) const -{ - // pass through - impl_->draw(alpha, cam); -} + Aabb playfieldBounds; + Aabb maximumBounds; -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); -/** - * Specialized search location for scene files. They can be found in the - * "scenes" subdirectory of any of the searched directories. - */ + if ((it = rootObj.find("instructions")) != rootObj.end()) + { + loadInstructions((*it).second, octree); + } -std::string Scene::getPathToResource(const std::string& name) -{ - return Resource::getPathToResource("scenes/" + name + ".json"); + octree->sort(); + + return octree; }