X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FScene.cc;fp=src%2FMoof%2FScene.cc;h=f4dd1c0e3f9597bdd7505ed236bd3d91591fc40c;hp=0000000000000000000000000000000000000000;hb=c2321281bf12a7efaedde930422c7ddbc92080d4;hpb=87bc17e55b0c1dc73ecc66df856d3f08fd7a7724 diff --git a/src/Moof/Scene.cc b/src/Moof/Scene.cc new file mode 100644 index 0000000..f4dd1c0 --- /dev/null +++ b/src/Moof/Scene.cc @@ -0,0 +1,497 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include +#include +#include + +#include "Aabb.hh" +#include "Camera.hh" +#include "Cullable.hh" +#include "Deserializer.hh" +#include "Drawable.hh" +#include "Math.hh" +#include "Mippleton.hh" +#include "OpenGL.hh" +#include "Scene.hh" +#include "Serializable.hh" +#include "Tilemap.hh" + + +namespace Mf { + + +class Scene::SceneImpl : public Mippleton +{ + class Scenery : public Drawable, public Cullable + { + public: + Scenery(const Matrix4& transform, const std::string& textureName) : + transformation(transform), + image(textureName) {} + + protected: + Matrix4 transformation; + Tilemap image; + bool blending; + long detail; + bool fog; + }; + + class TilePanel : public Scenery + { + public: + TilePanel(const Matrix4& transform, const std::string& textureName, + SerializablePtr root) : + Scenery(transform, textureName), + width(1), + height(1) + { + std::map rootObj; + + if (root->get(rootObj)) + { + std::map::iterator it; + + if ((it = rootObj.find("width")) != rootObj.end()) + { + (*it).second->get(width); + } + if ((it = rootObj.find("tiles")) != rootObj.end()) + { + std::vector theTiles; + + if ((*it).second->get(theTiles)) + { + std::vector::iterator jt; + + height = theTiles.size() / width; + int w, h; + + indices.resize(height); + + for (h = height - 1, jt = theTiles.begin(); + jt != theTiles.end(); h--) + { + std::vector row; + + for (w = 0; w < width && jt != theTiles.end(); + w++, jt++) + { + long index; + + if ((*jt)->get(index)) + { + row.push_back(Tilemap::Index(index)); + } + } + + indices[h] = row; + } + } + } + } + } + + void draw(Scalar alpha) + { + glPushMatrix(); + //std::cout << "transforming..." << std::endl; + //std::cout << transformation << std::endl; + glMultMatrixf(transformation.data()); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + image.bind(); + + long x, y; + Scalar xf, yf; + + for (y = 0, yf = 0.0; y < height; y++, yf += 1.0) + { + for (x = 0, xf = 0.0; x < width; x++, xf += 1.0) + { + Scalar texCoords[8]; + + Tilemap::Index index = indices[y][x]; + + if (image.getTileCoords(index, texCoords)) + { + glBegin(GL_TRIANGLE_FAN); + glTexCoord2f(texCoords[0], texCoords[1]); + glVertex3f(xf, yf, 0.0f); + glTexCoord2f(texCoords[2], texCoords[3]); + glVertex3f(xf+1.0, yf, 0.0f); + glTexCoord2f(texCoords[4], texCoords[5]); + glVertex3f(xf+1.0, yf+1.0, 0.0f); + glTexCoord2f(texCoords[6], texCoords[7]); + glVertex3f(xf, yf+1.0, 0.0f); + glEnd(); + } + } + } + + glPopMatrix(); + } + + bool isVisible(const Camera& cam) + { + return true; + } + + private: + long width, height; + std::vector > indices; + }; + + class Billboard : public Scenery + { + public: + Billboard(const Matrix4& transform, const std::string& textureName, + SerializablePtr root) : + Scenery(transform, textureName), + index(0) + { + std::map rootObj; + + if (root->get(rootObj)) + { + std::map::iterator it; + + if ((it = rootObj.find("tile")) != rootObj.end()) + { + long value; + if ((*it).second->get(value)) + { + index = Tilemap::Index(value); + } + } + } + + image.getTileCoords(index, texCoords); + } + + void draw(Scalar alpha) + { + glPushMatrix(); + glMultMatrixf(transformation.data()); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + image.bind(); + + glBegin(GL_TRIANGLE_FAN); + glTexCoord2f(texCoords[0], texCoords[1]); + glVertex2f(0.0f, 0.0f); + glTexCoord2f(texCoords[2], texCoords[3]); + glVertex2f(1.0f, 0.0f); + glTexCoord2f(texCoords[4], texCoords[5]); + glVertex2f(1.0f, 1.0f); + glTexCoord2f(texCoords[6], texCoords[7]); + glVertex2f(0.0f, 1.0f); + glEnd(); + + glPopMatrix(); + } + + bool isVisible(const Camera& cam) + { + return false; + } + + private: + Tilemap::Index index; + Scalar texCoords[8]; + }; + + + static bool loadBox(Aabb& theBox, SerializablePtr obj) + { + std::vector numbers; + + if (obj->get(numbers)) + { + if (numbers.size() == 6) + { + double num; + + if (numbers[0]->getNumber(num)) + { + + } + } + } + + return false; + } + +public: + SceneImpl(const std::string& name) : + Mippleton(name) + { + loadFromFile(); + } + + + void loadInstructions(SerializablePtr root) + { + std::vector rootObj; + + if (root->get(rootObj)) + { + std::vector::iterator it; + + Matrix4 transform; + std::string texture; + + for (it = rootObj.begin(); it != rootObj.end(); it++) + { + std::string instruction; + + if ((*it)->get(instruction)) + { + if (instruction == "reset_transform") + { + transform.identity(); + //std::cout << "===================RESET=====================" << std::endl; + } + else if (instruction == "translate") + { + std::vector values; + + 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; + //std::cout << "TRANSLATE\t" << vec << std::endl + //<< transform << std::endl; + } + } + else if (instruction == "scale") + { + 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; + //std::cout << "SCALE\t\t" << value << std::endl + //<< transform << std::endl; + } + 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; + //std::cout << "SCALE\t\t" << vec << std::endl + //<< transform << std::endl; + } + } + } + else if (instruction == "rotate") + { + std::vector values; + + it++; + if ((*it)->get(values)) + { + if (values.size() == 2) + { + std::string axis; + size_t axisIndex = 0; + double value = 0.0; + + if (values[0]->get(axis)) + { + if (axis == "x") + { + axisIndex = 0; + } + else if (axis == "y") + { + axisIndex = 1; + } + else if (axis == "z") + { + axisIndex = 2; + } + values[1]->getNumber(value); + } + + cml::matrix_rotate_about_local_axis(transform, + axisIndex, Scalar(value * cml::constantsd::rad_per_deg())); + //std::cout << "ROTATE\t" << axis << " " << value << std::endl + //<< transform << std::endl; + } + } + } + else if (instruction == "texture") + { + it++; + (*it)->get(texture); + } + else if (instruction == "tilemap") + { + //std::cout << "TILEMAP\t" << texture<< std::endl; + //std::cout << transform << std::endl; + + it++; + TilePanel* tilePanel = new TilePanel(transform, texture, + *it); + boost::shared_ptr sceneItem(tilePanel); + objects.push_back(sceneItem); + } + else if (instruction == "billboard") + { + //std::cout << "BILLBOARD\t" << texture << std::endl; + //std::cout << transform << std::endl; + + it++; + Billboard* billboard = new Billboard(transform, texture, + *it); + boost::shared_ptr sceneItem(billboard); + objects.push_back(sceneItem); + } + } + } + } + } + + + void loadFromFile() + { + std::string filePath = Scene::getPathToResource(getName()); + + Deserializer deserializer(filePath, true); + + SerializablePtr root = deserializer.deserialize(); + + if (root) + { + std::map rootObj; + + if (root->get(rootObj)) + { + std::map::iterator it; + + if ((it = rootObj.find("playfield_bounds")) != rootObj.end()) + { + loadBox(playfieldBounds, (*it).second); + } + if ((it = rootObj.find("maximum_bounds")) != rootObj.end()) + { + loadBox(maximumBounds, (*it).second); + } + if ((it = rootObj.find("instructions")) != rootObj.end()) + { + loadInstructions((*it).second); + } + } + } + } + + + void draw(Scalar alpha) + { + SceneryVector::iterator it; + + for (it = objects.begin(); it != objects.end(); it++) + { + //std::cout << "draw object"; + (*it)->draw(alpha); + } + } + + + Aabb playfieldBounds; + Aabb maximumBounds; + + typedef std::vector > SceneryVector; + SceneryVector objects; +}; + + +Scene::Scene(const std::string& name) : + // pass through + impl_(Scene::SceneImpl::retain(name), &Scene::SceneImpl::release) {} + + +void Scene::draw(Scalar alpha) +{ + // pass through + impl_->draw(alpha); +} + + +/** + * Specialized search location for scene files. They can be found in the + * "scenes" subdirectory of any of the searched directories. + */ + +std::string Scene::getPathToResource(const std::string& name) +{ + return Resource::getPathToResource("scenes/" + name + ".json"); +} + + +} // namespace Mf + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ +