#include <Moof/Aabb.hh>
#include <Moof/Camera.hh>
#include <Moof/Entity.hh>
+#include <Moof/Exception.hh>
+#include <Moof/Library.hh>
+#include <Moof/Line.hh>
#include <Moof/Log.hh>
#include <Moof/Math.hh>
-#include <Moof/Mippleton.hh>
-#include <Moof/Octree.hh>
+//#include <Moof/Octree.hh>
#include <Moof/Script.hh>
#include <Moof/Settings.hh>
-#include <Moof/Tilemap.hh>
+#include "Character.hh"
#include "Scene.hh"
+#include "Tilemap.hh"
-struct Scene::Impl : public Mf::Mippleton<Impl>
+struct Scene::Impl : public Mf::Library<Impl>
{
- class Quad : public Mf::Entity, public Mf::OctreeInsertable
+ struct Quad : public Mf::Entity
{
- Mf::Scalar vertices_[12];
- Mf::Scalar texCoords_[8];
-
- Mf::Tilemap tilemap_;
-
- bool blending_;
- bool fog_;
-
- Mf::Aabb aabb_;
- Mf::Sphere sphere_;
-
- public:
-
- enum SURFACE_TYPE
+ enum SURFACE
{
+ NONE = 0,
LEFT = 1,
RIGHT = 2,
TOP = 3
};
Quad(const Mf::Vector3 vertices[4], const std::string& texture,
- Mf::Tilemap::Index tileIndex) :
- tilemap_(texture),
- blending_(false),
- fog_(false)
+ Tilemap::Index tileIndex) :
+ mTilemap(texture),
+ mBlending(false),
+ mFog(false),
+ mSurface(NONE)
{
for (int i = 0, num = 0; i < 4; ++i)
{
for (int j = 0; j < 3; ++j, ++num)
{
- vertices_[num] = vertices[i][j];
+ mVertices[num] = vertices[i][j];
}
}
- if (!tilemap_.getTileCoords(tileIndex, texCoords_))
+ if (!mTilemap.getTileCoords(tileIndex, mTexCoords))
{
Mf::logWarning("no index %d in texture %s", tileIndex,
texture.c_str());
- texCoords_[0] = texCoords_[1] =
- texCoords_[3] = texCoords_[6] = 0.0;
- texCoords_[2] = texCoords_[4] =
- texCoords_[5] = texCoords_[7] = 1.0;
+ mTexCoords[0] = mTexCoords[1] =
+ mTexCoords[3] = mTexCoords[6] = 0.0;
+ mTexCoords[2] = mTexCoords[4] =
+ mTexCoords[5] = mTexCoords[7] = 1.0;
}
- aabb_.encloseVertices(vertices, 4);
- sphere_.point = aabb_.getCenter();
- sphere_.radius = (aabb_.min - sphere_.point).length();
+ mAabb.encloseVertices(vertices, 4);
+ mSphere.point = mAabb.getCenter();
+ mSphere.radius = (mAabb.min - mSphere.point).length();
}
void setBlending(bool blending)
{
- blending_ = blending;
+ mBlending = blending;
}
void setFog(bool fog)
{
- fog_ = fog;
+ mFog = fog;
+ }
+
+ void setSurface(SURFACE type)
+ {
+ mSurface = type;
+ }
+
+ SURFACE getSurface() const
+ {
+ return mSurface;
}
void draw(Mf::Scalar alpha = 0.0) const
{
- if (blending_)
+ if (mBlending)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- if (fog_)
+ if (mFog)
{
glEnable(GL_FOG);
glFogi(GL_FOG_MODE, GL_LINEAR);
}
//glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- tilemap_.bind();
+ mTilemap.bind();
- glVertexPointer(3, GL_SCALAR, 0, vertices_);
- glTexCoordPointer(2, GL_SCALAR, 0, texCoords_);
+ glVertexPointer(3, GL_SCALAR, 0, mVertices);
+ glTexCoordPointer(2, GL_SCALAR, 0, mTexCoords);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
bool isVisible(const Mf::Frustum& frustum) const
{
- return sphere_.isVisible(frustum);
- }
-
-
- bool isInsideAabb(const Mf::Aabb& aabb) const
- {
- // make sure the entity is fully inside the volume
- if (!(aabb_.max[0] < aabb.max[0] &&
- aabb_.min[0] > aabb.min[0] &&
- aabb_.max[1] < aabb.max[1] &&
- aabb_.min[1] > aabb.min[1] &&
- aabb_.max[2] < aabb.max[2] &&
- aabb_.min[2] > aabb.min[2]))
- {
- return false;
- }
-
- return true;
+ return mSphere.isVisible(frustum);
}
- int getOctant(const Mf::Aabb& aabb) const
- {
- int octantNum = -1;
-
- Mf::Plane::Halfspace halfspace;
-
- Mf::Plane xy = aabb.getPlaneXY();
- halfspace = xy.intersects(sphere_);
- if (halfspace == Mf::Plane::INTERSECT)
- {
- halfspace = xy.intersects(aabb_);
- }
- if (halfspace == Mf::Plane::POSITIVE)
- {
- Mf::Plane xz = aabb.getPlaneXZ();
- halfspace = xz.intersects(sphere_);
- if (halfspace == Mf::Plane::INTERSECT)
- {
- halfspace = xz.intersects(aabb_);
- }
-
- if (halfspace == Mf::Plane::POSITIVE)
- {
- Mf::Plane yz = aabb.getPlaneYZ();
- halfspace = yz.intersects(sphere_);
- if (halfspace == Mf::Plane::INTERSECT)
- {
- halfspace = yz.intersects(aabb_);
- }
-
- if (halfspace == Mf::Plane::POSITIVE)
- {
- octantNum = 2;
- }
- else if (halfspace == Mf::Plane::NEGATIVE)
- {
- octantNum = 3;
- }
- }
- else if (halfspace == Mf::Plane::NEGATIVE)
- {
- Mf::Plane yz = aabb.getPlaneYZ();
- halfspace = yz.intersects(sphere_);
- if (halfspace == Mf::Plane::INTERSECT)
- {
- halfspace = yz.intersects(aabb_);
- }
-
- if (halfspace == Mf::Plane::POSITIVE)
- {
- octantNum = 1;
- }
- else if (halfspace == Mf::Plane::NEGATIVE)
- {
- octantNum = 0;
- }
- }
- }
- else if (halfspace == Mf::Plane::NEGATIVE)
- {
- Mf::Plane xz = aabb.getPlaneXZ();
- halfspace = xz.intersects(sphere_);
- if (halfspace == Mf::Plane::INTERSECT)
- {
- halfspace = xz.intersects(aabb_);
- }
-
- if (halfspace == Mf::Plane::POSITIVE)
- {
- Mf::Plane yz = aabb.getPlaneYZ();
- halfspace = yz.intersects(sphere_);
- if (halfspace == Mf::Plane::INTERSECT)
- {
- halfspace = yz.intersects(aabb_);
- }
-
- if (halfspace == Mf::Plane::POSITIVE)
- {
- octantNum = 6;
- }
- else if (halfspace == Mf::Plane::NEGATIVE)
- {
- octantNum = 7;
- }
- }
- else if (halfspace == Mf::Plane::NEGATIVE)
- {
- Mf::Plane yz = aabb.getPlaneYZ();
- halfspace = yz.intersects(sphere_);
- if (halfspace == Mf::Plane::INTERSECT)
- {
- halfspace = yz.intersects(aabb_);
- }
-
- if (halfspace == Mf::Plane::POSITIVE)
- {
- octantNum = 5;
- }
- else if (halfspace == Mf::Plane::NEGATIVE)
- {
- octantNum = 4;
- }
- }
- }
+ Mf::Scalar mVertices[12];
+ Mf::Scalar mTexCoords[8];
+
+ Tilemap mTilemap;
- return octantNum;
- }
+ bool mBlending;
+ bool mFog;
+ SURFACE mSurface;
};
- Mf::Script script;
+ Mf::Matrix4 mTransform;
+ std::string mTexture;
- Mf::Matrix4 transform;
- std::string texture;
+ //Mf::Octree<Quad>::Ptr mOctree;
+ std::list< boost::shared_ptr<Impl::Quad> > mObjects;
+ std::list< Mf::Line<2> > mLines;
- Mf::Octree<Quad>::Ptr octree;
+ Mf::Aabb<3> mBounds;
enum AXIS
};
-
explicit Impl(const std::string& name) :
- Mf::Mippleton<Impl>(name)
- {
- script.importStandardLibraries();
- importLogScript(script);
-
- importSceneBindings(script);
- loadFromFile();
- }
+ Mf::Library<Impl>(name) {}
void importSceneBindings(Mf::Script& script)
{
- script.importFunction("SetPlayfieldBounds",
- boost::bind(&Impl::setPlayfieldBounds, this, _1));
- script.importFunction("SetMaximumBounds",
- boost::bind(&Impl::setMaximumBounds, this, _1));
+ script.importFunction("SetBounds",
+ boost::bind(&Impl::setBounds, this, _1));
script.importFunction("ResetTransform",
boost::bind(&Impl::resetTransform, this, _1));
script.importFunction("Translate",
boost::bind(&Impl::rotate, this, _1));
script.importFunction("SetTexture",
boost::bind(&Impl::setTexture, this, _1));
- script.importFunction("MakeTilemap",
- boost::bind(&Impl::makeTilemap, this, _1));
- script.importFunction("MakeBillboard",
- boost::bind(&Impl::makeBillboard, this, _1));
+ script.importFunction("DrawTilemap",
+ boost::bind(&Impl::drawTilemap, this, _1));
+ script.importFunction("DrawTile",
+ boost::bind(&Impl::drawTile, this, _1));
- long detail = 3;
+ int detail = 3;
Mf::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(1); script.set("LOW");
+ script.push(2); script.set("MEDIUM");
+ script.push(3); script.set("HIGH");
script.push(X); script.set("X");
script.push(Y); script.set("Y");
script.push(Z); script.set("Z");
+
+ script.push(Quad::LEFT); script.set("LEFT");
+ script.push(Quad::RIGHT); script.set("RIGHT");
+ script.push(Quad::TOP); script.set("TOP");
}
- void loadFromFile()
+ Mf::Script::Status load(Mf::Script& script)
{
std::string filePath = Scene::getPath(getName());
+ if (filePath == "") return Mf::Script::FILE_ERROR;
- if (script.doFile(filePath) != Mf::Script::SUCCESS)
- {
- std::string str;
- script[-1].get(str);
- Mf::logScript("%s", str.c_str());
- }
+ importSceneBindings(script);
+ return script.doFile(filePath);
}
- static int loadBox(Mf::Script& script, Mf::Aabb& aabb)
+ static int loadBox(Mf::Script& script, Mf::Aabb<3>& aabb)
{
Mf::Script::Value table[] =
{
script[2].requireTable()
};
- if (!table[0].isTable() || !table[1].isTable())
- {
- Mf::logWarning("wrong arguments to setPlayfieldBounds; ignoring...");
- return 0;
- }
-
for (int i = 0; i <= 1; ++i)
{
for (int j = 1; j <= 3; ++j)
{
- script.push((long)j);
+ script.push(j);
table[i].pushField();
}
}
return 0;
}
- int setPlayfieldBounds(Mf::Script& script)
- {
- Mf::Aabb bounds;
- return loadBox(script, bounds);
- }
-
- int setMaximumBounds(Mf::Script& script)
+ int setBounds(Mf::Script& script)
{
- Mf::Aabb bounds;
- int ret = loadBox(script, bounds);
- octree = Mf::Octree<Quad>::alloc(bounds);
+ int ret = loadBox(script, mBounds);
+ //mOctree = Mf::Octree<Quad>::alloc(mBounds);
return ret;
}
int resetTransform(Mf::Script& script)
{
- transform.identity();
+ mTransform.identity();
return 0;
}
Mf::Matrix4 translation;
cml::matrix_translation(translation, vec);
- transform = translation * transform;
+ mTransform = translation * mTransform;
return 0;
}
Mf::Matrix4 scaling;
cml::matrix_scale(scaling, vec);
- transform = scaling * transform;
+ mTransform = scaling * mTransform;
}
else if (script.getSize() == 1)
{
Mf::Matrix4 scaling;
cml::matrix_uniform_scale(scaling, value);
- transform = scaling * transform;
+ mTransform = scaling * mTransform;
}
else
{
int rotate(Mf::Script& script)
{
- Mf::Script::Value axis = script[1].requireString();
+ Mf::Script::Value axis = script[1].requireNumber();
Mf::Script::Value angle = script[2].requireNumber();
size_t index = 0;
Mf::Scalar value;
angle.get(value);
- cml::matrix_rotate_about_world_axis(transform, index, cml::rad(value));
+ cml::matrix_rotate_about_world_axis(mTransform, index, cml::rad(value));
return 0;
}
int setTexture(Mf::Script& script)
{
- Mf::Script::Value name = script[1].requireString();
-
- name.get(texture);
-
+ script[1].requireString().get(mTexture);
return 0;
}
- int makeTilemap(Mf::Script& script)
+ int drawTilemap(Mf::Script& script)
{
Mf::Script::Value table = script[1].requireTable();
Mf::Script::Value top = script[-1];
- long width = 1;
- long height = 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();
- long nTiles = 0;
+ int nTiles = 0;
- table.pushField("tiles");
+ //table.pushField("tiles");
Mf::Script::Value tiles = script.getTop();
nTiles = tiles.getLength();
if (nTiles % width != 0) table.throwError("invalid number of tiles");
- std::vector< std::vector<Mf::Tilemap::Index> > indices;
+ std::vector< std::vector<Tilemap::Index> > 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
+ // 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::vector<Mf::Tilemap::Index> row;
+ std::vector<Tilemap::Index> row;
for (w = 0; w < width; ++w, ++i)
{
script.checkStack(2);
- script.push(long(i));
+ script.push(i);
tiles.pushField();
- long index;
+ Tilemap::Index index;
top.get(index);
- row.push_back(Mf::Tilemap::Index(index));
+ row.push_back(index);
}
indices[h] = row;
Mf::Vector4 vertices[height+1][width+1];
- Mf::Matrix4 transposedTransform = transform;
+ Mf::Matrix4 transposedTransform = mTransform;
transposedTransform.transpose();
for (int h = 0; h <= height; ++h)
{
for (int w = 0; w <= width; ++w)
{
- vertices[h][w] = Mf::Vector4(Mf::Scalar(w), Mf::Scalar(h), 0.0, 1.0) *
- transposedTransform;
+ vertices[h][w] = Mf::Vector4(w, h, 0.0, 1.0) * transposedTransform;
}
}
{
for (int w = 0; w < width; ++w)
{
- if (indices[h][w] == Mf::Tilemap::NO_TILE) continue;
+ if (indices[h][w] == Tilemap::NO_TILE) continue;
- Mf::Vector3 quadVertices[4];
+ Mf::Vector3 demotedVertices[4];
- quadVertices[0] = Mf::demote(vertices[h][w]);
- quadVertices[1] = Mf::demote(vertices[h][w+1]);
- quadVertices[2] = Mf::demote(vertices[h+1][w+1]);
- quadVertices[3] = Mf::demote(vertices[h+1][w]);
+ 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]);
- Quad* quad = new Quad(quadVertices, texture, indices[h][w]);
- boost::shared_ptr<Quad> quadPtr(quad);
+ Quad* quad = new Quad(demotedVertices, mTexture, indices[h][w]);
+ quad->setSurface(surface);
- octree->insert(quadPtr);
+ 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
+ }
+
+ boost::shared_ptr<Quad> quadPtr(quad);
+ //mOctree->insert(quadPtr);
+ mObjects.push_back(quadPtr);
}
}
return 0;
}
- int makeBillboard(Mf::Script& script)
+ int drawTile(Mf::Script& script)
{
- Mf::Script::Value table = script[1];
+ Mf::Script::Value param = script[1];
Mf::Script::Value top = script[-1];
- long index = 0;
- long width = 1;
- bool blending = false;
- bool fog = false;
+ Tilemap::Index index = 0;
+ int width = 1;
+ bool blending = false;
+ bool fog = false;
- if (table.isTable())
+ if (param.isTable())
{
- table.pushField("tile");
+ script.push(1);
+ param.pushField();
top.get(index);
- table.pushField("u_scale");
+ param.pushField("u_scale");
top.get(width);
- table.pushField("blend");
+ param.pushField("blend");
top.get(blending);
- table.pushField("fog");
+ param.pushField("fog");
top.get(fog);
}
+ else if (param.isNumber())
+ {
+ param.get(index);
+ }
Mf::Vector4 vertices[2][width+1];
- Mf::Matrix4 transposedTransform = transform;
+ Mf::Matrix4 transposedTransform = mTransform;
transposedTransform.transpose();
Mf::Scalar xf;
for (int w = 0; w < width; ++w)
{
- Mf::Vector3 quadVertices[4];
+ Mf::Vector3 demotedVertices[4];
- quadVertices[0] = Mf::demote(vertices[0][w]);
- quadVertices[1] = Mf::demote(vertices[0][w+1]);
- quadVertices[2] = Mf::demote(vertices[1][w+1]);
- quadVertices[3] = Mf::demote(vertices[1][w]);
+ 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]);
- Quad* quad = new Quad(quadVertices, texture, Mf::Tilemap::Index(index));
+ Quad* quad = new Quad(demotedVertices, mTexture, index);
quad->setBlending(blending);
quad->setFog(fog);
boost::shared_ptr<Quad> quadPtr(quad);
-
- octree->insert(quadPtr);
+ //mOctree->insert(quadPtr);
+ mObjects.push_back(quadPtr);
}
return 0;
Scene::Scene(const std::string& name) :
// pass through
- impl_(Scene::Impl::getInstance(name)) {}
+ mImpl(Scene::Impl::getInstance(name)) {}
+
+
+Mf::Script::Status Scene::load(Mf::Script& script)
+{
+ // pass through
+ return mImpl->load(script);
+}
void Scene::draw(Mf::Scalar alpha) const
{
- impl_->octree->draw(alpha);
+ //mImpl->mOctree->draw(alpha);
+ std::list< boost::shared_ptr<Impl::Quad> >& objects = mImpl->mObjects;
+ std::list< boost::shared_ptr<Impl::Quad> >::const_iterator it;
+
+ for (it = objects.begin(); it != objects.end(); ++it)
+ {
+ (*it)->draw(alpha);
+ }
+
+ mImpl->mBounds.draw();
}
void Scene::drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const
{
- impl_->octree->drawIfVisible(alpha, frustum);
+ //mImpl->mOctree->drawIfVisible(alpha, frustum);
+ std::list< boost::shared_ptr<Impl::Quad> >& objects = mImpl->mObjects;
+ std::list< boost::shared_ptr<Impl::Quad> >::const_iterator it;
+
+ for (it = objects.begin(); it != objects.end(); ++it)
+ {
+ (*it)->drawIfVisible(alpha, frustum);
+ }
+
+ mImpl->mBounds.draw();
+}
+
+
+bool Scene::checkForCollision(Character& character)
+{
+ return false;
+ //std::list< boost::shared_ptr<Impl::Quad> > objects;
+ //std::list<Mf::Octree<Impl::Quad>::InsertableP> objects;
+ //mImpl->mOctree->getNearbyObjects(objects, character);
+
+ std::list< boost::shared_ptr<Impl::Quad> >& objects = mImpl->mObjects;
+ std::list< boost::shared_ptr<Impl::Quad> >::const_iterator it;
+
+ int collisions = 0;
+ Mf::Sphere<3> sphere = character.getSphere();
+
+ for (it = objects.begin(); it != objects.end(); ++it)
+ {
+ Impl::Quad::SURFACE type = (*it)->getSurface();
+ if (type == Impl::Quad::NONE) continue;
+
+ if (Mf::checkCollision(sphere, (*it)->getSphere()))
+ {
+ ++collisions;
+
+ Mf::Vector2 impulse(0.0, 0.0);
+ Mf::Vector2 p = character.getState().momentum;
+
+ Mf::State2 state = character.getState(1.0);
+ sphere = character.getSphere();
+ Mf::Scalar alpha = 1.0;
+ while (Mf::checkCollision(sphere, (*it)->getSphere()))
+ {
+ alpha -= 0.05;
+ state = character.getState(alpha);
+ }
+
+ character.setPosition(state.position);
+
+ //switch (type)
+ //{
+ //case Impl::Quad::TOP:
+ //if (p[1] < 0.0) impulse[1] = -p[1];
+ //break;
+ //case Impl::Quad::LEFT:
+ //if (p[0] > 0.0) impulse[0] = 1.5*-p[0];
+ //break;
+ //case Impl::Quad::RIGHT:
+ //if (p[0] < 0.0) impulse[0] = 1.5*-p[0];
+ //break;
+ //}
+
+ //character.addImpulse(impulse);
+ }
+ }
+
+ if (collisions > 0)
+ {
+ Mf::logInfo("collisions: %d", collisions);
+ }
+
+ return false;
}