X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2FMoof%2FScene.cc;h=b3313124d22100bb4e59871ca8d4e3070d290987;hb=892da43bf5796e7c5f593a6d0f53bd797a36bd3e;hp=f4dd1c0e3f9597bdd7505ed236bd3d91591fc40c;hpb=c2321281bf12a7efaedde930422c7ddbc92080d4;p=chaz%2Fyoink diff --git a/src/Moof/Scene.cc b/src/Moof/Scene.cc index f4dd1c0..b331312 100644 --- a/src/Moof/Scene.cc +++ b/src/Moof/Scene.cc @@ -26,468 +26,385 @@ *******************************************************************************/ -#include #include #include #include "Aabb.hh" #include "Camera.hh" -#include "Cullable.hh" -#include "Deserializer.hh" -#include "Drawable.hh" +#include "Entity.hh" +#include "Log.hh" #include "Math.hh" -#include "Mippleton.hh" -#include "OpenGL.hh" #include "Scene.hh" -#include "Serializable.hh" +#include "Script.hh" +#include "Settings.hh" #include "Tilemap.hh" namespace Mf { -class Scene::SceneImpl : public Mippleton +static std::string getPath(const std::string& name) { - class Scenery : public Drawable, public Cullable + return Resource::getPath("scenes/" + name + ".lua"); +} + + +struct Meh +{ + Matrix4 transform; + std::string texture; + + OctreeP octree; + + enum AXIS { - public: - Scenery(const Matrix4& transform, const std::string& textureName) : - transformation(transform), - image(textureName) {} - - protected: - Matrix4 transformation; - Tilemap image; - bool blending; - long detail; - bool fog; + X = 0, + Y = 1, + Z = 2 }; - class TilePanel : public Scenery + Meh() { - public: - TilePanel(const Matrix4& transform, const std::string& textureName, - SerializablePtr root) : - Scenery(transform, textureName), - width(1), - height(1) + octree = Octree::alloc(Aabb()); + } + + static int loadBox(Script& script, Aabb& aabb) + { + Script::Value table[] = {script[1], script[2]}; + + if (!table[0].isTable() || !table[1].isTable()) { - std::map rootObj; + logWarning("wrong arguments to setPlayfieldBounds; ignoring..."); + return 0; + } - if (root->get(rootObj)) + for (int i = 0; i <= 1; ++i) + { + for (int j = 1; j <= 3; ++j) { - 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; - } - } - } + script.push((long)j); + table[i].pushField(); } } - void draw(Scalar alpha) - { - glPushMatrix(); - //std::cout << "transforming..." << std::endl; - //std::cout << transformation << std::endl; - glMultMatrixf(transformation.data()); + script[3].get(aabb.min[0]); + script[4].get(aabb.min[1]); + script[5].get(aabb.min[2]); + script[6].get(aabb.max[0]); + script[7].get(aabb.max[1]); + script[8].get(aabb.max[2]); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - image.bind(); + return 0; + } - long x, y; - Scalar xf, yf; + int setPlayfieldBounds(Script& script) + { + Aabb bounds; + return loadBox(script, bounds); + } - 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(); - } - } - } + int setMaximumBounds(Script& script) + { + Aabb bounds; + int ret = loadBox(script, bounds); + octree = Octree::alloc(bounds); + return ret; + } + + int resetTransform(Script& script) + { + transform.identity(); + return 0; + } + + int translate(Script& script) + { + Script::Value x = script[1].requireNumber(); + Script::Value y = script[2].requireNumber(); + Script::Value z = script[3].requireNumber(); + + Vector3 vec; + x.get(vec[0]); + y.get(vec[1]); + z.get(vec[2]); + + Matrix4 translation; + cml::matrix_translation(translation, vec); + transform = translation * transform; - glPopMatrix(); + return 0; + } + + int scale(Script& script) + { + if (script.getSize() == 3) + { + Vector3 vec; + script[1].requireNumber().get(vec[0]); + script[2].requireNumber().get(vec[1]); + script[3].requireNumber().get(vec[2]); + + Matrix4 scaling; + cml::matrix_scale(scaling, vec); + transform = scaling * transform; } + else if (script.getSize() == 1) + { + Scalar value = 1.0; + script[1].requireNumber().get(value); - bool isVisible(const Camera& cam) + Matrix4 scaling; + cml::matrix_uniform_scale(scaling, value); + transform = scaling * transform; + } + else { - return true; + script.getTop().throwError("wrong number of arguments"); } - private: - long width, height; - std::vector > indices; - }; + return 0; + } + + int rotate(Script& script) + { + Script::Value axis = script[1].requireString(); + Script::Value angle = script[2].requireNumber(); + + size_t index = 0; + axis.get(index); + + Scalar value; + angle.get(value); + + cml::matrix_rotate_about_world_axis(transform, index, cml::rad(value)); + + return 0; + } - class Billboard : public Scenery + int setTexture(Script& script) { - public: - Billboard(const Matrix4& transform, const std::string& textureName, - SerializablePtr root) : - Scenery(transform, textureName), - index(0) + Script::Value name = script[1].requireString(); + + name.get(texture); + + return 0; + } + + int makeTilemap(Script& script) + { + Script::Value table = script[1].requireTable(); + Script::Value top = script[-1]; + + long width = 1; + long height = 1; + + table.pushField("width"); + top.get(width); + + long nTiles = 0; + + table.pushField("tiles"); + Script::Value tiles = script.getTop(); + nTiles = tiles.getLength(); + + if (nTiles % width != 0) table.throwError("invalid number of tiles"); + + std::vector< std::vector > indices; + + int i, w, h; + + height = nTiles / 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 + + i = 1; + for (h = height - 1; h >= 0; --h) { - std::map rootObj; + std::vector row; - if (root->get(rootObj)) + for (w = 0; w < width; ++w, ++i) { - std::map::iterator it; - - if ((it = rootObj.find("tile")) != rootObj.end()) - { - long value; - if ((*it).second->get(value)) - { - index = Tilemap::Index(value); - } - } - } + script.checkStack(2); + script.push(long(i)); + tiles.pushField(); - image.getTileCoords(index, texCoords); - } + long index; + top.get(index); - 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(); - } + row.push_back(Tilemap::Index(index)); + } - bool isVisible(const Camera& cam) - { - return false; + indices[h] = row; } - private: - Tilemap::Index index; - Scalar texCoords[8]; - }; + Vector4 vertices[height+1][width+1]; + Matrix4 transposedTransform = transform; + transposedTransform.transpose(); - static bool loadBox(Aabb& theBox, SerializablePtr obj) - { - std::vector numbers; + 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; + } + } - if (obj->get(numbers)) + for (int h = 0; h < height; ++h) { - if (numbers.size() == 6) + for (int w = 0; w < width; ++w) { - double num; + if (indices[h][w] == Tilemap::NO_TILE) continue; - if (numbers[0]->getNumber(num)) - { + 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]); + + Quad* quad = new Quad(quadVertices, texture, indices[h][w]); + boost::shared_ptr quadPtr(quad); + + octree->insert(quadPtr); } } - return false; + return 0; } -public: - SceneImpl(const std::string& name) : - Mippleton(name) + int makeBillboard(Script& script) { - loadFromFile(); - } + Script::Value table = script[1]; + Script::Value top = script[-1]; + long index = 0; + long width = 1; + bool blending = false; + bool fog = false; - void loadInstructions(SerializablePtr root) - { - std::vector rootObj; - - if (root->get(rootObj)) + if (table.isTable()) { - std::vector::iterator it; + table.pushField("tile"); + top.get(index); - Matrix4 transform; - std::string texture; + table.pushField("u_scale"); + top.get(width); - 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); - } - } - } - } - } + table.pushField("blend"); + top.get(blending); + table.pushField("fog"); + top.get(fog); + } - void loadFromFile() - { - std::string filePath = Scene::getPathToResource(getName()); + Vector4 vertices[2][width+1]; - Deserializer deserializer(filePath, true); + Matrix4 transposedTransform = transform; + transposedTransform.transpose(); - SerializablePtr root = deserializer.deserialize(); + Scalar xf; + Scalar increment = 1.0 / Scalar(width); - if (root) + for (int h = 0; h <= 1; ++h) { - std::map rootObj; - - if (root->get(rootObj)) + xf = 0.0; + for (int w = 0; w <= width; ++w, xf += increment) { - 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); - } + vertices[h][w] = Vector4(xf, Scalar(h), 0.0, 1.0) * + transposedTransform; } } - } + for (int w = 0; w < width; ++w) + { + Vector3 quadVertices[4]; - void draw(Scalar alpha) - { - SceneryVector::iterator it; + 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 (it = objects.begin(); it != objects.end(); it++) - { - //std::cout << "draw object"; - (*it)->draw(alpha); - } - } + Quad* quad = new Quad(quadVertices, texture, Tilemap::Index(index)); + quad->setBlending(blending); + quad->setFog(fog); + boost::shared_ptr quadPtr(quad); - Aabb playfieldBounds; - Aabb maximumBounds; + octree->insert(quadPtr); + } - typedef std::vector > SceneryVector; - SceneryVector objects; + return 0; + } }; -Scene::Scene(const std::string& name) : - // pass through - impl_(Scene::SceneImpl::retain(name), &Scene::SceneImpl::release) {} +static void importSceneBindings(Script& script, Meh& scene) +{ + script.importFunction("SetPlayfieldBounds", + boost::bind(&Meh::setPlayfieldBounds, &scene, _1)); + script.importFunction("SetMaximumBounds", + boost::bind(&Meh::setMaximumBounds, &scene, _1)); + script.importFunction("ResetTransform", + boost::bind(&Meh::resetTransform, &scene, _1)); + script.importFunction("Translate", + boost::bind(&Meh::translate, &scene, _1)); + script.importFunction("Scale", + boost::bind(&Meh::scale, &scene, _1)); + script.importFunction("Rotate", + boost::bind(&Meh::rotate, &scene, _1)); + script.importFunction("SetTexture", + boost::bind(&Meh::setTexture, &scene, _1)); + script.importFunction("MakeTilemap", + boost::bind(&Meh::makeTilemap, &scene, _1)); + script.importFunction("MakeBillboard", + boost::bind(&Meh::makeBillboard, &scene, _1)); + + long detail = 3; + Settings::getInstance().get("detail", detail); + script.push(detail); + script.set("detail"); + + script.push(Quad::LEFT); + script.set("LEFT"); + script.push(Quad::RIGHT); + script.set("RIGHT"); + script.push(Quad::TOP); + script.set("TOP"); + + script.push(Meh::X); + script.set("X"); + script.push(Meh::Y); + script.set("Y"); + script.push(Meh::Z); + script.set("Z"); +} -void Scene::draw(Scalar alpha) +OctreeP loadScene(const std::string& name) { - // pass through - impl_->draw(alpha); -} + std::string filePath = getPath(name); + Meh cool; -/** - * Specialized search location for scene files. They can be found in the - * "scenes" subdirectory of any of the searched directories. - */ + Script script; + script.importStandardLibraries(); + importLogScript(script); + importSceneBindings(script, cool); -std::string Scene::getPathToResource(const std::string& name) -{ - return Resource::getPathToResource("scenes/" + name + ".json"); + if (script.doFile(filePath) != Script::SUCCESS) + { + std::string str; + script[-1].get(str); + logScript("%s", str.c_str()); + } + + cool.octree->sort(); + return cool.octree; }