X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FScene.cc;h=16e1aef55b210903fff7caeb2e65bb4fb344df55;hp=9b4d1fdf65ee3544cd29bc176a08bc3bdc3e9787;hb=c78934a448d0126709fccec3d5a636b3baa87da4;hpb=8a1acac01b444dccf8b57cedf08392ada2e473c1 diff --git a/src/Scene.cc b/src/Scene.cc index 9b4d1fd..16e1aef 100644 --- a/src/Scene.cc +++ b/src/Scene.cc @@ -1,55 +1,37 @@ -/******************************************************************************* - - 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. - -*******************************************************************************/ +/*] Copyright (c) 2009-2010, Charles McGarvey [************************** +**] All rights reserved. +* +* vi:ts=4 sw=4 tw=75 +* +* Distributable under the terms and conditions of the 2-clause BSD license; +* see the file COPYING for a complete text of the license. +* +**************************************************************************/ #include -#include #include #include #include -#include -#include +#include +#include #include #include //#include #include #include +#include #include "Character.hh" #include "Scene.hh" -#include "Tilemap.hh" -struct Scene::Impl : public Mf::Library +struct Scene::Impl : public Mf::Manager { struct Quad : public Mf::Entity { - enum SURFACE + enum Surface { NONE = 0, LEFT = 1, @@ -57,25 +39,26 @@ struct Scene::Impl : public Mf::Library TOP = 3 }; - Quad(const Mf::Vector3 vertices[4], const std::string& texture, - Tilemap::Index tileIndex) : + Quad(const Mf::Vector3* vertices[4], const std::string& texture, + Mf::Texture::TileIndex tileIndex) : mTilemap(texture), mBlending(false), mFog(false), mSurface(NONE) { - for (int i = 0, num = 0; i < 4; ++i) + for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 3; ++j, ++num) - { - mVertices[num] = vertices[i][j]; - } + mVertices[i] = *vertices[i]; + //for (int j = 0; j < 3; ++j, ++num) + //{ + //mVertices[num] = (*vertices[i])[j]; + //} } if (!mTilemap.getTileCoords(tileIndex, mTexCoords)) { - Mf::logWarning("no index %d in texture %s", tileIndex, - texture.c_str()); + Mf::logWarning << "no index " << tileIndex << + " in texture " << texture << std::endl; mTexCoords[0] = mTexCoords[1] = mTexCoords[3] = mTexCoords[6] = 0.0; @@ -83,7 +66,7 @@ struct Scene::Impl : public Mf::Library mTexCoords[5] = mTexCoords[7] = 1.0; } - mAabb.encloseVertices(vertices, 4); + mAabb.encloseVertices(mVertices, 4); mSphere.point = mAabb.getCenter(); mSphere.radius = (mAabb.min - mSphere.point).length(); } @@ -98,12 +81,12 @@ struct Scene::Impl : public Mf::Library mFog = fog; } - void setSurface(SURFACE type) + void setSurface(Surface type) { mSurface = type; } - SURFACE getSurface() const + Surface getSurface() const { return mSurface; } @@ -125,7 +108,7 @@ struct Scene::Impl : public Mf::Library //glColor4f(1.0f, 1.0f, 1.0f, 1.0f); mTilemap.bind(); - glVertexPointer(3, GL_SCALAR, 0, mVertices); + glVertexPointer(3, GL_SCALAR, 0, mVertices[0].data()); glTexCoordPointer(2, GL_SCALAR, 0, mTexCoords); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -140,14 +123,14 @@ struct Scene::Impl : public Mf::Library } - Mf::Scalar mVertices[12]; + Mf::Vector3 mVertices[4]; Mf::Scalar mTexCoords[8]; - Tilemap mTilemap; + Mf::Texture mTilemap; bool mBlending; bool mFog; - SURFACE mSurface; + Surface mSurface; }; @@ -156,9 +139,10 @@ struct Scene::Impl : public Mf::Library std::string mTexture; //Mf::Octree::Ptr mOctree; - std::list< boost::shared_ptr > mObjects; + std::list< boost::shared_ptr > mObjects; + std::list mLines; - Mf::Aabb mBounds; + Mf::Aabb<3> mBounds; enum AXIS @@ -169,10 +153,10 @@ struct Scene::Impl : public Mf::Library }; - explicit Impl(const std::string& name) : - Mf::Library(name) {} + void init(const std::string& name) {} - void importSceneBindings(Mf::Script& script) + + void importSceneBindings(Mf::Settings& settings, Mf::Script& script) { script.importFunction("SetBounds", boost::bind(&Impl::setBounds, this, _1)); @@ -192,56 +176,48 @@ struct Scene::Impl : public Mf::Library boost::bind(&Impl::drawTile, this, _1)); int detail = 3; - Mf::Settings::getInstance().get("detail", detail); - script.push(detail); script.set("detail"); + settings.get("detail", detail); + script.globals().setField("detail", detail); - script.push(1); script.set("LOW"); - script.push(2); script.set("MEDIUM"); - script.push(3); script.set("HIGH"); + script.globals().setField("LOW", 1); + script.globals().setField("MEDIUM", 2); + script.globals().setField("HIGH", 3); - script.push(X); script.set("X"); - script.push(Y); script.set("Y"); - script.push(Z); script.set("Z"); + script.globals().setField("X", X); + script.globals().setField("Y", Y); + script.globals().setField("Z", Z); - script.push(Quad::LEFT); script.set("LEFT"); - script.push(Quad::RIGHT); script.set("RIGHT"); - script.push(Quad::TOP); script.set("TOP"); + script.globals().setField("LEFT", Quad::LEFT); + script.globals().setField("RIGHT", Quad::RIGHT); + script.globals().setField("TOP", Quad::TOP); } - Mf::Script::Status load(Mf::Script& script) + Mf::Script::Result load(Mf::Settings& settings, Mf::Script& script) { - std::string filePath = Scene::getPath(getName()); - if (filePath == "") return Mf::Script::FILE_ERROR; + std::string path(getName()); + if (!Scene::getPath(path)) + { + script.push("the scene file could not be found"); + return Mf::Script::FILE_ERROR; + } - importSceneBindings(script); - return script.doFile(filePath); + importSceneBindings(settings, script); + return script.doFile(path); } - static int loadBox(Mf::Script& script, Mf::Aabb& aabb) + static int loadBox(Mf::Script& script, Mf::Aabb3& aabb) { - Mf::Script::Value table[] = - { - script[1].requireTable(), - script[2].requireTable() - }; - - for (int i = 0; i <= 1; ++i) - { - for (int j = 1; j <= 3; ++j) - { - script.push(j); - table[i].pushField(); - } - } + script[1].requireTable(); + script[2].requireTable(); - 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]); + script[1].pushField(1).get(aabb.min[0]); + script[1].pushField(2).get(aabb.min[1]); + script[1].pushField(3).get(aabb.min[2]); + script[2].pushField(1).get(aabb.max[0]); + script[2].pushField(2).get(aabb.max[1]); + script[2].pushField(3).get(aabb.max[2]); return 0; } @@ -261,14 +237,10 @@ struct Scene::Impl : public Mf::Library int translate(Mf::Script& script) { - Mf::Script::Value x = script[1].requireNumber(); - Mf::Script::Value y = script[2].requireNumber(); - Mf::Script::Value z = script[3].requireNumber(); - Mf::Vector3 vec; - x.get(vec[0]); - y.get(vec[1]); - z.get(vec[2]); + script[1].requireNumber().get(vec[0]); + script[2].requireNumber().get(vec[1]); + script[3].requireNumber().get(vec[2]); Mf::Matrix4 translation; cml::matrix_translation(translation, vec); @@ -279,29 +251,31 @@ struct Scene::Impl : public Mf::Library int scale(Mf::Script& script) { - if (script.getSize() == 3) + int size = script.stackSize(); + + if (size == 1) { - Mf::Vector3 vec; - script[1].requireNumber().get(vec[0]); - script[2].requireNumber().get(vec[1]); - script[3].requireNumber().get(vec[2]); + Mf::Scalar value = 1.0; + script[1].requireNumber().get(value); Mf::Matrix4 scaling; - cml::matrix_scale(scaling, vec); + cml::matrix_uniform_scale(scaling, value); mTransform = scaling * mTransform; } - else if (script.getSize() == 1) + else if (size == 3) { - Mf::Scalar value = 1.0; - script[1].requireNumber().get(value); + Mf::Vector3 vec; + script[1].requireNumber().get(vec[0]); + script[2].requireNumber().get(vec[1]); + script[3].requireNumber().get(vec[2]); Mf::Matrix4 scaling; - cml::matrix_uniform_scale(scaling, value); + cml::matrix_scale(scaling, vec); mTransform = scaling * mTransform; } else { - script.getTop().throwError("wrong number of arguments"); + script.top().raise("wrong number of arguments"); } return 0; @@ -309,16 +283,14 @@ struct Scene::Impl : public Mf::Library int rotate(Mf::Script& script) { - Mf::Script::Value axis = script[1].requireNumber(); - Mf::Script::Value angle = script[2].requireNumber(); - size_t index = 0; - axis.get(index); + script[1].requireNumber().get(index); Mf::Scalar value; - angle.get(value); + script[2].requireNumber().get(value); - cml::matrix_rotate_about_world_axis(mTransform, index, cml::rad(value)); + cml::matrix_rotate_about_world_axis(mTransform, + index, cml::rad(value)); return 0; } @@ -331,92 +303,84 @@ struct Scene::Impl : public Mf::Library int drawTilemap(Mf::Script& script) { - Mf::Script::Value table = script[1].requireTable(); - Mf::Script::Value top = script[-1]; - - Quad::SURFACE surface; - table.pushField("surface"); - top.get(surface); - script.pop(); - - int width = 1; - int height = 1; - - table.pushField("width"); - top.get(width); - script.pop(); - - int nTiles = 0; + Mf::Script::Slot table = script[1].requireTable(); - //table.pushField("tiles"); - Mf::Script::Value tiles = script.getTop(); - nTiles = tiles.getLength(); + int width = 1; + table.get(width, "width"); - if (nTiles % width != 0) table.throwError("invalid number of tiles"); + int nTiles = table.length(); + if (nTiles % width != 0) + { + table.raise("invalid number of tiles"); + } - std::vector< std::vector > indices; + if (width == 0) table.raise("width field must not be zero"); + int height = nTiles / width; - int i, w, h; + Mf::Vector3 vertices[height+1][width+1]; - 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 - // 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 + // do first row and first column of vertices - i = 1; - for (h = height - 1; h >= 0; --h) + for (int w = 0; w <= width; ++w) { - std::vector row; + vertices[height][w] = Mf::demote(mTransform * + Mf::Vector4(w, height, 0.0, 1.0)); + } + for (int h = 0; h < height; ++h) + { + vertices[h][0] = Mf::demote(mTransform * + Mf::Vector4(0.0, h, 0.0, 1.0)); + } - for (w = 0; w < width; ++w, ++i) + size_t i = 1; + for (int h = height - 1; h >= 0; --h) + { + for (int w = 0; w < width; ++w, ++i) { - script.checkStack(2); - script.push(i); - tiles.pushField(); + int wPlus1 = w + 1; + int hPlus1 = h + 1; - Tilemap::Index index; - top.get(index); + Mf::Texture::TileIndex index; + table.get(index, i); - row.push_back(index); - } + vertices[h][wPlus1] = Mf::demote(mTransform * + Mf::Vector4(wPlus1, h, 0.0, 1.0)); - indices[h] = row; - } + if (index == Mf::Texture::NO_TILE) continue; - Mf::Vector4 vertices[height+1][width+1]; + const Mf::Vector3* corners[4] = { + &vertices[h][w], + &vertices[h][wPlus1], + &vertices[hPlus1][wPlus1], + &vertices[hPlus1][w] + }; - Mf::Matrix4 transposedTransform = mTransform; - transposedTransform.transpose(); + Quad* quad = new Quad(corners, mTexture, index); + //quad->setSurface(surface); - for (int h = 0; h <= height; ++h) - { - for (int w = 0; w <= width; ++w) - { - vertices[h][w] = Mf::Vector4(w, h, 0.0, 1.0) * transposedTransform; + boost::shared_ptr quadPtr(quad); + mObjects.push_back(quadPtr); } } - for (int h = 0; h < height; ++h) - { - for (int w = 0; w < width; ++w) - { - if (indices[h][w] == Tilemap::NO_TILE) continue; + Quad::Surface surface = Quad::NONE; + table.get(surface, "surface"); - Mf::Vector3 demotedVertices[4]; - - demotedVertices[0] = Mf::demote(vertices[h][w]); - demotedVertices[1] = Mf::demote(vertices[h][w+1]); - demotedVertices[2] = Mf::demote(vertices[h+1][w+1]); - demotedVertices[3] = Mf::demote(vertices[h+1][w]); + if (surface != Quad::NONE) + { + // need a 2d line for collisions + // assuming the camera always looks directly to -z when the + // scene is built, simply demoting the vector again should + // project the points to the xy-plane - Quad* quad = new Quad(demotedVertices, mTexture, indices[h][w]); - quad->setSurface(surface); + Mf::Vector2 bl = Mf::demote(vertices[0][0]); + Mf::Vector2 tr = Mf::demote(vertices[height][width]); - boost::shared_ptr quadPtr(quad); - //mOctree->insert(quadPtr); - mObjects.push_back(quadPtr); - } + mLines.push_back(Mf::Line<2>(bl, tr)); } return 0; @@ -424,67 +388,57 @@ struct Scene::Impl : public Mf::Library int drawTile(Mf::Script& script) { - Mf::Script::Value param = script[1]; - Mf::Script::Value top = script[-1]; + Mf::Script::Slot param = script[1]; + Mf::Script::Slot top = script[-1]; - Tilemap::Index index = 0; - int width = 1; - bool blending = false; - bool fog = false; + Mf::Texture::TileIndex index = 0; + int width = 1; + bool blending = false; + bool fog = false; if (param.isTable()) { - script.push(1); - param.pushField(); - top.get(index); - - param.pushField("u_scale"); - top.get(width); - - param.pushField("blend"); - top.get(blending); - - param.pushField("fog"); - top.get(fog); + param.get(index, 1); + param.get(width, "u_scale"); + param.get(blending, "blend"); + param.get(fog, "fog"); } else if (param.isNumber()) { param.get(index); } - Mf::Vector4 vertices[2][width+1]; - - Mf::Matrix4 transposedTransform = mTransform; - transposedTransform.transpose(); + Mf::Vector3 vertices[2][width+1]; Mf::Scalar xf; - Mf::Scalar increment = 1.0 / Mf::Scalar(width); + Mf::Scalar increment = SCALAR(1.0) / Mf::Scalar(width); for (int h = 0; h <= 1; ++h) { xf = 0.0; for (int w = 0; w <= width; ++w, xf += increment) { - vertices[h][w] = Mf::Vector4(xf, Mf::Scalar(h), 0.0, 1.0) * - transposedTransform; + vertices[h][w] = Mf::demote(mTransform * + Mf::Vector4(xf, Mf::Scalar(h), 0.0, 1.0)); } } for (int w = 0; w < width; ++w) { - Mf::Vector3 demotedVertices[4]; + int wPlus1 = w + 1; - demotedVertices[0] = Mf::demote(vertices[0][w]); - demotedVertices[1] = Mf::demote(vertices[0][w+1]); - demotedVertices[2] = Mf::demote(vertices[1][w+1]); - demotedVertices[3] = Mf::demote(vertices[1][w]); + const Mf::Vector3* corners[4] = { + &vertices[0][w], + &vertices[0][wPlus1], + &vertices[1][wPlus1], + &vertices[1][w] + }; - Quad* quad = new Quad(demotedVertices, mTexture, index); + Quad* quad = new Quad(corners, mTexture, index); quad->setBlending(blending); quad->setFog(fog); boost::shared_ptr quadPtr(quad); - //mOctree->insert(quadPtr); mObjects.push_back(quadPtr); } @@ -498,16 +452,15 @@ Scene::Scene(const std::string& name) : mImpl(Scene::Impl::getInstance(name)) {} -Mf::Script::Status Scene::load(Mf::Script& script) +Mf::Script::Result Scene::load(Mf::Settings& settings, Mf::Script& script) { // pass through - return mImpl->load(script); + return mImpl->load(settings, script); } void Scene::draw(Mf::Scalar alpha) const { - //mImpl->mOctree->draw(alpha); std::list< boost::shared_ptr >& objects = mImpl->mObjects; std::list< boost::shared_ptr >::const_iterator it; @@ -519,9 +472,9 @@ void Scene::draw(Mf::Scalar alpha) const mImpl->mBounds.draw(); } -void Scene::drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const +void Scene::drawIfVisible(Mf::Scalar alpha, + const Mf::Frustum& frustum) const { - //mImpl->mOctree->drawIfVisible(alpha, frustum); std::list< boost::shared_ptr >& objects = mImpl->mObjects; std::list< boost::shared_ptr >::const_iterator it; @@ -530,10 +483,40 @@ void Scene::drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const (*it)->drawIfVisible(alpha, frustum); } + std::list< Mf::Line<2> >& lines = mImpl->mLines; + std::list< Mf::Line<2> >::const_iterator lit; + + for (lit = lines.begin(); lit != lines.end(); ++lit) + { + (*lit).draw(alpha); + } + mImpl->mBounds.draw(); } +bool Scene::castRay(const Mf::Ray<2>& ray, + std::list::Contact>& hits) const +{ + std::list< Mf::Line<2> >& lines = mImpl->mLines; + std::list< Mf::Line<2> >::const_iterator it; + + for (it = lines.begin(); it != lines.end(); ++it) + { + Mf::Ray<2>::Contact hit; + Mf::Scalar d = (*it).intersectRay(ray, hit); + if (d > 0.0) + { + hits.push_back(hit); + //return true; + } + } + + hits.sort(); + return !hits.empty(); + //return false; +} + bool Scene::checkForCollision(Character& character) { return false; @@ -545,11 +528,11 @@ bool Scene::checkForCollision(Character& character) std::list< boost::shared_ptr >::const_iterator it; int collisions = 0; - Mf::Sphere sphere = character.getSphere(); + Mf::Sphere<3> sphere = character.getSphere(); for (it = objects.begin(); it != objects.end(); ++it) { - Impl::Quad::SURFACE type = (*it)->getSurface(); + Impl::Quad::Surface type = (*it)->getSurface(); if (type == Impl::Quad::NONE) continue; if (Mf::checkCollision(sphere, (*it)->getSphere())) @@ -589,18 +572,15 @@ bool Scene::checkForCollision(Character& character) if (collisions > 0) { - Mf::logInfo("collisions: %d", collisions); + Mf::logInfo << "collisions: " << collisions << std::endl; } return false; } -std::string Scene::getPath(const std::string& name) +bool Scene::getPath(std::string& name) { - return Mf::Resource::getPath("scenes/" + name + ".lua"); + return Mf::Resource::getPath(name, "scenes/", "lua"); } - -/** vim: set ts=4 sw=4 tw=80: *************************************************/ -