]> Dogcows Code - chaz/yoink/blobdiff - src/Moof/Scene.cc
extreme refactoring
[chaz/yoink] / src / Moof / Scene.cc
diff --git a/src/Moof/Scene.cc b/src/Moof/Scene.cc
new file mode 100644 (file)
index 0000000..f4dd1c0
--- /dev/null
@@ -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 <iostream>
+#include <map>
+#include <vector>
+
+#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<SceneImpl>
+{
+       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<std::string,SerializablePtr> rootObj;
+
+                       if (root->get(rootObj))
+                       {
+                               std::map<std::string,SerializablePtr>::iterator it;
+
+                               if ((it = rootObj.find("width")) != rootObj.end())
+                               {
+                                       (*it).second->get(width);
+                               }
+                               if ((it = rootObj.find("tiles")) != rootObj.end())
+                               {
+                                       std::vector<SerializablePtr> theTiles;
+
+                                       if ((*it).second->get(theTiles))
+                                       {
+                                               std::vector<SerializablePtr>::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<Tilemap::Index> 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<std::vector<Tilemap::Index> > indices;
+       };
+
+       class Billboard : public Scenery
+       {
+       public:
+               Billboard(const Matrix4& transform, const std::string& textureName,
+                               SerializablePtr root) :
+                       Scenery(transform, textureName),
+                       index(0)
+               {
+                       std::map<std::string,SerializablePtr> rootObj;
+
+                       if (root->get(rootObj))
+                       {
+                               std::map<std::string,SerializablePtr>::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<SerializablePtr> 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<SceneImpl>(name)
+       {
+               loadFromFile();
+       }
+
+
+       void loadInstructions(SerializablePtr root)
+       {
+               std::vector<SerializablePtr> rootObj;
+
+               if (root->get(rootObj))
+               {
+                       std::vector<SerializablePtr>::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<SerializablePtr> 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<SerializablePtr> 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<SerializablePtr> 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<Scenery> 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<Scenery> 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<std::string,SerializablePtr> rootObj;
+
+                       if (root->get(rootObj))
+                       {
+                               std::map<std::string,SerializablePtr>::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<boost::shared_ptr<Scenery> > 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: *************************************************/
+
This page took 0.03581 seconds and 4 git commands to generate.