[log_level=$withval],
[log_level=3])
+AC_ARG_ENABLE([double],
+ [ --enable-double use double-precision numbers],
+ [double=$enableval],
+ [double=no])
+
if test x$developer = xyes
then
CXXFLAGS="$CXXFLAGS -Wextra -Wno-unused-parameter"
fi
+if test x$double = xyes
+then
+ AC_DEFINE([USE_DOUBLE_PRECISION], 1,
+ [Define to 1 if you want to use double-precison numbers.])
+fi
+
+
AC_DEFINE_UNQUOTED([YOINK_LOGLEVEL], [$log_level],
[Define to detail level of logging.])
detail = 3
-- Set the amount of time in seconds between each update of the physics
--- state. A value of 0.01 or lower is ideal for accurate physics
--- approximations. Values that are much higher cause the CPU to do less
+-- state. A value of 100 or higher is ideal for accurate physics
+-- approximations. Values that are much lower cause the CPU to do less
-- work, but accuracy will suffer. Errors could be introduced in the game
--- with extremely high values.
+-- with extremely low values.
-timestep = 0.01
+timestep = 80
-- Set the maximum number of frames that can be drawn per second. A value
-- of 50 is pretty good. If your computer is really old, you can get away
-- not be able to update the physics on schedule which could actually
-- significantly lower the quality of the animation.
-maxfps = 45
+maxfps = 40
-- Set whether or not to print the current actual framerate to the console.
syntax used is lua.
.B yoink
looks for configuration files and loads them in this order, the options from
-each subsequent configuration files taking precedence over the same options from
-previous files.
+each subsequent configuration files taking precedence over the same options if
+they exist in previous files.
.TP
1. @DATADIR@/yoinkrc
This is the base configuration file which should be considered read-only. Look
file.
.PP
Options that are passed as arguments take precedence over options loaded from
-the configuration file(s). This mechanism is good for running the game with a
-temporary setting which you do not intend to retain. Examples:
+the configuration file(s). This mechanism can be used to play the game with
+temporary settings which you do not intend to retain. Here are some examples of
+passing options on the command-line:
.PP
.TP
yoink fullscreen=true
Here is a list of some of the options available:
.TP
.B detail
-The level of detail. Possible values are high, medium, and low. This effects
-the number of objects drawn to the screen. A high level of detail will draw
-everything but could cause poor frame rates if the graphics driver can't keep up
-with the load. Lower levels will omit certain details which aren't crucial for
-playing the game with the benefit of higher frame rates. See the Notes for more
-ways to get good performance.
+The level of detail. Possible values are 1, 2, or 3, 1 meaning the least amount
+of detail and 3 meaning the most. This effects the number of objects drawn to
+the screen. A high level of detail will draw everything but could cause poor
+frame rates if the graphics driver can't keep up with the load. Lower levels
+will omit certain details which aren't crucial for playing the game with the
+benefit of higher frame rates. See the Notes for more ways to increase the
+game's performance. The default value is 3.
.TP
.B doublebuffer
-If true, double-buffering will be used to render animations with minimal
-distortions. Otherwise, a single buffer will be used. The recommended value is
-true.
+If true, double-buffering will be used to help minimize distortion and artifacts
+caused by the animation of the game. Otherwise, a single buffer will be used.
+The default value is true.
.TP
.B fullscreen
If true, the window will capture the display and render the game in full screen
-splendor. A value of false means the game will run in a window.
+splendor. A value of false means the game will run in a window. The default
+value is false.
.TP
.B maxfps
-The maximum number of frames to be drawn per second. A value of 50 is pretty
-good. If your computer is pretty old, can get away with decreasing this value
-and still have reasonably smooth animation. You can set this to a very high
-number to effectively render as many frames as is possible, but the actual rate
-could be limited by vertical display synchronization, depending on the X11
-driver and settings used. You should not set this option higher than the point
-where the vertical synchronization effectively limits the draw rate or else the
-game may not be able to update the physics on schedule which could actually
-significantly lower the quality of the animation.
+The maximum number of frames to be drawn per second. If your computer is really
+old, you can get away with decreasing this value and still have reasonably
+smooth animation. You can set this to a very high number to effectively render
+as many frames as is possible, but the actual rate could be limited by vertical
+display synchronization, depending on the X11 driver and settings used. You
+should not set this option higher than the point where the vertical
+synchronization effectively limits the draw rate or else the game may not be
+able to update the physics on schedule which could actually significantly lower
+the quality of the animation. The default value is 40.
.TP
.B printfps
-If true, the current number of frames being draw per second will be printed to
-the console. This is usually off by default, but you can set this to true if
-you're interested in the draw rate you're actually getting.
+If true, the current number of frames being drawn per second will be printed to
+the console. The default value is false.
.TP
.B resizable
If true, the window will be resizable by the window manager. This option is
-meaningless if the game is drawing to the full screen.
+meaningless if the game is drawing to the full screen. The default option is
+true.
.TP
.B showcursor
This option effects the visibility of the cursor while it is "hovering" over the
-window. If the value is true, the cursor will be visible. Otherwise, the
-cursor will be hidden.
+display. If the value is true, the cursor will be visible. Otherwise, the
+cursor will be hidden. The default value is true.
.TP
.B timestep
-The amount of time in seconds between each update of the physics state. A value
-of 0.01 or lower is ideal for accurate physics approximations. Values that are
-much higher cause the CPU to do less work, but accuracy will suffer. Errors
-could be introduced in the game with extremely high values.
+The number of times per second the simulation state will be updated. A value
+of 100 or higher is ideal for a better physical simulation. Values that are
+much lower cause the CPU to do less work, but accuracy will suffer. Errors
+could be introduced in the game with extremely low values. The default value
+is 80.
.TP
.B videomode
The resolution or size of the window. The value is an array with three number
elements representing the width, height, and bits per pixel that make up the
-video mode. A typical value is {800,600} for a size of 800x600 pixels with
-millions of colors (the third number is optional).
+video mode. The third number is optional. The default value is {800, 600}.
.PP
This is only a list of the more useful options. You'll have to use the source
to find out about the more esoteric options, but you probably won't need to.
.B yoink
will look for a file at
.I $HOME/.yoinkrc
-and load it as a configuration file. Saving options within the game will cause
-this file to be over-written with the new options, unless the
-.I YOINKRC
-variable is set.
+and load it as a configuration file.
.TP
USER
.B yoink
accelerated OpenGL driver installed and working, depending on how fast your CPU
is. Yoink is really not all that heavy on graphics, but it doesn't take much to
overload a software implementation. If you're stuck without hardware
-acceleration, there are some things you can do to get better frame rates:
+acceleration, there are some things you can do to get better frame rates, in
+order of effectiveness:
.TP
1. Decrease the resolution.
Use the
.I videomode
-option. This speeds up software renderers considerably.
+option or just resize the window if the
+.I fullscreen
+option is false and the
+.I resizable
+option is true. This speeds up software renderers considerably.
.TP
-2. Decrease the level of rendering detail.
+2. Decrease the timestep.
+Use the
+.I timestep
+option. You can set the timestep to be as low as the your
+.I maxfps
+option, but it is not recommended to set this lower than the target frame rate.
+Remember the trade-off here is decreased simulation accuracy. Try this to set
+your frame rate to 30Hz and your timestep to 60Hz:
+.PP
+yoink maxfps=30 timestep=maxfps\\*2
+.TP
+3. Decrease the level of rendering detail.
Use the
.I detail
option. The game world may look sparse or incomplete, but that may be better
than choppy animation.
-.PP
-On the other hand, if you already get high frame rates, you may also want to cap
-the rate so that your computer doesn't do more work than it really needs to.
-You can get reasonably smooth animation at around 30fps, but you can probably
-tell a difference between that and a higher rate like 50fps. The latter will
-look noticeably smoother and nice, while the former is just "okay." See
-the
-.I maxfps
-option.
.br
.SH BUGS
.PP
previous = current;
- updateContainers();
+ //updateContainers();
}
animation_.update(t, dt);
- updateContainers();
+ //updateContainers();
}
-void Character::updateContainers()
-{
- aabb_.init(Mf::Vector3(current.position[0]-16.0, current.position[1]-16.0, z),
- Mf::Vector3(current.position[0]+16.0, current.position[1]+16.0, z));
- sphere_.point = Mf::Vector3(current.position[0], current.position[1], z);
- sphere_.radius = (aabb_.min - sphere_.point).length();
-}
-
-void Character::handleEvent(const Mf::Event& event)
-{
- // really just for heroine...
-
- Mf::Scalar force = 4000.0;
-
- Mf::Vector2 left = Mf::Vector2(-force, 0.0);
- Mf::Vector2 right = Mf::Vector2(force, 0.0);
- Mf::Vector2 down = Mf::Vector2(0.0, -force);
- Mf::Vector2 up = Mf::Vector2(0.0, force);
-
- switch (event.type)
- {
- case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_a)
- {
- userForce += left;
- }
- else if (event.key.keysym.sym == SDLK_d)
- {
- userForce += right;
- }
- else if (event.key.keysym.sym == SDLK_s)
- {
- userForce += down;
- }
- else if (event.key.keysym.sym == SDLK_w)
- {
- userForce += up;
- }
- break;
-
- case SDL_KEYUP:
- if (event.key.keysym.sym == SDLK_a)
- {
- userForce -= left;
- }
- else if (event.key.keysym.sym == SDLK_d)
- {
- userForce -= right;
- }
- else if (event.key.keysym.sym == SDLK_s)
- {
- userForce -= down;
- }
- else if (event.key.keysym.sym == SDLK_w)
- {
- userForce -= up;
- }
- break;
- }
-
- //Mf::logInfo("current force [%f %f]", current.force[0], current.force[1]);
- //std::cerr << "current force: " << current.force << std::endl;
-}
+//void Character::updateContainers()
+//{
+ //aabb_.init(Mf::Vector3(current.position[0]-16.0, current.position[1]-16.0, z),
+ //Mf::Vector3(current.position[0]+16.0, current.position[1]+16.0, z));
+ //sphere_.point = Mf::Vector3(current.position[0], current.position[1], z);
+ //sphere_.radius = (aabb_.min - sphere_.point).length();
+//}
void Character::draw(Mf::Scalar alpha) const
{
State state = cml::lerp(previous, current, alpha);
- glColor3f(1.0f, 1.0f, 1.0f);
+ //glColor3f(1.0f, 1.0f, 1.0f);
tilemap_.bind();
Mf::Tilemap::Index frame = animation_.getFrame();
+ Mf::Tilemap::Orientation orientation = Mf::Tilemap::NORMAL;
+
+ if (current.velocity[0] < 0.0) orientation = Mf::Tilemap::REVERSE;
+
Mf::Scalar coords[8];
- tilemap_.getTileCoords(frame, coords);
+ tilemap_.getTileCoords(frame, coords, orientation);
Mf::Scalar s = 16.0;
glVertex3(state.position[0]-s, state.position[1]+s, z);
glEnd();
- glColor3f(0.0f, 0.0f, 0.0f);
+ //glColor3f(0.0f, 0.0f, 0.0f);
Mf::Texture::resetBind();
glBegin(GL_TRIANGLES);
glVertex3(500.0, 210.0, 64.0);
glEnd();
- glColor3f(1.0f, 1.0f, 1.0f);
+ //glColor3f(1.0f, 1.0f, 1.0f);
}
#include <Moof/Entity.hh>
#include <Moof/Event.hh>
#include <Moof/Math.hh>
-#include <Moof/Octree.hh>
#include <Moof/RK4.hh>
#include <Moof/Tilemap.hh>
State previous;
State current;
- Mf::OctreeNodeP treeNode;
-
private:
static const Mf::Scalar z = 96.0;
- Mf::Vector2 userForce;
-
Mf::Tilemap tilemap_;
Mf::Animation animation_;
- void updateContainers();
+ //void updateContainers();
-public:
+protected:
- static CharacterP alloc(const std::string& name)
- {
- return CharacterP(new Character(name));
- }
+ Mf::Vector2 userForce;
+
+public:
Character(const std::string& name);
virtual ~Character() {}
- void update(Mf::Scalar t, Mf::Scalar dt);
- void handleEvent(const Mf::Event& event);
- void draw(Mf::Scalar alpha) const;
+ virtual void update(Mf::Scalar t, Mf::Scalar dt);
+ virtual void draw(Mf::Scalar alpha) const;
Mf::Tilemap& getTilemap();
Mf::Animation& getAnimation();
#include <Moof/Log.hh>
#include <Moof/Math.hh>
#include <Moof/OpenGL.hh>
+#include <Moof/Video.hh>
#include "GameLayer.hh"
GameLayer::GameLayer() :
- music("NightFusionIntro"),
+ music("BeatTheCube"),
punchSound("Thump")
{
music.setLooping(true);
music.enqueue("NightFusionLoop");
music.stream();
- heroine = Character::alloc("RobotTrooper");
- heroine->getAnimation().startSequence("Run");
+ heroine = Heroine::alloc();
+ heroine->getAnimation().startSequence("FlyDiagonallyUp");
Mf::Scalar a[6] = {0.0, 1.5, -0.5, 3.0, -2.0, 1.0};
interp.init(a, 2.0, Mf::Interpolator::OSCILLATE);
- Mf::Scalar b[2] = {1.0, 0.0};
- fadeIn.init(b, 1.0);
+ scene = Scene::alloc("Classic");
- octree = Mf::loadScene("Classic");
- heroine->treeNode = octree->insert(heroine);
+ setProjection();
- camera.setProjection(cml::rad(60.0), 1.33333, 32.0, 2500.0);
- camera.uploadProjectionToGL();
+ hud = Hud::alloc();
}
void GameLayer::pushed(Mf::Engine& engine)
{
- hud = Hud::alloc();
- engine.pushLayer(hud);
+ engine.push(hud);
}
void GameLayer::update(Mf::Scalar t, Mf::Scalar dt)
{
- //dt *= 0.7;
-
- fadeIn.update(dt);
camera.update(t, dt);
heroine->update(t, dt);
- // reinsert heroine
- heroine->treeNode = octree->reinsert(heroine, heroine->treeNode);
- octree->print(heroine->treeNode);
-
//camera.lookAt(heroine->getSphere().point);
camera.setPosition(Mf::Vector3(-heroine->current.position[0],
-heroine->current.position[1], -256));
- Mf::Vector3 heroinePosition;
- Mf::promoteVector(heroinePosition, heroine->current.position);
- Mf::Sound::setListenerPosition(heroinePosition);
-
- interp.update(dt);
+ //Mf::Vector3 heroinePosition = Mf::promote(heroine->current.position);
+ //Mf::Sound::setListenerPosition(heroinePosition);
+
+ interp.update(t, dt);
hud->setBar1Progress(interp.getState(dt));
hud->setBar2Progress(1.0 - interp.getState(dt));
}
void GameLayer::draw(Mf::Scalar alpha) const
{
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrix(camera.getModelviewMatrix().data());
+ camera.uploadToGL();
// DRAW THE SCENE
Mf::Texture::resetBind();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- octree->drawIfVisible(alpha, camera.getFrustum());
-
- //heroine->draw(alpha);
- heroine->getAabb().draw();
-
- // DRAW FADE
- glEnable(GL_BLEND);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glColor4f(0.0f, 0.0f, 0.0f, fadeIn.getState(alpha));
- Mf::Texture::resetBind();
-
- //glRectf(-1.0f, -1.0f, 1.0f, 1.0f);
- glBegin(GL_QUADS);
- glVertex3f(-1.0, -1.0, -0.1);
- glVertex3f(1.0, -1.0, -0.1);
- glVertex3f(1.0, 1.0, -0.1);
- glVertex3f(-1.0, 1.0, -0.1);
- glEnd();
-
- glDisable(GL_BLEND);
+ scene->drawIfVisible(alpha, camera.getFrustum());
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ heroine->draw(alpha);
}
bool GameLayer::handleEvent(const Mf::Event& event)
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_SPACE)
{
- heroine->getAnimation().startSequence("Punch");
+ heroine->getAnimation().startSequence("Flattened");
Mf::logInfo("thump!");
punchSound.play();
return true;
}
else if (event.key.keysym.sym == SDLK_y)
{
- Mf::Engine::getInstance().popLayer();
+ Mf::Engine::getInstance().pop();
return true;
}
return true;
case SDL_VIDEORESIZE:
- glViewport(0, 0, event.resize.w, event.resize.h);
- camera.setProjection(cml::rad(60.0),
- double(event.resize.w) / double(event.resize.h), 32.0, 2500.0);
- camera.uploadProjectionToGL();
+ setProjection(Mf::Scalar(event.resize.w), Mf::Scalar(event.resize.h));
break;
}
}
+void GameLayer::setProjection()
+{
+ Mf::Video& video = Mf::Engine::getInstance().getVideo();
+ setProjection(video.getWidth(), video.getHeight());
+}
+
+void GameLayer::setProjection(Mf::Scalar width, Mf::Scalar height)
+{
+ camera.setProjection(cml::rad(60.0), width / height, 32.0, 2500.0);
+}
+
+
/** vim: set ts=4 sw=4 tw=80: *************************************************/
#include <Moof/Interpolator.hh>
#include <Moof/Layer.hh>
#include <Moof/Math.hh>
-#include <Moof/Scene.hh>
#include <Moof/Sound.hh>
#include "Character.hh"
+#include "Heroine.hh"
#include "Hud.hh"
+#include "Scene.hh"
class GameLayer;
private:
+ void setProjection();
+ void setProjection(Mf::Scalar width, Mf::Scalar height);
+
Mf::Sound music;
- CharacterP heroine;
+ HeroineP heroine;
+ SceneP scene;
Mf::Sound punchSound;
Mf::PolynomialInterpolator<5> interp;
- Mf::Lerp fadeIn;
Mf::Camera camera;
- Mf::OctreeP octree;
HudP hud;
};
--- /dev/null
+
+/*******************************************************************************
+
+ 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 "Heroine.hh"
+#include "Log.hh"
+
+
+Heroine::Heroine() :
+ Character("Heroine") {}
+
+
+void Heroine::handleEvent(const Mf::Event& event)
+{
+ // really just for heroine...
+
+ Mf::Scalar force = 4000.0;
+
+ Mf::Vector2 left = Mf::Vector2(-force, 0.0);
+ Mf::Vector2 right = Mf::Vector2(force, 0.0);
+ Mf::Vector2 down = Mf::Vector2(0.0, -force);
+ Mf::Vector2 up = Mf::Vector2(0.0, force);
+
+ switch (event.type)
+ {
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_a)
+ {
+ userForce += left;
+ }
+ else if (event.key.keysym.sym == SDLK_d)
+ {
+ userForce += right;
+ }
+ else if (event.key.keysym.sym == SDLK_s)
+ {
+ userForce += down;
+ }
+ else if (event.key.keysym.sym == SDLK_w)
+ {
+ userForce += up;
+ }
+ break;
+
+ case SDL_KEYUP:
+ if (event.key.keysym.sym == SDLK_a)
+ {
+ userForce -= left;
+ }
+ else if (event.key.keysym.sym == SDLK_d)
+ {
+ userForce -= right;
+ }
+ else if (event.key.keysym.sym == SDLK_s)
+ {
+ userForce -= down;
+ }
+ else if (event.key.keysym.sym == SDLK_w)
+ {
+ userForce -= up;
+ }
+ break;
+ }
+
+ //Mf::logInfo("current force [%f %f]", current.force[0], current.force[1]);
+ //std::cerr << "current force: " << current.force << std::endl;
+}
+
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ 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.
+
+*******************************************************************************/
+
+#ifndef _HEROINE_HH_
+#define _HEROINE_HH_
+
+#include <boost/shared_ptr.hpp>
+
+#include <Moof/Animation.hh>
+#include <Moof/Entity.hh>
+#include <Moof/Event.hh>
+#include <Moof/Math.hh>
+#include <Moof/Octree.hh>
+#include <Moof/RK4.hh>
+#include <Moof/Tilemap.hh>
+
+#include "Character.hh"
+
+
+struct Heroine;
+typedef boost::shared_ptr<Heroine> HeroineP;
+
+
+/**
+ * Parent class of animate objects with "personalities." This basically
+ * includes the heroine herself and the bad guys.
+ */
+
+struct Heroine : public Character
+{
+ Heroine();
+
+ static HeroineP alloc()
+ {
+ return HeroineP(new Heroine);
+ }
+
+ void handleEvent(const Mf::Event& event);
+};
+
+
+#endif // _HEROINE_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
void Hud::resize(int width, int height)
{
- cml::matrix_orthographic_RH( projection_,
- 0.0f,
- Mf::Scalar(width), 0.0f, Mf::Scalar(height),
- 1.0f, -1.0f, cml::z_clip_neg_one);
+ cml::matrix_orthographic_RH(projection_,
+ SCALAR(0.0),
+ Mf::Scalar(width), SCALAR(0.0), Mf::Scalar(height),
+ SCALAR(1.0), SCALAR(-1.0), cml::z_clip_neg_one);
// position the two progress bars at the top-left of the screen
bar1_.resize(Mf::Rectangle(20, height - 51,
*******************************************************************************/
-#include <cstdlib> // getenv
+#include <cstdlib> // atexit, getenv
#include <cstring>
#include <iostream>
#include <string>
#include <Moof/Log.hh>
#include <Moof/OpenGL.hh>
#include <Moof/Resource.hh>
+#include <Moof/Transition.hh>
#include <Moof/Video.hh>
#include "GameLayer.hh"
#include "MainLayer.hh"
+#include "TitleLayer.hh"
#if HAVE_CONFIG_H
#include "config.h"
void MainLayer::pushed(Mf::Engine& e)
{
engine = &e;
- engine->pushLayer(GameLayer::alloc());
+
+ //Mf::Scalar coeff[] = {0.0, 1.0};
+ //Mf::Lerp interp(coeff, 0.25);
+
+ //Mf::LayerP gameLayer = GameLayer::alloc();
+ //Mf::Transition<Mf::Lerp>::Ptr transition =
+ //Mf::Transition<Mf::Lerp>::alloc(gameLayer, Mf::LayerP(), interp);
+ //engine->push(transition);
+ //engine->push(GameLayer::alloc());
+ engine->push(TitleLayer::alloc());
}
void MainLayer::draw(Mf::Scalar alpha) const
{
- glClear(GL_DEPTH_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
}
bool MainLayer::handleEvent(const Mf::Event& event)
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
{
- engine->clearLayers();
+ quit();
}
else if (event.key.keysym.sym == SDLK_f)
{
}
else if (event.key.keysym.sym == SDLK_y)
{
- engine->pushLayer(GameLayer::alloc());
+ engine->push(GameLayer::alloc());
}
break;
+ case SDL_VIDEORESIZE:
+ glViewport(0, 0, event.resize.w, event.resize.h);
+ break;
+
case SDL_QUIT:
- engine->clearLayers();
+ quit();
break;
}
return false;
}
+void MainLayer::quit()
+{
+#if NDEBUG
+ // we don't really need to unwind the stack and shut everything down because
+ // the operating system will take care of cleaning up
+ exit(0);
+#else
+ engine->clear();
+#endif
+}
+
void MainLayer::setupGL()
{
glEnable(GL_TEXTURE_2D);
-
- //glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_POLYGON_SMOOTH);
glShadeModel(GL_SMOOTH);
- //glEnable(GL_POLYGON_SMOOTH);
- //int texSize;
- //glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
- //std::cout << "texture size: " << texSize << std::endl;
-
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0);
- glClearColor(1.0, 0.0, 0.0, 1.0);
+ glClearColor(0.0, 0.0, 0.0, 1.0);
- //glMatrixMode(GL_PROJECTION);
- //glLoadIdentity();
- //gluPerspective(60.0, 1.33333, 1.0, 2500.0);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(60.0, 1.33333, 1.0, 2500.0);
- //glMatrixMode(GL_MODELVIEW);
-
- //glLineWidth(10.0f);
+ glMatrixMode(GL_MODELVIEW);
}
void MainLayer::contextRecreated(const Mf::Notification* note)
<< "See documentation for more options." << std::endl;
}
+void goodbye()
+{
+ std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
+}
+
int main(int argc, char* argv[])
{
if (argc > 1 &&
<< "Send patches and bug reports to <"
PACKAGE_BUGREPORT << ">." << std::endl << std::endl;
+ atexit(goodbye);
+
#if YOINK_LOGLEVEL >= 4
Mf::setLogLevel(Mf::LOG_DEBUG);
try
{
Mf::Engine app(argc, argv, PACKAGE_STRING, iconFile, configFiles);
- app.pushLayer(MainLayer::alloc());
+ app.push(MainLayer::alloc());
app.run();
}
throw e;
}
- std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
return 0;
}
void draw(Mf::Scalar alpha) const;
bool handleEvent(const Mf::Event& event);
+ void quit();
+
private:
/**
Moof/Log.hh \
Moof/Math.hh \
Moof/Mippleton.hh \
- Moof/Octree.cc \
Moof/Octree.hh \
Moof/OpenGL.hh \
Moof/Plane.cc \
Moof/Resource.cc \
Moof/Resource.hh \
Moof/RK4.hh \
- Moof/Scene.cc \
- Moof/Scene.hh \
Moof/Script.hh \
Moof/Serializable.cc \
Moof/Serializable.hh \
Moof/Tilemap.hh \
Moof/Timer.cc \
Moof/Timer.hh \
+ Moof/Transition.hh \
Moof/Video.cc \
Moof/Video.hh \
Moof/fastevents.c \
Character.hh \
GameLayer.cc \
GameLayer.hh \
+ Heroine.cc \
+ Heroine.hh \
Hud.cc \
Hud.hh \
MainLayer.cc \
MainLayer.hh \
+ Scene.cc \
+ Scene.hh \
TilemapFont.cc \
TilemapFont.hh \
+ TitleLayer.cc \
+ TitleLayer.hh \
Typesetter.cc \
Typesetter.hh \
$(ENDLIST)
}
-void Camera::uploadProjectionToGL() const
+void Camera::uploadToGL() const
{
glMatrixMode(GL_PROJECTION);
- glLoadMatrix(projection_.data());
+ glMultMatrix(projection_.data());
glMatrixMode(GL_MODELVIEW);
+ glMultMatrix(modelview_.data());
}
void Camera::update(Scalar t, Scalar dt)
Camera() :
position_(0.0, 0.0, 0.0)
{
- cml::quaternion_rotation_world_y(rotation_, 0.0f);
+ cml::quaternion_rotation_world_y(rotation_, SCALAR(0.0));
calculateSecondary();
}
void setProjection(const Matrix4& projection);
void setProjection(Scalar fovy, Scalar aspect, Scalar near, Scalar far);
- void uploadProjectionToGL() const;
+ void uploadToGL() const;
void lookAt(const Vector3& point);
if (settings.get("rngseed", randomSeed)) setSeed(randomSeed);
else setSeed();
- settings.get("timestep", timestep);
+ Scalar timeStep = 80.0;
+ settings.get("timestep", timeStep);
+ timestep = 1.0 / timeStep;
- long maxFps = 40;
+ Scalar maxFps = 40.0;
settings.get("maxfps", maxFps);
- drawRate = 1.0 / Scalar(maxFps);
+ drawRate = 1.0 / maxFps;
settings.get("printfps", printFps);
}
- void pushLayer(LayerP layer)
+ void push(LayerP layer)
{
ASSERT(layer && "cannot push null layer");
stack.push_front(layer);
+ logInfo(" push: %d", stack.size());
layer->pushed(interface);
}
- void popLayer()
+ LayerP pop()
{
bool fixIt = false;
if (stack.begin() == stackIt) fixIt = true;
LayerP popped = stack.front();
stack.pop_front();
+ logInfo(" pop: %d", stack.size());
popped->popped(interface);
if (fixIt) stackIt = --stack.begin();
+
+ return popped;
}
- void popLayer(Layer* layer)
+ LayerP pop(Layer* layer)
{
bool fixIt = false;
+ std::list<LayerP> popped;
+
std::list<LayerP>::iterator it;
for (it = stack.begin(); it != stack.end(); ++it)
{
+ popped.push_back(*it);
+
if (it == stackIt) fixIt = true;
if ((*it).get() == layer)
{
++it;
- do
+ stack.erase(stack.begin(), it);
+
+ for (it = popped.begin(); it != popped.end(); ++it)
{
- LayerP popped = stack.front();
- stack.pop_front();
- popped->popped(interface);
+ (*it)->popped(interface);
}
- while (stack.begin() != it);
if (fixIt) stackIt = --stack.begin();
- return;
+
+ return popped.back();
}
}
+
+ return LayerP();
}
- void clearLayers()
+ void clear()
{
stack.clear();
stackIt = stack.begin();
+ logInfo("clear: %d", stack.size());
}
{
ASSERT(instance && "dereferencing null pointer");
return *instance;
+ //static Engine engine;
+ //return engine;
}
}
-void Engine::pushLayer(LayerP layer)
+void Engine::push(LayerP layer)
{
// pass through
- impl_->pushLayer(layer);
+ impl_->push(layer);
}
-void Engine::popLayer()
+LayerP Engine::pop()
{
// pass through
- impl_->popLayer();
+ return impl_->pop();
}
-void Engine::popLayer(Layer* layer)
+LayerP Engine::pop(Layer* layer)
{
// pass through
- impl_->popLayer(layer);
+ return impl_->pop(layer);
}
-void Engine::clearLayers()
+void Engine::clear()
{
// pass through
- impl_->clearLayers();
+ impl_->clear();
}
Video& getVideo() const;
long getFrameRate() const;
- void pushLayer(LayerP layer);
- void popLayer();
- void popLayer(Layer* layer);
- void clearLayers();
+ void push(LayerP layer);
+ LayerP pop();
+ // pops a specific layer and all layers above it
+ LayerP pop(Layer* layer);
+ void clear();
struct Exception : public Mf::Exception
{
public:
virtual ~Entity() {}
- const Aabb& getAabb() const
- {
- return aabb_;
- }
-
- const Sphere& getSphere() const
- {
- return sphere_;
- }
-
- void drawIfVisible(Scalar alpha, const Frustum& frustum) const
+ virtual void drawIfVisible(Scalar alpha, const Frustum& frustum) const
{
if (isVisible(frustum)) draw(alpha);
}
-
-protected:
- Aabb aabb_;
- Sphere sphere_;
};
#ifndef _MOOF_INTERPOLATOR_HH_
#define _MOOF_INTERPOLATOR_HH_
+#include <Moof/Log.hh>
#include <Moof/Math.hh>
{
case STOP:
value = 1.0;
- stopped_ = true;
+ done_ = true;
break;
case REPEAT:
value -= 1.0;
{
case STOP:
value = 0.0;
- stopped_ = true;
+ done_ = true;
break;
case REPEAT:
value += 1.0;
void setMode(Mode mode)
{
mode_ = mode;
- stopped_ = false;
+ done_ = false;
}
- void update(Scalar dt)
+ void update(Scalar t, Scalar dt)
{
- if (!stopped_)
+ if (!done_)
{
alpha_ += dt * scale_;
clamp(alpha_);
}
}
+ bool isDone() const
+ {
+ return done_;
+ }
+
virtual void calculate(Scalar alpha) = 0;
private:
+
Scalar alpha_;
Mode mode_;
Scalar scale_;
- bool stopped_;
+ bool done_;
};
template <class T = Scalar>
typedef cml::constants<Scalar> Constants;
-inline Vector3& demoteVector(Vector3& left, const Vector4& right)
+inline Vector3 demote(const Vector4& vec)
{
- left[0] = right[0];
- left[1] = right[1];
- left[2] = right[2];
- return left;
+ return Vector3(vec[0], vec[1], vec[2]);
}
-inline Vector2& demoteVector(Vector2& left, const Vector3& right)
+inline Vector2 demote(const Vector3& vec)
{
- left[0] = right[0];
- left[1] = right[1];
- return left;
+ return Vector2(vec[0], vec[1]);
}
-inline Vector4& promoteVector(Vector4& left, const Vector3& right, Scalar extra = 1.0)
+inline Vector4 promote(const Vector3& vec, Scalar extra = 1.0)
{
- left[0] = right[0];
- left[1] = right[1];
- left[2] = right[2];
- left[3] = extra;
- return left;
+ return Vector4(vec[0], vec[1], vec[2], extra);
}
-inline Vector3& promoteVector(Vector3& left, const Vector2& right, Scalar extra = 1.0)
+inline Vector3 promote(const Vector2& vec, Scalar extra = 1.0)
{
- left[0] = right[0];
- left[1] = right[1];
- left[3] = extra;
- return left;
+ return Vector3(vec[0], vec[1], extra);
}
+++ /dev/null
-
-/*******************************************************************************
-
- 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 "Frustum.hh"
-#include "Log.hh"
-#include "Octree.hh"
-
-
-namespace Mf {
-
-
-void Octree::sort()
-{
- stlplus::ntree<OctreeNode>::prefix_iterator it;
-
- for (it = tree_.prefix_begin(); it != tree_.prefix_end(); ++it)
- {
- it->sort();
- }
-}
-
-
-OctreeNodeP Octree::insert(EntityP entity, OctreeNodeP node)
-{
- ASSERT(node.valid() && "invalid node passed");
- ASSERT(entity && "null entity passed");
-
- int octantNum = -1;
-
- Plane::Halfspace halfspace;
-
- // TODO this method needs a lot of work
- Plane xy = node->getAabb().getPlaneXY();
-
-
- // make sure the entity is fully inside the volume
- if (!(entity->getAabb().max[0] < node->getAabb().max[0] &&
- entity->getAabb().min[0] > node->getAabb().min[0] &&
- entity->getAabb().max[1] < node->getAabb().max[1] &&
- entity->getAabb().min[1] > node->getAabb().min[1] &&
- entity->getAabb().max[2] < node->getAabb().max[2] &&
- entity->getAabb().min[2] > node->getAabb().min[2]))
- {
- // TODO this check is only needed for the root node, if we're inside the
- // volume of the root node, we'll be fully inside the child as
- // determined by trying to insert the parent node
- goto done;
- }
-
- halfspace = xy.intersects(entity->getSphere());
- if (halfspace == Plane::INTERSECT)
- {
- halfspace = xy.intersects(entity->getAabb());
- }
-
- if (halfspace == Plane::POSITIVE)
- {
- Plane xz = node->getAabb().getPlaneXZ();
- halfspace = xz.intersects(entity->getSphere());
- if (halfspace == Plane::INTERSECT)
- {
- halfspace = xz.intersects(entity->getAabb());
- }
-
- if (halfspace == Plane::POSITIVE)
- {
- Plane yz = node->getAabb().getPlaneYZ();
- halfspace = yz.intersects(entity->getSphere());
- if (halfspace == Plane::INTERSECT)
- {
- halfspace = yz.intersects(entity->getAabb());
- }
-
- if (halfspace == Plane::POSITIVE)
- {
- octantNum = 2;
- }
- else if (halfspace == Plane::NEGATIVE)
- {
- octantNum = 3;
- }
- }
- else if (halfspace == Plane::NEGATIVE)
- {
- Plane yz = node->getAabb().getPlaneYZ();
- halfspace = yz.intersects(entity->getSphere());
- if (halfspace == Plane::INTERSECT)
- {
- halfspace = yz.intersects(entity->getAabb());
- }
-
- if (halfspace == Plane::POSITIVE)
- {
- octantNum = 1;
- }
- else if (halfspace == Plane::NEGATIVE)
- {
- octantNum = 0;
- }
- }
- }
- else if (halfspace == Plane::NEGATIVE)
- {
- Plane xz = node->getAabb().getPlaneXZ();
- halfspace = xz.intersects(entity->getSphere());
- if (halfspace == Plane::INTERSECT)
- {
- halfspace = xz.intersects(entity->getAabb());
- }
-
- if (halfspace == Plane::POSITIVE)
- {
- Plane yz = node->getAabb().getPlaneYZ();
- halfspace = yz.intersects(entity->getSphere());
- if (halfspace == Plane::INTERSECT)
- {
- halfspace = yz.intersects(entity->getAabb());
- }
-
- if (halfspace == Plane::POSITIVE)
- {
- octantNum = 6;
- }
- else if (halfspace == Plane::NEGATIVE)
- {
- octantNum = 7;
- }
- }
- else if (halfspace == Plane::NEGATIVE)
- {
- Plane yz = node->getAabb().getPlaneYZ();
- halfspace = yz.intersects(entity->getSphere());
- if (halfspace == Plane::INTERSECT)
- {
- halfspace = yz.intersects(entity->getAabb());
- }
-
- if (halfspace == Plane::POSITIVE)
- {
- octantNum = 5;
- }
- else if (halfspace == Plane::NEGATIVE)
- {
- octantNum = 4;
- }
- }
- }
-
-done:
-
- if (octantNum == -1)
- {
- node->objects.push_front(entity);
- return node;
- }
- else
- {
- if ((int)tree_.children(node) <= octantNum)
- {
- addChild(node, octantNum);
- }
-
- OctreeNodeP child = tree_.child(node, octantNum);
- ASSERT(child.valid() && "expected valid child node");
-
- return insert(entity, child);
- }
-}
-
-OctreeNodeP Octree::reinsert(EntityP entity, OctreeNodeP node)
-{
- ASSERT(entity && "null entity passed");
- ASSERT(node.valid() && "invalid node passed");
-
- std::list<EntityP>::iterator it;
- it = std::find(node->objects.begin(), node->objects.end(), entity);
-
- if (it != node->objects.end())
- {
- node->objects.erase(it);
- }
-
- return insert(entity);
-}
-
-
-void Octree::addChild(OctreeNodeP node, int index)
-{
- ASSERT(node.valid() && "invalid node passed");
-
- Aabb octant;
-
- for (int i = tree_.children(node); i <= index; ++i)
- {
- node->getAabb().getOctant(octant, i);
- tree_.append(node, octant);
- }
-}
-
-
-void Octree::draw(Scalar alpha, OctreeNodeP node)
-{
- ASSERT(node.valid() && "invalid node passed");
-
- node->draw(alpha);
-
- for (unsigned i = 0; i < tree_.children(node); ++i)
- {
- OctreeNodeP child = tree_.child(node, i);
- ASSERT(child.valid() && "expected valid child node");
-
- draw(alpha, child);
- }
-}
-
-void Octree::drawIfVisible(Scalar alpha, const Frustum& frustum, OctreeNodeP node)
-{
- ASSERT(node.valid() && "invalid node passed");
-
- // try to cull by sphere
- Frustum::Collision collision =
- frustum.contains(node->getSphere());
- if (collision == Frustum::OUTSIDE) return;
-
- // try to cull by aabb
- collision = frustum.contains(node->getAabb());
- if (collision == Frustum::OUTSIDE) return;
-
-
- if (collision == Frustum::INSIDE)
- {
- node->draw(alpha);
- }
- else // collision == Frustum::INTERSECT
- {
- node->drawIfVisible(alpha, frustum);
- }
-
- if (tree_.children(node) > 0)
- {
- if (collision == Frustum::INSIDE)
- {
- for (unsigned i = 0; i < tree_.children(node); ++i)
- {
- OctreeNodeP child = tree_.child(node, i);
- ASSERT(child.valid() && "expected valid child node");
-
- draw(alpha, child);
- }
- }
- else // collision == Frustum::INTERSECT
- {
- for (unsigned i = 0; i < tree_.children(node); ++i)
- {
- OctreeNodeP child = tree_.child(node, i);
- ASSERT(child.valid() && "expected valid child node");
-
- drawIfVisible(alpha, frustum, child);
- }
- }
- }
-}
-
-
-} // namespace Mf
-
-/** vim: set ts=4 sw=4 tw=80: *************************************************/
-
#include <Moof/Aabb.hh>
#include <Moof/Drawable.hh>
#include <Moof/Entity.hh>
+#include <Moof/Frustum.hh>
#include <Moof/Log.hh>
#include <Moof/Math.hh>
#include <Moof/Sphere.hh>
namespace Mf {
-class Frustum;
+//class Octree;
+//typedef boost::shared_ptr<Octree> OctreeP;
+//class Octree::Node;
+//typedef stlplus::ntree<Octree::Node>::iterator OctreeNodeP;
-struct OctreeNode;
-typedef stlplus::ntree<OctreeNode>::iterator OctreeNodeP;
-class Octree;
-typedef boost::shared_ptr<Octree> OctreeP;
+struct OctreeInsertable
+{
+ virtual ~OctreeInsertable() {}
+
+ virtual bool isInsideAabb(const Aabb& aabb) const = 0;
+ virtual int getOctant(const Aabb& aabb) const = 0;
+};
-struct OctreeNode : public Entity
+template <class T>
+class Octree : public Entity
{
- std::list<EntityP> objects;
+ typedef boost::shared_ptr<T> InsertableP;
- OctreeNode()
+ struct Node : public Entity
{
- aabb_.min = Vector3(-1.0, -1.0, -1.0);
- aabb_.max = Vector3(1.0, 1.0, 1.0);
- sphere_.init(Vector3(0.0, 0.0, 0.0), 1.41421);
- }
+ std::list<InsertableP> objects;
- OctreeNode(const Aabb& aabb)
- {
- aabb_ = aabb;
- sphere_.point = aabb.getCenter();
- sphere_.radius = (aabb.min - sphere_.point).length();
- }
+ Aabb aabb;
+ Sphere sphere;
- void draw(Scalar alpha) const
- {
- std::list<EntityP>::const_iterator it;
+ Node(const Aabb& box) :
+ aabb(box)
+ {
+ sphere.point = aabb.getCenter();
+ sphere.radius = (aabb.min - sphere.point).length();
+ }
- for (it = objects.begin(); it != objects.end(); ++it)
+ void draw(Scalar alpha) const
{
- (*it)->draw(alpha);
+ typename std::list<InsertableP>::const_iterator it;
+
+ for (it = objects.begin(); it != objects.end(); ++it)
+ {
+ (*it)->draw(alpha);
+ }
+
+ if (!objects.empty())
+ aabb.draw(); // temporary
}
- if (!objects.empty())
- aabb_.draw(); // temporary
- }
+ void drawIfVisible(Scalar alpha, const Frustum& frustum) const
+ {
+ typename std::list<InsertableP>::const_iterator it;
+
+ for (it = objects.begin(); it != objects.end(); ++it)
+ {
+ (*it)->drawIfVisible(alpha, frustum);
+ }
+
+ if (!objects.empty())
+ {
+ //aabb.draw();
+ //sphere.draw();
+ }
+ }
- void drawIfVisible(Scalar alpha, const Frustum& frustum) const
- {
- std::list<EntityP>::const_iterator it;
- for (it = objects.begin(); it != objects.end(); ++it)
+ bool isVisible(const Frustum& frustum) const
{
- (*it)->drawIfVisible(alpha, frustum);
+ if (sphere.isVisible(frustum))
+ {
+ return aabb.isVisible(frustum);
+ }
+
+ return false;
}
+ };
- if (!objects.empty())
+
+public:
+
+ typedef boost::shared_ptr<Octree> Ptr;
+ typedef typename stlplus::ntree<Node>::iterator NodeP;
+
+private:
+
+
+ NodeP insert(InsertableP entity, NodeP node)
+ {
+ ASSERT(node.valid() && "invalid node passed");
+ ASSERT(entity && "null entity passed");
+
+ if (entity->isInsideAabb(node->aabb))
{
- aabb_.draw();
- //sphere_.draw();
+ return insert_recurse(entity, node);
+ }
+ else
+ {
+ node->objects.push_back(entity);
+ return node;
}
}
-
- bool isVisible(const Frustum& frustum) const
+ NodeP insert_recurse(InsertableP entity, NodeP node)
{
- if (sphere_.isVisible(frustum))
+ ASSERT(node.valid() && "invalid node passed");
+ ASSERT(entity && "null entity passed");
+
+ int octantNum = entity->getOctant(node->aabb);
+ if (octantNum == -1)
{
- return aabb_.isVisible(frustum);
+ node->objects.push_back(entity);
+ return node;
}
+ else
+ {
+ if ((int)tree_.children(node) <= octantNum)
+ {
+ addChild(node, octantNum);
+ }
- return false;
- }
+ NodeP child = tree_.child(node, octantNum);
+ ASSERT(child.valid() && "expected valid child node");
+ return insert(entity, child);
+ }
+ }
- static bool compareZOrder(EntityP a, EntityP b)
+ void addChild(NodeP node, int index)
{
- return a->getSphere().point[2] < b->getSphere().point[2];
+ ASSERT(node.valid() && "invalid node passed");
+
+ Aabb octant;
+
+ for (int i = tree_.children(node); i <= index; ++i)
+ {
+ node->aabb.getOctant(octant, i);
+ tree_.append(node, octant);
+ }
}
- void sort()
+
+ void draw(Scalar alpha, NodeP node) const
{
- //std::sort(objects.begin(), objects.end(), compareZOrder);
- objects.sort(compareZOrder);
+ ASSERT(node.valid() && "invalid node passed");
+
+ node->draw(alpha);
+
+ for (unsigned i = 0; i < tree_.children(node); ++i)
+ {
+ NodeP child = tree_.child(node, i);
+ ASSERT(child.valid() && "expected valid child node");
+
+ draw(alpha, child);
+ }
}
-};
+ void drawIfVisible(Scalar alpha, const Frustum& frustum, NodeP node) const
+ {
+ ASSERT(node.valid() && "invalid node passed");
-class Octree
-{
- OctreeNodeP insert(EntityP entity, OctreeNodeP node);
-
- void addChild(OctreeNodeP node, int index);
+ // try to cull by sphere
+ Frustum::Collision collision = frustum.contains(node->sphere);
+ if (collision == Frustum::OUTSIDE) return;
+
+ // try to cull by aabb
+ collision = frustum.contains(node->aabb);
+ if (collision == Frustum::OUTSIDE) return;
+
+
+ if (collision == Frustum::INSIDE)
+ {
+ node->draw(alpha);
+ }
+ else // collision == Frustum::INTERSECT
+ {
+ node->drawIfVisible(alpha, frustum);
+ }
- void draw(Scalar alpha, OctreeNodeP node);
- void drawIfVisible(Scalar alpha, const Frustum& frustum, OctreeNodeP node);
+ if (tree_.children(node) > 0)
+ {
+ if (collision == Frustum::INSIDE)
+ {
+ for (unsigned i = 0; i < tree_.children(node); ++i)
+ {
+ NodeP child = tree_.child(node, i);
+ ASSERT(child.valid() && "expected valid child node");
+
+ draw(alpha, child);
+ }
+ }
+ else // collision == Frustum::INTERSECT
+ {
+ for (unsigned i = 0; i < tree_.children(node); ++i)
+ {
+ NodeP child = tree_.child(node, i);
+ ASSERT(child.valid() && "expected valid child node");
+
+ drawIfVisible(alpha, frustum, child);
+ }
+ }
+ }
+ }
+
+ mutable stlplus::ntree<Node> tree_;
- stlplus::ntree<OctreeNode> tree_;
public:
- void print(OctreeNodeP node)
+ void print(NodeP node)
{
//logDebug("-----");
//logDebug("depth to node: %d", tree_.depth(node));
//logDebug("size of node: %d", tree_.size(node));
}
- static OctreeP alloc(const OctreeNode& rootNode)
+ static Ptr alloc(const Node& rootNode)
{
- return OctreeP(new Octree(rootNode));
+ return Ptr(new Octree(rootNode));
}
- explicit Octree(const OctreeNode& rootNode)
+ explicit Octree(const Node& rootNode)
{
tree_.insert(rootNode);
}
- OctreeNodeP insert(EntityP entity)
+ NodeP insert(InsertableP entity)
{
return insert(entity, tree_.root());
}
- OctreeNodeP reinsert(EntityP entity, OctreeNodeP node);
+ NodeP reinsert(InsertableP entity, NodeP node)
+ {
+ ASSERT(entity && "null entity passed");
+ ASSERT(node.valid() && "invalid node passed");
+
+ typename std::list<InsertableP>::iterator it;
+ it = std::find(node->objects.begin(), node->objects.end(), entity);
- void draw(Scalar alpha)
+ if (it != node->objects.end())
+ {
+ node->objects.erase(it);
+ }
+
+ return insert(entity);
+ }
+
+ void draw(Scalar alpha) const
{
draw(alpha, tree_.root());
}
- void drawIfVisible(Scalar alpha, const Frustum& frustum)
+ void drawIfVisible(Scalar alpha, const Frustum& frustum) const
{
drawIfVisible(alpha, frustum, tree_.root());
}
-
- void sort();
};
#include <SDL/SDL_opengl.h>
-
-/* Define to 1 if you want to use double precision floating-point numbers. */
-//#define USE_DOUBLE_PRECISION 1
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
#if USE_DOUBLE_PRECISION
typedef GLdouble GLscalar;
#define GL_SCALAR GL_DOUBLE
-
-inline void glGetScalarv(GLenum a, GLscalar* b) { glGetDoublev(a, b); }
-
-inline void glLoadMatrix(const GLscalar* a) { glLoadMatrixd(a); }
-inline void glMultMatrix(const GLscalar* a) { glMultMatrixd(a); }
-
-inline void glScale(GLscalar a, GLscalar b, GLscalar c) { glScaled(a, b, c); }
-inline void glRotate(GLscalar a, GLscalar b, GLscalar c, GLscalar d) { glRotated(a, b, c, d); }
-inline void glTranslate(GLscalar a, GLscalar b, GLscalar c) { glTranslated(a, b, c); }
-
-inline void glColor3(GLscalar a, GLscalar b, GLscalar c) { glColor3d(a, b, c); }
-inline void glColor4(GLscalar a, GLscalar b, GLscalar c, GLscalar d) { glColor4d(a, b, c, d); }
-inline void glColor3v(const GLscalar *a) { glColor3dv(a); }
-inline void glColor4v(const GLscalar *a) { glColor4dv(a); }
-
-inline void glVertex2(GLscalar a, GLscalar b) { glVertex2d(a, b); }
-inline void glVertex3(GLscalar a, GLscalar b, GLscalar c) { glVertex3d(a, b, c); }
-inline void glVertex4(GLscalar a, GLscalar b, GLscalar c, GLscalar d) { glVertex4d(a, b, c, d); }
-inline void glVertex2v(const GLscalar* a) { glVertex2dv(a); }
-inline void glVertex3v(const GLscalar* a) { glVertex3dv(a); }
-inline void glVertex4v(const GLscalar* a) { glVertex4dv(a); }
-
-inline void glTexCoord2(GLscalar a, GLscalar b) { glTexCoord2d(a, b); }
-inline void glTexCoord3(GLscalar a, GLscalar b, GLscalar c) { glTexCoord3d(a, b, c); }
-inline void glTexCoord4(GLscalar a, GLscalar b, GLscalar c, GLscalar d) { glTexCoord4d(a, b, c, d); }
-inline void glTexCoord2v(const GLscalar* a) { glTexCoord2dv(a); }
-inline void glTexCoord3v(const GLscalar* a) { glTexCoord3dv(a); }
-inline void glTexCoord4v(const GLscalar* a) { glTexCoord4dv(a); }
+#define SCALAR(D) D
+
+inline void glGetScalarv(GLenum a, GLscalar* b)
+{ glGetDoublev(a, b); }
+
+inline void glLoadMatrix(const GLscalar* a)
+{ glLoadMatrixd(a); }
+inline void glMultMatrix(const GLscalar* a)
+{ glMultMatrixd(a); }
+
+inline void glScale(GLscalar a, GLscalar b, GLscalar c)
+{ glScaled(a, b, c); }
+inline void glRotate(GLscalar a, GLscalar b, GLscalar c, GLscalar d)
+{ glRotated(a, b, c, d); }
+inline void glTranslate(GLscalar a, GLscalar b, GLscalar c)
+{ glTranslated(a, b, c); }
+
+inline void glColor3(GLscalar a, GLscalar b, GLscalar c)
+{ glColor3d(a, b, c); }
+inline void glColor4(GLscalar a, GLscalar b, GLscalar c, GLscalar d)
+{ glColor4d(a, b, c, d); }
+inline void glColor3v(const GLscalar *a)
+{ glColor3dv(a); }
+inline void glColor4v(const GLscalar *a)
+{ glColor4dv(a); }
+
+inline void glVertex2(GLscalar a, GLscalar b)
+{ glVertex2d(a, b); }
+inline void glVertex3(GLscalar a, GLscalar b, GLscalar c)
+{ glVertex3d(a, b, c); }
+inline void glVertex4(GLscalar a, GLscalar b, GLscalar c, GLscalar d)
+{ glVertex4d(a, b, c, d); }
+inline void glVertex2v(const GLscalar* a)
+{ glVertex2dv(a); }
+inline void glVertex3v(const GLscalar* a)
+{ glVertex3dv(a); }
+inline void glVertex4v(const GLscalar* a)
+{ glVertex4dv(a); }
+
+inline void glTexCoord2(GLscalar a, GLscalar b)
+{ glTexCoord2d(a, b); }
+inline void glTexCoord3(GLscalar a, GLscalar b, GLscalar c)
+{ glTexCoord3d(a, b, c); }
+inline void glTexCoord4(GLscalar a, GLscalar b, GLscalar c, GLscalar d)
+{ glTexCoord4d(a, b, c, d); }
+inline void glTexCoord2v(const GLscalar* a)
+{ glTexCoord2dv(a); }
+inline void glTexCoord3v(const GLscalar* a)
+{ glTexCoord3dv(a); }
+inline void glTexCoord4v(const GLscalar* a)
+{ glTexCoord4dv(a); }
#else
typedef GLfloat GLscalar;
#define GL_SCALAR GL_FLOAT
-
-inline void glGetScalarv(GLenum a, GLscalar* b) { glGetFloatv(a, b); }
-
-inline void glLoadMatrix(const GLscalar* a) { glLoadMatrixf(a); }
-inline void glMultMatrix(const GLscalar* a) { glMultMatrixf(a); }
-
-inline void glScale(GLscalar a, GLscalar b, GLscalar c) { glScalef(a, b, c); }
-inline void glRotate(GLscalar a, GLscalar b, GLscalar c, GLscalar d) { glRotatef(a, b, c, d); }
-inline void glTranslate(GLscalar a, GLscalar b, GLscalar c) { glTranslatef(a, b, c); }
-
-inline void glColor3(GLscalar a, GLscalar b, GLscalar c) { glColor3f(a, b, c); }
-inline void glColor4(GLscalar a, GLscalar b, GLscalar c, GLscalar d) { glColor4f(a, b, c, d); }
-inline void glColor3v(const GLscalar *a) { glColor3fv(a); }
-inline void glColor4v(const GLscalar *a) { glColor4fv(a); }
-
-inline void glVertex2(GLscalar a, GLscalar b) { glVertex2f(a, b); }
-inline void glVertex3(GLscalar a, GLscalar b, GLscalar c) { glVertex3f(a, b, c); }
-inline void glVertex4(GLscalar a, GLscalar b, GLscalar c, GLscalar d) { glVertex4f(a, b, c, d); }
-inline void glVertex2v(const GLscalar* a) { glVertex2fv(a); }
-inline void glVertex3v(const GLscalar* a) { glVertex3fv(a); }
-inline void glVertex4v(const GLscalar* a) { glVertex4fv(a); }
-
-inline void glTexCoord2(GLscalar a, GLscalar b) { glTexCoord2f(a, b); }
-inline void glTexCoord3(GLscalar a, GLscalar b, GLscalar c) { glTexCoord3f(a, b, c); }
-inline void glTexCoord4(GLscalar a, GLscalar b, GLscalar c, GLscalar d) { glTexCoord4f(a, b, c, d); }
-inline void glTexCoord2v(const GLscalar* a) { glTexCoord2fv(a); }
-inline void glTexCoord3v(const GLscalar* a) { glTexCoord3fv(a); }
-inline void glTexCoord4v(const GLscalar* a) { glTexCoord4fv(a); }
+#define SCALAR(F) F##f
+
+inline void glGetScalarv(GLenum a, GLscalar* b)
+{ glGetFloatv(a, b); }
+
+inline void glLoadMatrix(const GLscalar* a)
+{ glLoadMatrixf(a); }
+inline void glMultMatrix(const GLscalar* a)
+{ glMultMatrixf(a); }
+
+inline void glScale(GLscalar a, GLscalar b, GLscalar c)
+{ glScalef(a, b, c); }
+inline void glRotate(GLscalar a, GLscalar b, GLscalar c, GLscalar d)
+{ glRotatef(a, b, c, d); }
+inline void glTranslate(GLscalar a, GLscalar b, GLscalar c)
+{ glTranslatef(a, b, c); }
+
+inline void glColor3(GLscalar a, GLscalar b, GLscalar c)
+{ glColor3f(a, b, c); }
+inline void glColor4(GLscalar a, GLscalar b, GLscalar c, GLscalar d)
+{ glColor4f(a, b, c, d); }
+inline void glColor3v(const GLscalar *a)
+{ glColor3fv(a); }
+inline void glColor4v(const GLscalar *a)
+{ glColor4fv(a); }
+
+inline void glVertex2(GLscalar a, GLscalar b)
+{ glVertex2f(a, b); }
+inline void glVertex3(GLscalar a, GLscalar b, GLscalar c)
+{ glVertex3f(a, b, c); }
+inline void glVertex4(GLscalar a, GLscalar b, GLscalar c, GLscalar d)
+{ glVertex4f(a, b, c, d); }
+inline void glVertex2v(const GLscalar* a)
+{ glVertex2fv(a); }
+inline void glVertex3v(const GLscalar* a)
+{ glVertex3fv(a); }
+inline void glVertex4v(const GLscalar* a)
+{ glVertex4fv(a); }
+
+inline void glTexCoord2(GLscalar a, GLscalar b)
+{ glTexCoord2f(a, b); }
+inline void glTexCoord3(GLscalar a, GLscalar b, GLscalar c)
+{ glTexCoord3f(a, b, c); }
+inline void glTexCoord4(GLscalar a, GLscalar b, GLscalar c, GLscalar d)
+{ glTexCoord4f(a, b, c, d); }
+inline void glTexCoord2v(const GLscalar* a)
+{ glTexCoord2fv(a); }
+inline void glTexCoord3v(const GLscalar* a)
+{ glTexCoord3fv(a); }
+inline void glTexCoord4v(const GLscalar* a)
+{ glTexCoord4fv(a); }
#endif
+++ /dev/null
-
-/*******************************************************************************
-
- 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 <map>
-#include <vector>
-
-#include "Aabb.hh"
-#include "Camera.hh"
-#include "Entity.hh"
-#include "Log.hh"
-#include "Math.hh"
-#include "Scene.hh"
-#include "Script.hh"
-#include "Settings.hh"
-#include "Tilemap.hh"
-
-
-namespace Mf {
-
-
-static std::string getPath(const std::string& name)
-{
- return Resource::getPath("scenes/" + name + ".lua");
-}
-
-
-struct Meh
-{
- Matrix4 transform;
- std::string texture;
-
- OctreeP octree;
-
- enum AXIS
- {
- X = 0,
- Y = 1,
- Z = 2
- };
-
- Meh()
- {
- 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())
- {
- 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);
- table[i].pushField();
- }
- }
-
- 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]);
-
- return 0;
- }
-
- int setPlayfieldBounds(Script& script)
- {
- Aabb bounds;
- return loadBox(script, bounds);
- }
-
- 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;
-
- 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);
-
- Matrix4 scaling;
- cml::matrix_uniform_scale(scaling, value);
- transform = scaling * transform;
- }
- else
- {
- script.getTop().throwError("wrong number of arguments");
- }
-
- 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;
- }
-
- int setTexture(Script& script)
- {
- 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<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
-
- i = 1;
- for (h = height - 1; h >= 0; --h)
- {
- std::vector<Tilemap::Index> row;
-
- for (w = 0; w < width; ++w, ++i)
- {
- script.checkStack(2);
- script.push(long(i));
- tiles.pushField();
-
- long index;
- top.get(index);
-
- row.push_back(Tilemap::Index(index));
- }
-
- indices[h] = row;
- }
-
- Vector4 vertices[height+1][width+1];
-
- Matrix4 transposedTransform = transform;
- transposedTransform.transpose();
-
- 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;
- }
- }
-
- for (int h = 0; h < height; ++h)
- {
- for (int w = 0; w < width; ++w)
- {
- if (indices[h][w] == Tilemap::NO_TILE) continue;
-
- 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<Quad> quadPtr(quad);
-
- octree->insert(quadPtr);
- }
- }
-
- return 0;
- }
-
- int makeBillboard(Script& script)
- {
- Script::Value table = script[1];
- Script::Value top = script[-1];
-
- long index = 0;
- long width = 1;
- bool blending = false;
- bool fog = false;
-
- if (table.isTable())
- {
- table.pushField("tile");
- top.get(index);
-
- table.pushField("u_scale");
- top.get(width);
-
- table.pushField("blend");
- top.get(blending);
-
- table.pushField("fog");
- top.get(fog);
- }
-
- Vector4 vertices[2][width+1];
-
- Matrix4 transposedTransform = transform;
- transposedTransform.transpose();
-
- Scalar xf;
- Scalar increment = 1.0 / Scalar(width);
-
- for (int h = 0; h <= 1; ++h)
- {
- xf = 0.0;
- for (int w = 0; w <= width; ++w, xf += increment)
- {
- vertices[h][w] = Vector4(xf, Scalar(h), 0.0, 1.0) *
- transposedTransform;
- }
- }
-
- for (int w = 0; w < width; ++w)
- {
- Vector3 quadVertices[4];
-
- 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]);
-
- Quad* quad = new Quad(quadVertices, texture, Tilemap::Index(index));
- quad->setBlending(blending);
- quad->setFog(fog);
-
- boost::shared_ptr<Quad> quadPtr(quad);
-
- octree->insert(quadPtr);
- }
-
- return 0;
- }
-};
-
-
-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");
-}
-
-
-OctreeP loadScene(const std::string& name)
-{
- std::string filePath = getPath(name);
-
- Meh cool;
-
- Script script;
- script.importStandardLibraries();
- importLogScript(script);
- importSceneBindings(script, cool);
-
- if (script.doFile(filePath) != Script::SUCCESS)
- {
- std::string str;
- script[-1].get(str);
- logScript("%s", str.c_str());
- }
-
- cool.octree->sort();
- return cool.octree;
-}
-
-
-} // namespace Mf
-
-/** vim: set ts=4 sw=4 tw=80: *************************************************/
-
+++ /dev/null
-
-/*******************************************************************************
-
- 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.
-
-*******************************************************************************/
-
-#ifndef _MOOF_SCENE_HH_
-#define _MOOF_SCENE_HH_
-
-#include <string>
-
-#include <boost/shared_ptr.hpp>
-
-#include <Moof/Drawable.hh>
-#include <Moof/Entity.hh>
-#include <Moof/Octree.hh>
-#include <Moof/Resource.hh>
-#include <Moof/Tilemap.hh>
-
-
-namespace Mf {
-
-
-OctreeP loadScene(const std::string& name);
-
-
-class Quad : public Entity
-{
- Scalar vertices_[12];
- Scalar texCoords_[8];
-
- Tilemap tilemap_;
-
- bool blending_;
- bool fog_;
-
-public:
-
- enum SURFACE_TYPE
- {
- LEFT = 1,
- RIGHT = 2,
- TOP = 3
- };
-
- Quad(const Vector3 vertices[4], const std::string& texture,
- Tilemap::Index tileIndex) :
- tilemap_(texture),
- blending_(false),
- fog_(false)
- {
- for (int i = 0, num = 0; i < 4; ++i)
- {
- for (int j = 0; j < 3; ++j, ++num)
- {
- vertices_[num] = vertices[i][j];
- }
- }
-
- if (!tilemap_.getTileCoords(tileIndex, texCoords_))
- {
- 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;
- }
-
- aabb_.encloseVertices(vertices, 4);
- sphere_.point = aabb_.getCenter();
- sphere_.radius = (aabb_.min - sphere_.point).length();
- }
-
- void setBlending(bool blending)
- {
- blending_ = blending;
- }
-
- void setFog(bool fog)
- {
- fog_ = fog;
- }
-
- void draw(Scalar alpha = 0.0) const
- {
- if (blending_)
- {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- if (fog_)
- {
- glEnable(GL_FOG);
- glFogi(GL_FOG_MODE, GL_LINEAR);
- }
-
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- tilemap_.bind();
-
- glVertexPointer(3, GL_SCALAR, 0, vertices_);
- glTexCoordPointer(2, GL_SCALAR, 0, texCoords_);
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- glDisable(GL_BLEND);
- glDisable(GL_FOG);
- }
-
- bool isVisible(const Frustum& frustum) const
- {
- return sphere_.isVisible(frustum);
- }
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_SCENE_HH_
-
-/** vim: set ts=4 sw=4 tw=80: *************************************************/
-
--- /dev/null
+
+/*******************************************************************************
+
+ 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.
+
+*******************************************************************************/
+
+#ifndef _MOOF_TRANSITION_HH_
+#define _MOOF_TRANSITION_HH_
+
+#include <boost/shared_ptr.hpp>
+
+#include <Moof/Engine.hh>
+#include <Moof/Interpolator.hh>
+#include <Moof/Layer.hh>
+#include <Moof/Log.hh>
+#include <Moof/Math.hh>
+#include <Moof/OpenGL.hh>
+#include <Moof/Texture.hh>
+
+
+namespace Mf {
+
+
+template <typename T>
+class Transition : public Layer
+{
+ LayerP to;
+ LayerP from;
+
+ T interpolator;
+
+ Engine* engine;
+
+public:
+
+ Transition(LayerP t, LayerP f, const T& interp) :
+ to(t),
+ from(f),
+ interpolator(interp),
+ engine(0) {}
+
+ typedef boost::shared_ptr<Transition> Ptr;
+
+ static Ptr alloc(LayerP t, LayerP f, const T& interp)
+ {
+ return Ptr(new Transition(t, f, interp));
+ }
+
+
+ void pushed(Engine& e)
+ {
+ engine = &e;
+ }
+
+ void popped(Engine& e)
+ {
+ if (to) e.push(to);
+ }
+
+ void update(Scalar t, Scalar dt)
+ {
+ interpolator.update(t, dt);
+
+ if (from) from->update(t, dt);
+ if (to) to->update(t, dt);
+
+ if (interpolator.isDone())
+ {
+ // to should /replace/ this
+ engine->pop(this);
+ }
+ }
+
+ void drawFade(Scalar alpha) const
+ {
+ // DRAW FADE
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_ALPHA_TEST);
+ glEnable(GL_BLEND);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glColor4(1.0, 1.0, 1.0, alpha);
+ Mf::Texture::resetBind();
+
+ //glRectf(-1.0f, -1.0f, 1.0f, 1.0f);
+ glBegin(GL_QUADS);
+ glVertex3f(-1.0, -1.0, -0.1);
+ glVertex3f(1.0, -1.0, -0.1);
+ glVertex3f(1.0, 1.0, -0.1);
+ glVertex3f(-1.0, 1.0, -0.1);
+ glEnd();
+
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_ALPHA_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+
+ void draw(Scalar alpha) const
+ {
+ Scalar a = interpolator.getState(alpha);
+ logInfo("draw state: %f", a);
+
+ //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ if (from)
+ {
+ glPushMatrix();
+ glLoadIdentity();
+ glRotate(180.0 * a, 0.0, 1.0, 0.0);
+ from->draw(alpha);
+ glPopMatrix();
+ }
+ //drawFade(a);
+
+ if (to)
+ {
+ glPushMatrix();
+ glLoadIdentity();
+ glRotate(180.0 * (1.0 - a), 0.0, 1.0, 0.0);
+ to->draw(alpha);
+ glPopMatrix();
+ }
+ //drawFade(1.0 - a);
+ }
+
+ bool handleEvent(const Event& event)
+ {
+ if (to)
+ {
+ return to->handleEvent(event);
+ }
+ else if (from)
+ {
+ return from->handleEvent(event);
+ }
+ return false;
+ }
+};
+
+
+} // namespace Mf
+
+#endif // _MOOF_TRANSITION_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
}
+int Video::getWidth() const
+{
+ return context_->w;
+}
+
+int Video::getHeight() const
+{
+ return context_->h;
+}
+
+
Video::Attributes::Attributes()
{
// Set some sane GL and window defaults (see SDL_video.c:217)
void makeActive();
void swap();
+ int getWidth() const;
+ int getHeight() const;
+
struct Exception : public Mf::Exception
{
--- /dev/null
+
+/*******************************************************************************
+
+ 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 <map>
+#include <vector>
+
+#include <Moof/Aabb.hh>
+#include <Moof/Camera.hh>
+#include <Moof/Entity.hh>
+#include <Moof/Log.hh>
+#include <Moof/Math.hh>
+#include <Moof/Mippleton.hh>
+#include <Moof/Octree.hh>
+#include <Moof/Script.hh>
+#include <Moof/Settings.hh>
+#include <Moof/Tilemap.hh>
+
+#include "Scene.hh"
+
+
+struct Scene::Impl : public Mf::Mippleton<Impl>
+{
+ class Quad : public Mf::Entity, public Mf::OctreeInsertable
+ {
+ 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
+ {
+ 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)
+ {
+ for (int i = 0, num = 0; i < 4; ++i)
+ {
+ for (int j = 0; j < 3; ++j, ++num)
+ {
+ vertices_[num] = vertices[i][j];
+ }
+ }
+
+ if (!tilemap_.getTileCoords(tileIndex, texCoords_))
+ {
+ 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;
+ }
+
+ aabb_.encloseVertices(vertices, 4);
+ sphere_.point = aabb_.getCenter();
+ sphere_.radius = (aabb_.min - sphere_.point).length();
+ }
+
+ void setBlending(bool blending)
+ {
+ blending_ = blending;
+ }
+
+ void setFog(bool fog)
+ {
+ fog_ = fog;
+ }
+
+ void draw(Mf::Scalar alpha = 0.0) const
+ {
+ if (blending_)
+ {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ if (fog_)
+ {
+ glEnable(GL_FOG);
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+ }
+
+ //glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ tilemap_.bind();
+
+ glVertexPointer(3, GL_SCALAR, 0, vertices_);
+ glTexCoordPointer(2, GL_SCALAR, 0, texCoords_);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_FOG);
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+ }
+ }
+
+ return octantNum;
+ }
+ };
+
+
+
+ Mf::Script script;
+
+ Mf::Matrix4 transform;
+ std::string texture;
+
+ Mf::Octree<Quad>::Ptr octree;
+
+
+ enum AXIS
+ {
+ X = 0,
+ Y = 1,
+ Z = 2
+ };
+
+
+
+ explicit Impl(const std::string& name) :
+ Mf::Mippleton<Impl>(name)
+ {
+ script.importStandardLibraries();
+ importLogScript(script);
+
+ importSceneBindings(script);
+ loadFromFile();
+ }
+
+ 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("ResetTransform",
+ boost::bind(&Impl::resetTransform, this, _1));
+ script.importFunction("Translate",
+ boost::bind(&Impl::translate, this, _1));
+ script.importFunction("Scale",
+ boost::bind(&Impl::scale, this, _1));
+ script.importFunction("Rotate",
+ 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));
+
+ long 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(X); script.set("X");
+ script.push(Y); script.set("Y");
+ script.push(Z); script.set("Z");
+ }
+
+
+ void loadFromFile()
+ {
+ std::string filePath = Scene::getPath(getName());
+
+ if (script.doFile(filePath) != Mf::Script::SUCCESS)
+ {
+ std::string str;
+ script[-1].get(str);
+ Mf::logScript("%s", str.c_str());
+ }
+ }
+
+
+ static int loadBox(Mf::Script& script, Mf::Aabb& aabb)
+ {
+ Mf::Script::Value table[] =
+ {
+ script[1].requireTable(),
+ 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);
+ table[i].pushField();
+ }
+ }
+
+ 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]);
+
+ return 0;
+ }
+
+ int setPlayfieldBounds(Mf::Script& script)
+ {
+ Mf::Aabb bounds;
+ return loadBox(script, bounds);
+ }
+
+ int setMaximumBounds(Mf::Script& script)
+ {
+ Mf::Aabb bounds;
+ int ret = loadBox(script, bounds);
+ octree = Mf::Octree<Quad>::alloc(bounds);
+ return ret;
+ }
+
+ int resetTransform(Mf::Script& script)
+ {
+ transform.identity();
+ return 0;
+ }
+
+ 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]);
+
+ Mf::Matrix4 translation;
+ cml::matrix_translation(translation, vec);
+ transform = translation * transform;
+
+ return 0;
+ }
+
+ int scale(Mf::Script& script)
+ {
+ if (script.getSize() == 3)
+ {
+ 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_scale(scaling, vec);
+ transform = scaling * transform;
+ }
+ else if (script.getSize() == 1)
+ {
+ Mf::Scalar value = 1.0;
+ script[1].requireNumber().get(value);
+
+ Mf::Matrix4 scaling;
+ cml::matrix_uniform_scale(scaling, value);
+ transform = scaling * transform;
+ }
+ else
+ {
+ script.getTop().throwError("wrong number of arguments");
+ }
+
+ return 0;
+ }
+
+ int rotate(Mf::Script& script)
+ {
+ Mf::Script::Value axis = script[1].requireString();
+ Mf::Script::Value angle = script[2].requireNumber();
+
+ size_t index = 0;
+ axis.get(index);
+
+ Mf::Scalar value;
+ angle.get(value);
+
+ cml::matrix_rotate_about_world_axis(transform, index, cml::rad(value));
+
+ return 0;
+ }
+
+ int setTexture(Mf::Script& script)
+ {
+ Mf::Script::Value name = script[1].requireString();
+
+ name.get(texture);
+
+ return 0;
+ }
+
+ int makeTilemap(Mf::Script& script)
+ {
+ Mf::Script::Value table = script[1].requireTable();
+ Mf::Script::Value top = script[-1];
+
+ long width = 1;
+ long height = 1;
+
+ table.pushField("width");
+ top.get(width);
+
+ long nTiles = 0;
+
+ 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;
+
+ 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::vector<Mf::Tilemap::Index> row;
+
+ for (w = 0; w < width; ++w, ++i)
+ {
+ script.checkStack(2);
+ script.push(long(i));
+ tiles.pushField();
+
+ long index;
+ top.get(index);
+
+ row.push_back(Mf::Tilemap::Index(index));
+ }
+
+ indices[h] = row;
+ }
+
+ Mf::Vector4 vertices[height+1][width+1];
+
+ Mf::Matrix4 transposedTransform = transform;
+ 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;
+ }
+ }
+
+ for (int h = 0; h < height; ++h)
+ {
+ for (int w = 0; w < width; ++w)
+ {
+ if (indices[h][w] == Mf::Tilemap::NO_TILE) continue;
+
+ Mf::Vector3 quadVertices[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]);
+
+ Quad* quad = new Quad(quadVertices, texture, indices[h][w]);
+ boost::shared_ptr<Quad> quadPtr(quad);
+
+ octree->insert(quadPtr);
+ }
+ }
+
+ return 0;
+ }
+
+ int makeBillboard(Mf::Script& script)
+ {
+ Mf::Script::Value table = script[1];
+ Mf::Script::Value top = script[-1];
+
+ long index = 0;
+ long width = 1;
+ bool blending = false;
+ bool fog = false;
+
+ if (table.isTable())
+ {
+ table.pushField("tile");
+ top.get(index);
+
+ table.pushField("u_scale");
+ top.get(width);
+
+ table.pushField("blend");
+ top.get(blending);
+
+ table.pushField("fog");
+ top.get(fog);
+ }
+
+ Mf::Vector4 vertices[2][width+1];
+
+ Mf::Matrix4 transposedTransform = transform;
+ transposedTransform.transpose();
+
+ Mf::Scalar xf;
+ Mf::Scalar increment = 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;
+ }
+ }
+
+ for (int w = 0; w < width; ++w)
+ {
+ Mf::Vector3 quadVertices[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]);
+
+ Quad* quad = new Quad(quadVertices, texture, Mf::Tilemap::Index(index));
+ quad->setBlending(blending);
+ quad->setFog(fog);
+
+ boost::shared_ptr<Quad> quadPtr(quad);
+
+ octree->insert(quadPtr);
+ }
+
+ return 0;
+ }
+};
+
+
+Scene::Scene(const std::string& name) :
+ // pass through
+ impl_(Scene::Impl::getInstance(name)) {}
+
+
+void Scene::draw(Mf::Scalar alpha) const
+{
+ impl_->octree->draw(alpha);
+}
+
+void Scene::drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const
+{
+ impl_->octree->drawIfVisible(alpha, frustum);
+}
+
+
+std::string Scene::getPath(const std::string& name)
+{
+ return Mf::Resource::getPath("scenes/" + name + ".lua");
+}
+
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ 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.
+
+*******************************************************************************/
+
+#ifndef _SCENE_HH_
+#define _SCENE_HH_
+
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+
+#include <Moof/Cullable.hh>
+#include <Moof/Drawable.hh>
+#include <Moof/Resource.hh>
+
+
+class Scene;
+typedef boost::shared_ptr<Scene> SceneP;
+
+class Scene : public Mf::Cullable, public Mf::Drawable, public Mf::Resource
+{
+ class Impl;
+ boost::shared_ptr<Impl> impl_;
+
+public:
+
+ Scene(const std::string& name);
+
+ static SceneP alloc(const std::string& name)
+ {
+ return SceneP(new Scene(name));
+ }
+
+ void draw(Mf::Scalar alpha) const;
+ void drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const;
+
+ static std::string getPath(const std::string& name);
+};
+
+
+#endif // _SCENE_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ 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 <Moof/Engine.hh>
+#include <Moof/OpenGL.hh>
+#include <Moof/Transition.hh>
+
+#include "GameLayer.hh"
+#include "TitleLayer.hh"
+
+
+void TitleLayer::pushed(Mf::Engine& e)
+{
+ engine = &e;
+
+ Mf::Scalar coeff[] = {0.0, 1.0};
+ fadeIn.init(coeff, 0.1);
+
+ gameLayer = GameLayer::alloc();
+}
+
+void TitleLayer::update(Mf::Scalar t, Mf::Scalar dt)
+{
+ if (!fadeIn.isDone()) fadeIn.update(t, dt);
+}
+
+void TitleLayer::draw(Mf::Scalar alpha) const
+{
+ glClearColor(0.0, 0.0, fadeIn.getState(alpha), 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+bool TitleLayer::handleEvent(const Mf::Event& event)
+{
+ switch (event.type)
+ {
+ case SDL_KEYUP:
+ Mf::LayerP titleLayer = engine->pop(this);
+ //engine->pushLayer(GameLayer::alloc());
+
+ Mf::Scalar coeff[] = {0.0, 1.0};
+ Mf::Lerp interp(coeff, 0.2);
+
+ //Mf::LayerP gameLayer = GameLayer::alloc();
+ Mf::Transition<Mf::Lerp>::Ptr transition =
+ Mf::Transition<Mf::Lerp>::alloc(gameLayer, titleLayer, interp);
+ engine->push(transition);
+ return true;
+ }
+
+ return false;
+}
+
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ 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.
+
+*******************************************************************************/
+
+#ifndef _TITLELAYER_HH_
+#define _TITLELAYER_HH_
+
+#include <boost/shared_ptr.hpp>
+
+#include <Moof/Interpolator.hh>
+#include <Moof/Layer.hh>
+#include <Moof/Math.hh>
+
+
+class TitleLayer;
+typedef boost::shared_ptr<TitleLayer> TitleLayerP;
+
+struct TitleLayer : public Mf::Layer
+{
+ static TitleLayerP alloc()
+ {
+ return TitleLayerP(new TitleLayer);
+ }
+
+ void pushed(Mf::Engine& engine);
+
+ void update(Mf::Scalar t, Mf::Scalar dt);
+ void draw(Mf::Scalar alpha) const;
+ bool handleEvent(const Mf::Event& event);
+
+private:
+
+ Mf::Lerp fadeIn;
+ Mf::Engine* engine;
+
+ Mf::LayerP gameLayer;
+};
+
+
+#endif // _TITLELAYER_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+