From: Charles McGarvey Date: Mon, 31 Aug 2009 05:59:27 +0000 (-0600) Subject: preliminary physics, sound, hud X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=commitdiff_plain;h=bfa6212d09d8735d8fd5e2638188e4a99f21ada4;ds=sidebyside preliminary physics, sound, hud --- diff --git a/configure.ac b/configure.ac index e8d8d9b..e8fd379 100644 --- a/configure.ac +++ b/configure.ac @@ -98,12 +98,21 @@ BOOST_FUNCTION AC_SEARCH_LIBS([IMG_Load], [SDL_image],, [AC_MSG_ERROR([libSDL_image is required])]) +AC_SEARCH_LIBS([Sound_Init], [SDL_sound],, + [AC_MSG_ERROR([libSDL_sound is required])]) + AC_SEARCH_LIBS([glBegin], [GL],, [AC_MSG_ERROR([libGL is required])]) AC_SEARCH_LIBS([gluPerspective], [GLU],, [AC_MSG_ERROR([libGLU is required])]) +AC_SEARCH_LIBS([alGenBuffers], [openal],, + [AC_MSG_ERROR([libopenal is required])]) + +AC_SEARCH_LIBS([alutInit], [alut],, + [AC_MSG_ERROR([libalut is required])]) + AC_SEARCH_LIBS([clock_gettime], [rt], [AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [Define to 1 if you have the 'clock_gettime' function.])]) @@ -171,7 +180,7 @@ AC_OUTPUT # Print a friendly little message. # -echo "=====================================" +echo "======================================" echo " Configuration complete!" echo "" @@ -194,5 +203,5 @@ fi echo " To finish the installation, execute:" echo " make" echo " make install" -echo "=====================================" +echo "======================================" diff --git a/data/scenes/Test.json b/data/scenes/Test.json index 562a3be..b6aac66 100644 --- a/data/scenes/Test.json +++ b/data/scenes/Test.json @@ -1,6 +1,6 @@ { "playfield_bounds": [0, 0, -100, 1280, 500, 100], - "maximum_bounds": [-160, 0, -192, 1440, 512, 224], + "maximum_bounds": [-160, 0, -192, 1440, 480, 224], "instructions": [ @@ -1043,16 +1043,13 @@ "translate", [-0.3, -0.17, -900], "scale", [3200, 1600, 1], "texture", "BackgroundFar", - "billboard", - { - "fog": false - }, + "billboard", null, + "translate", [0, 0, 300], "texture", "BackgroundNear", "billboard", { - "blend": true, - "fog": false + "blend": true }, /* Trees */ diff --git a/data/sounds/NightFusion.xm b/data/sounds/NightFusion.xm new file mode 100644 index 0000000..06120fc Binary files /dev/null and b/data/sounds/NightFusion.xm differ diff --git a/extra/yoink.ebuild b/extra/yoink.ebuild index 75a1808..52e26c7 100644 --- a/extra/yoink.ebuild +++ b/extra/yoink.ebuild @@ -3,23 +3,30 @@ # $Header: $ EAPI=2 + inherit autotools eutils games DESCRIPTION="Alien-smashing action game" HOMEPAGE="http://www.dogcows.com/" -SRC_URI="http://www.dogcows.com/yoink/${P}.tar.bz2" +SRC_URI="http://www.dogcows.com/yoink/${P}.tar.bz2 + http://eng.utah.edu/~mcgarvey/yoink/${P}.tar.bz2" LICENSE="BSD-2" SLOT="0" -KEYWORDS="~amd64 ~ppc ~x86" +KEYWORDS="amd64 ~ppc x86" IUSE="debug profile" RDEPEND="media-libs/libsdl[opengl] media-libs/sdl-image[png] - virtual/opengl" + virtual/opengl + media-libs/sdl-sound[mikmod, vorbis] + media-libs/openal" DEPEND="${RDEPEND} + dev-libs/boost dev-util/pkgconfig" +RESTRICT="mirror" + src_prepare() { sed -i \ -e "s/-Werror//g" \ @@ -34,6 +41,7 @@ src_prepare() { -e "/man/d" \ doc/Makefile.am \ || die "sed failed" + eautoreconf } diff --git a/src/Character.cc b/src/Character.cc index f508682..97a10b2 100644 --- a/src/Character.cc +++ b/src/Character.cc @@ -28,10 +28,25 @@ #include "Character.hh" +#include Character::Character(const std::string& name) : - tilemap(name), - animation(name) {} + tilemap_(name), + animation_(name) +{ + current.mass = 1.0; + current.inverseMass = 1.0 / current.mass; + + current.force = Mf::Vector2(0.0, -120.0); + + current.position = Mf::Vector2(64.0, 64.0); + current.momentum = Mf::Vector2(0.0, 0.0); + current.recalculate(); + + previous = current; + + updateContainers(); +} Character::~Character() { @@ -40,16 +55,115 @@ Character::~Character() } -void Character::draw(Mf::Scalar alpha) const {} +void Character::update(Mf::Scalar t, Mf::Scalar dt) +{ + previous = current; + Mf::integrate(current, t, dt); + + animation_.update(t, dt); + + 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 = 500.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) + { + current.force += left; + } + else if (event.key.keysym.sym == SDLK_d) + { + current.force += right; + } + else if (event.key.keysym.sym == SDLK_s) + { + current.force += down; + } + else if (event.key.keysym.sym == SDLK_w) + { + current.force += up; + } + break; + + case SDL_KEYUP: + if (event.key.keysym.sym == SDLK_a) + { + current.force -= left; + } + else if (event.key.keysym.sym == SDLK_d) + { + current.force -= right; + } + else if (event.key.keysym.sym == SDLK_s) + { + current.force -= down; + } + else if (event.key.keysym.sym == SDLK_w) + { + current.force -= up; + } + break; + } + + std::cout << "current force: " << current.force << std::endl; +} + + +void Character::draw(Mf::Scalar alpha) const +{ + State state = cml::lerp(previous, current, alpha); + + glColor3f(1.0f, 1.0f, 1.0f); + tilemap_.bind(); + + Mf::Tilemap::Index frame = animation_.getFrame(); + + Mf::Scalar coords[8]; + tilemap_.getTileCoords(frame, coords); + + Mf::Scalar s = 16.0; + + glBegin(GL_QUADS); + glTexCoord2f(coords[0], coords[1]); + glVertex3(state.position[0]-s, state.position[1]-s, z); + glTexCoord2f(coords[2], coords[3]); + glVertex3(state.position[0]+s, state.position[1]-s, z); + glTexCoord2f(coords[4], coords[5]); + glVertex3(state.position[0]+s, state.position[1]+s, z); + glTexCoord2f(coords[6], coords[7]); + glVertex3(state.position[0]-s, state.position[1]+s, z); + glEnd(); +} + Mf::Tilemap& Character::getTilemap() { - return tilemap; + return tilemap_; } Mf::Animation& Character::getAnimation() { - return animation; + return animation_; } diff --git a/src/Character.hh b/src/Character.hh index e39e7ff..a92992c 100644 --- a/src/Character.hh +++ b/src/Character.hh @@ -29,32 +29,143 @@ #ifndef _CHARACTER_HH_ #define _CHARACTER_HH_ +#include + #include -#include -#include +#include +#include +#include +#include +#include #include /** - * Parent class of animate objects with "personalities." + * Parent class of animate objects with "personalities." This basically + * includes the heroine herself and the bad guys. */ -class Character : public Mf::Drawable +class Character : public Mf::Entity { public: + + struct Derivative + { + Mf::Vector2 velocity; + Mf::Vector2 force; + + Derivative operator*(Mf::Scalar dt) const + { + Derivative derivative; + derivative.velocity = dt * velocity; + derivative.force = dt * force; + return derivative; + } + + Derivative operator+(const Derivative& other) const + { + Derivative derivative; + derivative.velocity = velocity + other.velocity; + derivative.force = force + other.force; + return derivative; + } + }; + + struct State + { + // primary + + Mf::Vector2 position; + Mf::Vector2 momentum; + Mf::Vector2 force; + + // secondary + + Mf::Vector2 velocity; + + // constant + + Mf::Scalar mass; + Mf::Scalar inverseMass; + + + void getDerivative(Derivative& derivative, Mf::Scalar t) const + { + //derivative.velocity = Mf::Vector2(0.0, 0.0); + //derivative.force = Mf::Vector2(0.0, 0.0); + derivative.velocity = velocity; + derivative.force = force; + } + + void recalculate() + { + velocity = momentum * inverseMass; + } + + void applyDerivative(const Derivative& derivative, Mf::Scalar dt) + { + position += dt * derivative.velocity; + momentum += dt * derivative.force; + recalculate(); + } + + State operator*(Mf::Scalar scalar) const + { + State state = *this; + state.position *= scalar; + state.momentum *= scalar; + state.recalculate(); + return state; + } + + State operator+(State state) const + { + State newState = *this; + newState.position += state.position; + newState.momentum += state.momentum; + newState.recalculate(); + return newState; + } + }; + + Character(const std::string& name); - ~Character(); + virtual ~Character(); + void update(Mf::Scalar t, Mf::Scalar dt); + void handleEvent(const Mf::Event& event); void draw(Mf::Scalar alpha) const; Mf::Tilemap& getTilemap(); Mf::Animation& getAnimation(); + State previous; + State current; + + stlplus::ntree::iterator treeNode; + private: - Mf::Tilemap tilemap; - Mf::Animation animation; + + void updateContainers(); + + static const Mf::Scalar z = 96.0; + + Mf::Tilemap tilemap_; + Mf::Animation animation_; }; +typedef boost::shared_ptr CharacterPtr; + + +inline Character::State operator*(Mf::Scalar scalar, const Character::State& state) +{ + Character::State newState = state; + newState.position *= scalar; + newState.momentum *= scalar; + newState.recalculate(); + return newState; +} + #endif // _CHARACTER_HH_ diff --git a/src/Hud.cc b/src/Hud.cc new file mode 100644 index 0000000..ea0dfea --- /dev/null +++ b/src/Hud.cc @@ -0,0 +1,176 @@ + +/******************************************************************************* + + 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 + +#include "Hud.hh" + +#include + + +ProgressBar::ProgressBar(const Mf::Tilemap& tilemap, Mf::Tilemap::Index index) : + progress_(0.0), + tilemap_(tilemap) +{ + tilemap.getTileCoords(index, texCoords_); + + Mf::Scalar half = (texCoords_[2] - texCoords_[0]) / 2.0 + texCoords_[0]; + midCoords_[0] = half - 0.01; + midCoords_[1] = half + 0.01; +} + +void ProgressBar::resize(const Mf::Rectangle& rect) +{ + Mf::Scalar height = rect.max[1] - rect.min[1]; + Mf::Scalar halfHeight = height / 2.0; + + width_ = rect.max[0] - rect.min[0] - height; + // assert width > 0 + + vertices_[0] = rect.min; + vertices_[1] = Mf::Vector2(rect.min[0] + halfHeight, rect.min[1]); + vertices_[2] = vertices_[1]; + vertices_[3] = Mf::Vector2(rect.min[0] + height, rect.min[1]); + vertices_[4] = Mf::Vector2(rect.min[0] + height, rect.max[1]); + vertices_[5] = Mf::Vector2(rect.min[0] + halfHeight, rect.max[1]); + vertices_[6] = vertices_[5]; + vertices_[7] = Mf::Vector2(rect.min[0], rect.max[1]); + + setProgress(progress_); +} + +void ProgressBar::setProgress(Mf::Scalar progress) +{ + Mf::Scalar halfHeight = (vertices_[7][1] - vertices_[0][1]) / 2.0; + + vertices_[2][0] = vertices_[1][0] + progress * width_; + vertices_[3][0] = vertices_[1][0] + progress * width_ + halfHeight; + vertices_[4][0] = vertices_[1][0] + progress * width_ + halfHeight; + vertices_[5][0] = vertices_[1][0] + progress * width_; + + progress_ = progress; +} + +void ProgressBar::draw(Mf::Scalar alpha) const +{ + if (Mf::isEqual(progress_, 0.0)) + { + // don't draw anything if the progress is 0% + return; + } + + glColor4f(1.0f, 1.0f, 1.0f, 0.85f); + tilemap_.bind(); + + glBegin(GL_QUADS); + glTexCoord2(texCoords_[0], texCoords_[1]); + glVertex2v(vertices_[0].data()); + glTexCoord2(midCoords_[0], texCoords_[3]); + glVertex2v(vertices_[1].data()); + glTexCoord2(midCoords_[0], texCoords_[5]); + glVertex2v(vertices_[6].data()); + glTexCoord2(texCoords_[6], texCoords_[7]); + glVertex2v(vertices_[7].data()); + + glTexCoord2(midCoords_[0], texCoords_[1]); + glVertex2v(vertices_[1].data()); + glTexCoord2(midCoords_[1], texCoords_[3]); + glVertex2v(vertices_[2].data()); + glTexCoord2(midCoords_[1], texCoords_[5]); + glVertex2v(vertices_[5].data()); + glTexCoord2(midCoords_[0], texCoords_[7]); + glVertex2v(vertices_[6].data()); + + glTexCoord2(midCoords_[1], texCoords_[1]); + glVertex2v(vertices_[2].data()); + glTexCoord2(texCoords_[2], texCoords_[3]); + glVertex2v(vertices_[3].data()); + glTexCoord2(texCoords_[4], texCoords_[5]); + glVertex2v(vertices_[4].data()); + glTexCoord2(midCoords_[1], texCoords_[7]); + glVertex2v(vertices_[5].data()); + glEnd(); +} + + +Hud::Hud() : + bar1_(Mf::Tilemap("StatusBars"), 0), + bar2_(Mf::Tilemap("StatusBars"), 2), + font_("Font") +{ + resize(800, 600); +} + + +void Hud::resize(int width, int height) +{ + cml::matrix_orthographic_RH( projection_, + 0.0, + Mf::Scalar(width), 0.0, Mf::Scalar(height), + 1.0, -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, + 0.7 * width, height - 3)); + bar2_.resize(Mf::Rectangle(20, height - 28, + 0.7 * width, height - 70)); + + setBar1Progress(0.05); + setBar2Progress(0.0); +} + + +void Hud::draw(Mf::Scalar alpha) const +{ + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrix(projection_.data()); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + + bar1_.draw(); + bar2_.draw(); + + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Hud.hh b/src/Hud.hh new file mode 100644 index 0000000..813e67f --- /dev/null +++ b/src/Hud.hh @@ -0,0 +1,107 @@ + +/******************************************************************************* + + 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 _HUD_HH_ +#define _HUD_HH_ + +/** + * @file Hud.hh + * Heads-up Display + */ + +#include +#include +#include +#include + + +class ProgressBar : public Mf::Drawable +{ +public: + + ProgressBar(const Mf::Tilemap& tilemap, Mf::Tilemap::Index index); + + void resize(const Mf::Rectangle& rect); + + void setProgress(Mf::Scalar progress); + + void draw(Mf::Scalar alpha = 0.0) const; + +private: + + Mf::Scalar progress_; + + Mf::Vector2 vertices_[8]; + Mf::Scalar width_; + + Mf::Tilemap tilemap_; + Mf::Scalar texCoords_[8]; + Mf::Scalar midCoords_[2]; +}; + + +class Hud : public Mf::Drawable +{ +public: + + Hud(); + + inline void setBar1Progress(Mf::Scalar progress) + { + // pass through + bar1_.setProgress(progress); + } + + inline void setBar2Progress(Mf::Scalar progress) + { + // pass through + bar2_.setProgress(progress); + } + + void setNumber(unsigned value); + + void resize(int width, int height); + + void draw(Mf::Scalar alpha = 0.0) const; + +private: + + ProgressBar bar1_; + ProgressBar bar2_; + + unsigned number_; + Mf::Tilemap font_; + + Mf::Matrix4 projection_; +}; + + +#endif // _HUD_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Makefile.am b/src/Makefile.am index f4122de..3273bea 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,13 +27,17 @@ libmoof_la_SOURCES = \ Moof/Interpolator.hh \ Moof/Math.hh \ Moof/Mippleton.hh \ + Moof/Octree.cc \ Moof/Octree.hh \ Moof/OpenGL.cc \ Moof/OpenGL.hh \ + Moof/Physics.hh \ Moof/Plane.cc \ Moof/Plane.hh \ Moof/Random.cc \ Moof/Random.hh \ + Moof/Rectangle.cc \ + Moof/Rectangle.hh \ Moof/Resource.cc \ Moof/Resource.hh \ Moof/Scene.cc \ @@ -45,6 +49,8 @@ libmoof_la_SOURCES = \ Moof/Settings.cc \ Moof/Settings.hh \ Moof/Singleton.hh \ + Moof/Sound.cc \ + Moof/Sound.hh \ Moof/Sphere.cc \ Moof/Sphere.hh \ Moof/StringTools.cc \ @@ -71,6 +77,8 @@ bin_PROGRAMS = yoink yoink_SOURCES = \ Character.cc \ Character.hh \ + Hud.cc \ + Hud.hh \ TilemapFont.cc \ TilemapFont.hh \ Typesetter.cc \ diff --git a/src/Moof/Aabb.cc b/src/Moof/Aabb.cc index c844251..1fb382f 100644 --- a/src/Moof/Aabb.cc +++ b/src/Moof/Aabb.cc @@ -26,10 +26,10 @@ *******************************************************************************/ -#include -#include -#include -#include +#include "Aabb.hh" +#include "Camera.hh" +#include "OpenGL.hh" +#include "Texture.hh" namespace Mf { diff --git a/src/Moof/Animation.cc b/src/Moof/Animation.cc index 38ffa6c..30e3fbb 100644 --- a/src/Moof/Animation.cc +++ b/src/Moof/Animation.cc @@ -39,14 +39,14 @@ namespace Mf { /** * The collection of nested animation classes. The animation implementation - * consists of an AnimationImpl classes which is allocated and initialized with - * the interface object. This class contains the specific fields which are - * required to run a single instance of an animation. The sequence data is - * loaded in a difference class which can be shared amongst multiple animation - * implementation instances. + * consists of an Impl class which is allocated and initialized with the + * interface object. This class contains the specific fields which are required + * to run a single instance of an animation. The sequence data is loaded in a + * different class which can be shared amongst multiple animation implementation + * instances. */ -struct Animation::AnimationImpl +struct Animation::Impl { /** @@ -55,7 +55,7 @@ struct Animation::AnimationImpl * which wants to use these loaded sequences. */ - struct AnimationData : public Mippleton + struct GlobalData : public Mippleton { /** * A frame of an animation sequence. A frame is merely an index which @@ -182,7 +182,7 @@ struct Animation::AnimationImpl void loadFromFile() { - std::string filePath = Animation::getPathToResource(getName()); + std::string filePath = Animation::getPath(getName()); Deserializer deserializer(filePath); @@ -210,8 +210,8 @@ struct Animation::AnimationImpl * registers itself as a mippleton and then loads the animation data. */ - explicit AnimationData(const std::string& name) : - Mippleton(name) + explicit GlobalData(const std::string& name) : + Mippleton(name) { loadFromFile(); } @@ -224,8 +224,8 @@ struct Animation::AnimationImpl * Construction is intialization. */ - AnimationImpl(const std::string& name) : - data(AnimationData::retain(name), &AnimationData::release), + Impl(const std::string& name) : + data(GlobalData::retain(name), &GlobalData::release), currentSequence(0), frameCounter(0), frameIndex(0), @@ -241,7 +241,7 @@ struct Animation::AnimationImpl void startSequence(const std::string& name) { - std::map::iterator it; + std::map::iterator it; it = data->sequences.find(name); @@ -299,9 +299,9 @@ struct Animation::AnimationImpl } } - boost::shared_ptr data; ///< Internal data. + boost::shared_ptr data; ///< Internal data. - AnimationData::Sequence* currentSequence; ///< Active sequence. + GlobalData::Sequence* currentSequence; ///< Active sequence. unsigned frameCounter; ///< Current frame. unsigned frameIndex; ///< Index of current frame. Scalar timeAccum; ///< Time accumulation. @@ -311,7 +311,7 @@ struct Animation::AnimationImpl Animation::Animation(const std::string& name) : // pass through - impl_(new Animation::AnimationImpl(name)) {} + impl_(new Animation::Impl(name)) {} void Animation::startSequence(const std::string& name) @@ -343,9 +343,9 @@ unsigned Animation::getFrame() const * "animations" subdirectory of any of the searched directories. */ -std::string Animation::getPathToResource(const std::string& name) +std::string Animation::getPath(const std::string& name) { - return Resource::getPathToResource("animations/" + name + ".json"); + return Resource::getPath("animations/" + name + ".json"); } diff --git a/src/Moof/Animation.hh b/src/Moof/Animation.hh index 57ce6a8..cfda19b 100644 --- a/src/Moof/Animation.hh +++ b/src/Moof/Animation.hh @@ -63,11 +63,11 @@ public: void update(Scalar t, Scalar dt); unsigned getFrame() const; - static std::string getPathToResource(const std::string& name); + static std::string getPath(const std::string& name); private: - class AnimationImpl; - boost::shared_ptr impl_; + class Impl; + boost::shared_ptr impl_; }; diff --git a/src/Moof/Camera.cc b/src/Moof/Camera.cc index cdebc7a..b38dd14 100644 --- a/src/Moof/Camera.cc +++ b/src/Moof/Camera.cc @@ -37,6 +37,7 @@ namespace Mf { void Camera::setPosition(const Vector3& point) { position_ = point; + calculateSecondary(); //Vector3 coeff[2] = {position_, point}; //pInterp_.init(coeff, 0.1); } @@ -79,7 +80,8 @@ void Camera::update(Scalar t, Scalar dt) void Camera::lookAt(const Vector3& point) { - quaternion_rotation_aim_at(rotation_, position_, point); + cml::quaternion_rotation_aim_at(rotation_, position_, point, Vector3(0.0, -1.0, 0.0)); + calculateSecondary(); } void Camera::adjustFromInput(const Event& event) @@ -87,29 +89,25 @@ void Camera::adjustFromInput(const Event& event) switch (event.type) { case SDL_KEYDOWN: - if (event.key.keysym.sym == SDLK_RIGHT || - event.key.keysym.sym == SDLK_d) + if (event.key.keysym.sym == SDLK_RIGHT) { Vector3 vec = position_; vec[0] -= 50.0; setPosition(vec); } - else if (event.key.keysym.sym == SDLK_LEFT || - event.key.keysym.sym == SDLK_a) + else if (event.key.keysym.sym == SDLK_LEFT) { Vector3 vec = position_; vec[0] += 50.0; setPosition(vec); } - else if (event.key.keysym.sym == SDLK_UP || - event.key.keysym.sym == SDLK_w) + else if (event.key.keysym.sym == SDLK_UP) { Vector3 vec = position_; vec[1] -= 50.0; setPosition(vec); } - else if (event.key.keysym.sym == SDLK_DOWN || - event.key.keysym.sym == SDLK_s) + else if (event.key.keysym.sym == SDLK_DOWN) { Vector3 vec = position_; vec[1] += 50.0; @@ -123,7 +121,6 @@ void Camera::adjustFromInput(const Event& event) } else if (event.key.keysym.sym == SDLK_PAGEDOWN) { - //position_[2] -= 50.0; Vector3 vec = position_; vec[2] -= 50.0; setPosition(vec); @@ -137,9 +134,9 @@ void Camera::adjustFromInput(const Event& event) Quaternion rotation = rotation_; - quaternion_rotate_about_world_x(rotation, yrel); + cml::quaternion_rotate_about_world_x(rotation, yrel); //rotation_.normalize(); - quaternion_rotate_about_world_y(rotation, xrel); + cml::quaternion_rotate_about_world_y(rotation, xrel); rotation.normalize(); setRotation(rotation); @@ -167,13 +164,14 @@ void Camera::adjustFromInput(const Event& event) void Camera::calculateSecondary() { - matrix_rotation_quaternion(modelview_, rotation_); + cml::matrix_rotation_quaternion(modelview_, rotation_); Matrix4 translate; - matrix_translation(translate, position_); + cml::matrix_translation(translate, position_); - //modelview_ = translate * modelview_; + //modelview_.transpose(); modelview_ *= translate; + //modelview_ = translate * modelview_; frustum_.init(modelview_, projection_); } diff --git a/src/Moof/Engine.cc b/src/Moof/Engine.cc index 53fca73..7823368 100644 --- a/src/Moof/Engine.cc +++ b/src/Moof/Engine.cc @@ -32,6 +32,8 @@ #include #include "fastevents.h" +#include +#include #include "Dispatcher.hh" #include "Engine.hh" @@ -44,10 +46,10 @@ namespace Mf { -class Engine::EngineImpl +class Engine::Impl { public: - EngineImpl(int argc, char* argv[], const std::string& configFile, + Impl(int argc, char* argv[], const std::string& configFile, const std::string& name, const std::string& iconFile, Engine* outer) : interface(outer), @@ -61,18 +63,18 @@ public: { throw Exception(FE_GetError()); } + if (Sound_Init() != 0) + { + //throw Exception(Sound_GetError()); + std::cerr << Sound_GetError() << std::endl; + } + alutInit(&argc, argv); settings.loadFromFile(configFile); long randomSeed; - if (settings.get("engine.rngseed", randomSeed)) - { - setSeed(randomSeed); - } - else - { - setSeed(); - } + if (settings.get("engine.rngseed", randomSeed)) setSeed(randomSeed); + else setSeed(); double ts = 0.01; settings.get("engine.timestep", ts); @@ -89,11 +91,13 @@ public: video->makeActive(); } - ~EngineImpl() + ~Impl() { // the video object must be destroyed before we can shutdown SDL video.reset(); + alutExit(); + Sound_Quit(); FE_Quit(); SDL_Quit(); } @@ -232,8 +236,7 @@ public: Engine::Engine(int argc, char* argv[], const std::string& configFile, const std::string& name, const std::string& iconFile) : - impl_(new Engine::EngineImpl(argc, argv, configFile, name, iconFile, this)) -{} + impl_(new Engine::Impl(argc, argv, configFile, name, iconFile, this)) {} Engine::~Engine() {} diff --git a/src/Moof/Engine.hh b/src/Moof/Engine.hh index 76120c4..971d68f 100644 --- a/src/Moof/Engine.hh +++ b/src/Moof/Engine.hh @@ -75,8 +75,8 @@ public: }; private: - class EngineImpl; - boost::shared_ptr impl_; + class Impl; + boost::shared_ptr impl_; }; diff --git a/src/Moof/Math.hh b/src/Moof/Math.hh index 26c4b51..a38af8b 100644 --- a/src/Moof/Math.hh +++ b/src/Moof/Math.hh @@ -68,12 +68,27 @@ inline Vector3& demoteVector(Vector3& left, const Vector4& right) return left; } -inline Vector4& promoteVector(Vector4& left, const Vector3& right) +inline Vector2& demoteVector(Vector2& left, const Vector3& right) +{ + left[0] = right[0]; + left[1] = right[1]; + return left; +} + +inline Vector4& promoteVector(Vector4& left, const Vector3& right, Scalar extra = 1.0) { left[0] = right[0]; left[1] = right[1]; left[2] = right[2]; - left[3] = 1.0; + left[3] = extra; + return left; +} + +inline Vector3& promoteVector(Vector3& left, const Vector2& right, Scalar extra = 1.0) +{ + left[0] = right[0]; + left[1] = right[1]; + left[3] = extra; return left; } diff --git a/src/Moof/Mippleton.hh b/src/Moof/Mippleton.hh index 7058ecc..9ef9602 100644 --- a/src/Moof/Mippleton.hh +++ b/src/Moof/Mippleton.hh @@ -38,9 +38,11 @@ * after the last interested code releases its hold on the object. */ -#include #include +#include + + namespace Mf { diff --git a/src/Moof/Octree.cc b/src/Moof/Octree.cc new file mode 100644 index 0000000..50b38ac --- /dev/null +++ b/src/Moof/Octree.cc @@ -0,0 +1,320 @@ + +/******************************************************************************* + + 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 "Camera.hh" +#include "Octree.hh" + + +namespace Mf { + + +void Octree::sort() +{ + stlplus::ntree::prefix_iterator it; + + for (it = tree_.prefix_begin(); it != tree_.prefix_end(); ++it) + { + it->sort(); + } +} + + +stlplus::ntree::iterator Octree::insert(stlplus::ntree::iterator node, + EntityPtr entity) +{ + Plane::Halfspace halfspace; + int octantNum = -1; + + if (!node.valid()) + { + std::cerr << "cannot insert into invalid node" << std::endl; + return stlplus::ntree::iterator(); + } + + Plane xy = node->getAabb().getPlaneXY(); + halfspace = xy.intersectsSphere(entity->getSphere()); + if (halfspace == Plane::INTERSECT) + { + halfspace = xy.intersectsAabb(entity->getAabb()); + } + + if (halfspace == Plane::POSITIVE) + { + Plane xz = node->getAabb().getPlaneXZ(); + halfspace = xz.intersectsSphere(entity->getSphere()); + if (halfspace == Plane::INTERSECT) + { + halfspace = xz.intersectsAabb(entity->getAabb()); + } + + if (halfspace == Plane::POSITIVE) + { + Plane yz = node->getAabb().getPlaneYZ(); + halfspace = yz.intersectsSphere(entity->getSphere()); + if (halfspace == Plane::INTERSECT) + { + halfspace = yz.intersectsAabb(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.intersectsSphere(entity->getSphere()); + if (halfspace == Plane::INTERSECT) + { + halfspace = yz.intersectsAabb(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.intersectsSphere(entity->getSphere()); + if (halfspace == Plane::INTERSECT) + { + halfspace = xz.intersectsAabb(entity->getAabb()); + } + + if (halfspace == Plane::POSITIVE) + { + Plane yz = node->getAabb().getPlaneYZ(); + halfspace = yz.intersectsSphere(entity->getSphere()); + if (halfspace == Plane::INTERSECT) + { + halfspace = yz.intersectsAabb(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.intersectsSphere(entity->getSphere()); + if (halfspace == Plane::INTERSECT) + { + halfspace = yz.intersectsAabb(entity->getAabb()); + } + + if (halfspace == Plane::POSITIVE) + { + octantNum = 5; + } + else if (halfspace == Plane::NEGATIVE) + { + octantNum = 4; + } + } + } + + if (octantNum == -1) + { + node->objects.push_front(entity); + return node; + } + else + { + if ((int)tree_.children(node) <= octantNum) + { + addChild(node, octantNum); + } + + stlplus::ntree::iterator child = tree_.child(node, octantNum); + + if (child.valid()) + { + return insert(child, entity); + } + else + { + std::cerr << "expected but found no child at index " << octantNum << std::endl; + return stlplus::ntree::iterator(); + } + } +} + +stlplus::ntree::iterator Octree::reinsert(EntityPtr entity, + stlplus::ntree::iterator node) +{ + if (!node.valid()) + { + std::cerr << "cannot move entity from invalid node" << std::endl; + return stlplus::ntree::iterator(); + } + + std::list::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(stlplus::ntree::iterator node, int index) +{ + Aabb octant; + + if (!node.valid()) + { + std::cerr << "cannot add children to invalid node" << std::endl; + return; + } + + for (int i = tree_.children(node); i <= index; ++i) + { + node->getAabb().getOctant(octant, i); + tree_.append(node, octant); + } +} + + +void Octree::draw(stlplus::ntree::iterator node, Scalar alpha) +{ + if (!node.valid()) + { + std::cerr << "cannot draw null child node :-(" << std::endl; + return; + } + + node->draw(alpha); + + for (unsigned i = 0; i < tree_.children(node); ++i) + { + stlplus::ntree::iterator child = tree_.child(node, i); + + if (child.valid()) + { + draw(child, alpha); + } + else + { + std::cerr << "node is not a leaf, but has an invalid child" << std::endl; + } + + } +} + +void Octree::drawIfVisible(stlplus::ntree::iterator node, + Scalar alpha, const Camera& cam) +{ + //node.drawIfVisible(alpha, cam); + + if (!node.valid()) + { + std::cerr << "invalid child while drawing :-(" << std::endl; + return; + } + + Frustum::Collision collision = + cam.getFrustum().containsSphere(node->getSphere()); + if (collision == Frustum::OUTSIDE) return; + + collision = cam.getFrustum().containsAabb(node->getAabb()); + if (collision == Frustum::OUTSIDE) return; + + + if (collision == Frustum::INSIDE) + { + node->draw(alpha); + } + else // collision == Frustum::INTERSECT + { + node->drawIfVisible(alpha, cam); + } + + if (tree_.children(node) > 0) + { + if (collision == Frustum::INSIDE) + { + for (unsigned i = 0; i < tree_.children(node); ++i) + { + stlplus::ntree::iterator child = tree_.child(node, i); + + if (child.valid()) + { + draw(child, alpha); + } + else + { + std::cerr << "node is not a leaf, but has an invalid child" << std::endl; + } + + } + } + else // collision == Frustum::INTERSECT + { + for (unsigned i = 0; i < tree_.children(node); ++i) + { + stlplus::ntree::iterator child = tree_.child(node, i); + + if (child.valid()) + { + drawIfVisible(child, alpha, cam); + } + else + { + std::cerr << "node is not a leaf, but has an invalid child" << std::endl; + } + } + } + } +} + + +} // namespace Mf + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Moof/Octree.hh b/src/Moof/Octree.hh index 1c57ff2..d896844 100644 --- a/src/Moof/Octree.hh +++ b/src/Moof/Octree.hh @@ -29,6 +29,7 @@ #ifndef _MOOF_OCTREE_HH_ #define _MOOF_OCTREE_HH_ +#include #include #include @@ -45,6 +46,9 @@ namespace Mf { +class Camera; + + struct OctreeNode : public Entity { std::list objects; @@ -71,8 +75,9 @@ struct OctreeNode : public Entity { (*it)->draw(alpha); } - if (!objects.empty()) - aabb_.draw(); // temporary + + //if (!objects.empty()) + //aabb_.draw(); // temporary } void drawIfVisible(Scalar alpha, const Camera& cam) const @@ -83,8 +88,9 @@ struct OctreeNode : public Entity { (*it)->drawIfVisible(alpha, cam); } - if (!objects.empty()) - aabb_.draw(); + + //if (!objects.empty()) + //aabb_.draw(); } @@ -97,257 +103,58 @@ struct OctreeNode : public Entity return false; } -}; -class Octree; -typedef boost::shared_ptr OctreePtr; + static bool compareZOrder(EntityPtr a, EntityPtr b) + { + return a->getSphere().point[2] < b->getSphere().point[2]; + } -class Octree -{ + void sort() + { + //std::sort(objects.begin(), objects.end(), compareZOrder); + objects.sort(compareZOrder); + } +}; - stlplus::ntree root_; +class Octree +{ public: explicit Octree(const OctreeNode& rootNode) { - root_.insert(rootNode); + tree_.insert(rootNode); } - void insert(EntityPtr entity) + stlplus::ntree::iterator insert(EntityPtr entity) { - insert(root_.root(), entity); + return insert(tree_.root(), entity); } - void insert(stlplus::ntree::iterator node, EntityPtr entity) - { - Plane::Halfspace halfspace; - int octantNum = -1; + stlplus::ntree::iterator reinsert(EntityPtr entity, + stlplus::ntree::iterator node); - if (!node.valid()) - { - std::cerr << "cannot insert into invalid node" << std::endl; - return; - } - - Plane xy = node->getAabb().getPlaneXY(); - halfspace = xy.intersectsSphere(entity->getSphere()); - - if (halfspace == Plane::POSITIVE) - { - Plane xz = node->getAabb().getPlaneXZ(); - halfspace = xz.intersectsSphere(entity->getSphere()); - - if (halfspace == Plane::POSITIVE) - { - Plane yz = node->getAabb().getPlaneYZ(); - halfspace = yz.intersectsSphere(entity->getSphere()); - - 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.intersectsSphere(entity->getSphere()); - - 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.intersectsSphere(entity->getSphere()); - - if (halfspace == Plane::POSITIVE) - { - Plane yz = node->getAabb().getPlaneYZ(); - halfspace = yz.intersectsSphere(entity->getSphere()); - - 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.intersectsSphere(entity->getSphere()); - - if (halfspace == Plane::POSITIVE) - { - octantNum = 5; - } - else if (halfspace == Plane::NEGATIVE) - { - octantNum = 4; - } - } - } - - if (octantNum == -1) - { - node->objects.push_front(entity); - //return node; - } - else - { - if (root_.children(node) == 0) - { - addChildren(node); - } - - stlplus::ntree::iterator child = root_.child(node, octantNum); - - if (child.valid()) - { - return insert(child, entity); - } - else - { - std::cerr << "expected but found no child at index " << octantNum << std::endl; - //return stlplus::ntree::iterator(); - } - //return WeakPtr(); - } - } - - void addChildren(stlplus::ntree::iterator node) + void drawIfVisible(Scalar alpha, const Camera& cam) { - Aabb octant; - - if (!node.valid()) - { - std::cerr << "cannot add children to invalid node" << std::endl; - return; - } - - for (int i = 0; i < 8; ++i) - { - node->getAabb().getOctant(octant, i); - //OctreeNode octantNode(octant); - - root_.append(node, octant); - } + drawIfVisible(tree_.root(), alpha, cam); } - void draw(stlplus::ntree::iterator node, Scalar alpha) - { - if (!node.valid()) - { - std::cerr << "cannot draw null child node :-(" << std::endl; - return; - } + void sort(); - node->draw(alpha); - - for (unsigned i = 0; i < root_.children(node); ++i) - { - stlplus::ntree::iterator child = root_.child(node, i); - - if (child.valid()) - { - draw(child, alpha); - } - else - { - std::cerr << "node is not a leaf, but has an invalid child" << std::endl; - } - - } - } +private: + stlplus::ntree::iterator insert(stlplus::ntree::iterator node, EntityPtr entity); + + void addChild(stlplus::ntree::iterator node, int index); + void draw(stlplus::ntree::iterator node, Scalar alpha); void drawIfVisible(stlplus::ntree::iterator node, - Scalar alpha, const Camera& cam) - { - //node.drawIfVisible(alpha, cam); - - if (!node.valid()) - { - std::cerr << "invalid child while drawing :-(" << std::endl; - return; - } - - Frustum::Collision collision = - cam.getFrustum().containsSphere(node->getSphere()); - if (collision == Frustum::OUTSIDE) return; - - collision = cam.getFrustum().containsAabb(node->getAabb()); - if (collision == Frustum::OUTSIDE) return; - - - if (collision == Frustum::INSIDE) - { - node->draw(alpha); - } - else // collision == Frustum::INTERSECT - { - node->drawIfVisible(alpha, cam); - } - - if (root_.children(node) > 0) - { - if (collision == Frustum::INSIDE) - { - for (unsigned i = 0; i < root_.children(node); ++i) - { - stlplus::ntree::iterator child = root_.child(node, i); - - if (child.valid()) - { - draw(child, alpha); - } - else - { - std::cerr << "node is not a leaf, but has an invalid child" << std::endl; - } - - } - } - else // collision == Frustum::INTERSECT - { - for (unsigned i = 0; i < root_.children(node); ++i) - { - stlplus::ntree::iterator child = root_.child(node, i); - - if (child.valid()) - { - drawIfVisible(child, alpha, cam); - } - else - { - std::cerr << "node is not a leaf, but has an invalid child" << std::endl; - } - } - } - } - } - - void drawIfVisible(Scalar alpha, const Camera& cam) - { - drawIfVisible(root_.root(), alpha, cam); - } + Scalar alpha, const Camera& cam); + stlplus::ntree tree_; }; +typedef boost::shared_ptr OctreePtr; } // namespace Mf diff --git a/src/Moof/OpenGL.cc b/src/Moof/OpenGL.cc index e3e742b..b286b35 100644 --- a/src/Moof/OpenGL.cc +++ b/src/Moof/OpenGL.cc @@ -52,6 +52,13 @@ void (*glVertex2v)(const GLscalar*)(glVertex2dv); void (*glVertex3v)(const GLscalar*)(glVertex3dv); void (*glVertex4v)(const GLscalar*)(glVertex4dv); +void (*glTexCoord2)(GLscalar, GLscalar)(glTexCoord2d); +void (*glTexCoord3)(GLscalar, GLscalar, GLscalar)(glTexCoord3d); +void (*glTexCoord4)(GLscalar, GLscalar, GLscalar, GLscalar)(glTexCoord4d); +void (*glTexCoord2v)(const GLscalar*)(glTexCoord2dv); +void (*glTexCoord3v)(const GLscalar*)(glTexCoord3dv); +void (*glTexCoord4v)(const GLscalar*)(glTexCoord4dv); + #else void (*glGetScalarv(GLenum, GLscalar*)(glGetFloatv); @@ -63,6 +70,11 @@ void (*glScale)(GLscalar, GLscalar, GLscalar)(glScalef); void (*glRotate)(GLscalar, GLscalar, GLscalar, GLscalar)(glRotatef); void (*glTranslate)(GLscalar, GLscalar, GLscalar)(glTranslatef); +void (*glColor3)(GLscalar, GLscalar, GLscalar)(glColor3f); +void (*glColor4)(GLscalar, GLscalar, GLscalar, GLscalar)(glColor4f); +void (*glColor3v)(const GLscalar*)(glColor3fv); +void (*glColor4v)(const GLscalar*)(glColor4fv); + void (*glVertex2)(GLscalar, GLscalar)(glVertex2f); void (*glVertex3)(GLscalar, GLscalar, GLscalar)(glVertex3f); void (*glVertex4)(GLscalar, GLscalar, GLscalar, GLscalar)(glVertex4f); @@ -70,10 +82,12 @@ void (*glVertex2v)(const GLscalar*)(glVertex2fv); void (*glVertex3v)(const GLscalar*)(glVertex3fv); void (*glVertex4v)(const GLscalar*)(glVertex4fv); -void (*glColor3)(GLscalar, GLscalar, GLscalar)(glColor3f); -void (*glColor4)(GLscalar, GLscalar, GLscalar, GLscalar)(glColor4f); -void (*glColor3v)(const GLscalar*)(glColor3fv); -void (*glColor4v)(const GLscalar*)(glColor4fv); +void (*glTexCoord2)(GLscalar, GLscalar)(glTexCoord2f); +void (*glTexCoord3)(GLscalar, GLscalar, GLscalar)(glTexCoord3f); +void (*glTexCoord4)(GLscalar, GLscalar, GLscalar, GLscalar)(glTexCoord4f); +void (*glTexCoord2v)(const GLscalar*)(glTexCoord2df); +void (*glTexCoord3v)(const GLscalar*)(glTexCoord3df); +void (*glTexCoord4v)(const GLscalar*)(glTexCoord4df); #endif diff --git a/src/Moof/OpenGL.hh b/src/Moof/OpenGL.hh index 657f05f..51c3e5f 100644 --- a/src/Moof/OpenGL.hh +++ b/src/Moof/OpenGL.hh @@ -70,6 +70,14 @@ extern void (*glVertex2v)(const GLscalar*); extern void (*glVertex3v)(const GLscalar*); extern void (*glVertex4v)(const GLscalar*); +extern void (*glTexCoord2)(GLscalar, GLscalar); +extern void (*glTexCoord3)(GLscalar, GLscalar, GLscalar); +extern void (*glTexCoord4)(GLscalar, GLscalar, GLscalar, GLscalar); +extern void (*glTexCoord2v)(const GLscalar*); +extern void (*glTexCoord3v)(const GLscalar*); +extern void (*glTexCoord4v)(const GLscalar*); + + #endif // _MOOF_OPENGL_HH_ diff --git a/src/Moof/Physics.hh b/src/Moof/Physics.hh new file mode 100644 index 0000000..a79a5c3 --- /dev/null +++ b/src/Moof/Physics.hh @@ -0,0 +1,75 @@ + +/******************************************************************************* + + 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_PHYSICS_HH_ +#define _MOOF_PHYSICS_HH_ + +#include + + +namespace Mf { + +// Generic implementation of the RK4 integrator. To use, you need one type +// representing the state and another containing the derivatives of the state. + +template +inline D evaluate(const S& state, Scalar t) +{ + D derivative; + state.getDerivative(derivative, t); + return derivative; +} + +template +inline D evaluate(const S& state, Scalar t, Scalar dt, const D& derivative) +{ + S temp = state; + temp.applyDerivative(derivative, dt); + return evaluate(temp, t + dt); +} + + +template +inline void integrate(S& state, Scalar t, Scalar dt) +{ + D a = evaluate(state, t); + D b = evaluate(state, t, dt * 0.5, a); + D c = evaluate(state, t, dt * 0.5, b); + D d = evaluate(state, t, dt, c); + + //state += (a + (b + c) * 2.0 + d) * (1.0/6.0) * dt; + state.applyDerivative((a + (b + c) * 2.0 + d) * (1.0/6.0), dt); +} + + +} // namespace Mf + +#endif // _MOOF_PHYSICS_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Moof/Rectangle.cc b/src/Moof/Rectangle.cc new file mode 100644 index 0000000..fef6ac4 --- /dev/null +++ b/src/Moof/Rectangle.cc @@ -0,0 +1,51 @@ + +/******************************************************************************* + + 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 "Rectangle.hh" + + +namespace Mf { + + +void Rectangle::getCorners(Vector2 corners[4]) const +{ + corners[0][0] = min[0]; corners[0][1] = min[1]; + corners[1][0] = max[0]; corners[1][1] = min[1]; + corners[2][0] = max[0]; corners[2][1] = max[1]; + corners[3][0] = min[0]; corners[3][1] = max[1]; + corners[4][0] = min[0]; corners[4][1] = min[1]; + corners[5][0] = max[0]; corners[5][1] = min[1]; + corners[6][0] = max[0]; corners[6][1] = max[1]; + corners[7][0] = min[0]; corners[7][1] = max[1]; +} + + +} // namespace Mf + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Moof/Rectangle.hh b/src/Moof/Rectangle.hh new file mode 100644 index 0000000..97bb44a --- /dev/null +++ b/src/Moof/Rectangle.hh @@ -0,0 +1,102 @@ + +/******************************************************************************* + + 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_RECTANGLE_HH_ +#define _MOOF_RECTANGLE_HH_ + +#include + + +namespace Mf { + + +/** + * Axis-aligned Bounding Box + */ + +struct Rectangle +{ + Vector2 min; + Vector2 max; + + + Rectangle() {} + + Rectangle(const Vector2& a, const Vector2& b) + { + init(a, b); + } + + Rectangle(Scalar ax, Scalar ay, Scalar bx, Scalar by) + { + Vector2 a(ax, ay); + Vector2 b(bx, by); + + init(a, b); + } + + inline void init(const Vector2& a, const Vector2& b) + { + if (a[0] < b[0]) + { + min[0] = a[0]; + max[0] = b[0]; + } + else + { + min[0] = b[0]; + max[0] = a[0]; + } + if (a[1] < b[1]) + { + min[1] = a[1]; + max[1] = b[1]; + } + else + { + min[1] = b[1]; + max[1] = a[1]; + } + } + + inline Vector2 getCenter() const + { + return Vector2((min[0] + max[0]) / 2.0, + (min[1] + max[1]) / 2.0); + } + + void getCorners(Vector2 corners[4]) const; +}; + + +} // namespace Mf + +#endif // _MOOF_RECTANGLE_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Moof/Resource.cc b/src/Moof/Resource.cc index e21c834..d958c3a 100644 --- a/src/Moof/Resource.cc +++ b/src/Moof/Resource.cc @@ -54,7 +54,7 @@ void Resource::addSearchPath(const std::string& directory) } } -std::string Resource::getPathToResource(const std::string& name) +std::string Resource::getPath(const std::string& name) { std::vector::iterator it; diff --git a/src/Moof/Resource.hh b/src/Moof/Resource.hh index 716e906..f7d1782 100644 --- a/src/Moof/Resource.hh +++ b/src/Moof/Resource.hh @@ -72,7 +72,7 @@ public: * @return The first path found which resolves to a file. */ - static std::string getPathToResource(const std::string& name); + static std::string getPath(const std::string& name); private: static std::vector searchPaths_; diff --git a/src/Moof/RigidBody.hh b/src/Moof/RigidBody.hh new file mode 100644 index 0000000..11c6354 --- /dev/null +++ b/src/Moof/RigidBody.hh @@ -0,0 +1,72 @@ + +/******************************************************************************* + + 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_RIGIDBODY_HH_ +#define _MOOF_RIGIDBODY_HH_ + +#include +#include + + +namespace Mf { + + +/** + * Interface for physical things with mass, momentum, yada yada yada. + */ + +template +class RigidBody +{ +public: + inline virtual ~RigidBody() {} + + virtual void update(Scalar t, Scalar dt) + { + prevState_ = currentState_; + currentState_.integrate(t, dt); + } + + inline T getInterpolatedState(Scalar alpha) const + { + return currentState_.interpolate(alpha, prevState_); + } + +protected: + T prevState_; + T currentState_; +}; + + +} // namespace Mf + +#endif // _MOOF_RIGIDBODY_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + + diff --git a/src/Moof/Scene.cc b/src/Moof/Scene.cc index 6c2b427..5e44221 100644 --- a/src/Moof/Scene.cc +++ b/src/Moof/Scene.cc @@ -36,7 +36,6 @@ #include "Entity.hh" #include "Math.hh" #include "Mippleton.hh" -#include "Octree.hh" #include "OpenGL.hh" #include "Scene.hh" #include "Serializable.hh" @@ -46,7 +45,7 @@ namespace Mf { -class Scene::SceneImpl : public Mippleton +class Scene::Impl : public Mippleton { class Quad : public Entity { @@ -99,6 +98,12 @@ class Scene::SceneImpl : public Mippleton 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(); @@ -108,6 +113,7 @@ class Scene::SceneImpl : public Mippleton glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisable(GL_BLEND); + glDisable(GL_FOG); } bool isVisible(const Camera& cam) const @@ -145,8 +151,8 @@ class Scene::SceneImpl : public Mippleton } public: - SceneImpl(const std::string& name) : - Mippleton(name) + Impl(const std::string& name) : + Mippleton(name) { loadFromFile(); } @@ -380,7 +386,6 @@ public: Quad* quad = new Quad(quadVertices, texture, indices[h][w]); boost::shared_ptr quadPtr(quad); - //objects.push_back(quadPtr); octree->insert(quadPtr); } } @@ -392,39 +397,36 @@ public: std::map rootObj; std::map::iterator it; - if (!root->get(rootObj)) - { - std::cerr << "error loading scene billboard object" << std::endl; - return; - } - Tilemap::Index index = 0; long width = 1; bool blending = false; bool fog = false; - if ((it = rootObj.find("tile")) != rootObj.end()) + if (root->get(rootObj)) { - long value; - if ((*it).second->get(value)) + if ((it = rootObj.find("tile")) != rootObj.end()) { - index = Tilemap::Index(value); + long value; + if ((*it).second->get(value)) + { + index = Tilemap::Index(value); + } } - } - if ((it = rootObj.find("u_scale")) != rootObj.end()) - { - (*it).second->get(width); - } + if ((it = rootObj.find("u_scale")) != rootObj.end()) + { + (*it).second->get(width); + } - if ((it = rootObj.find("blend")) != rootObj.end()) - { - (*it).second->get(blending); - } + if ((it = rootObj.find("blend")) != rootObj.end()) + { + (*it).second->get(blending); + } - if ((it = rootObj.find("fog")) != rootObj.end()) - { - (*it).second->get(fog); + if ((it = rootObj.find("fog")) != rootObj.end()) + { + (*it).second->get(fog); + } } @@ -461,7 +463,6 @@ public: boost::shared_ptr quadPtr(quad); - //objects.push_back(quad_Ptr); octree->insert(quadPtr); } } @@ -469,7 +470,7 @@ public: void loadFromFile() { - std::string filePath = Scene::getPathToResource(getName()); + std::string filePath = Scene::getPath(getName()); Deserializer deserializer(filePath, true); SerializablePtr root = deserializer.deserialize(); @@ -497,67 +498,50 @@ public: return; } - //OctreeNode rootNode(maximumBounds); + // create the tree to store the quads octree = OctreePtr(new Octree(maximumBounds)); if ((it = rootObj.find("instructions")) != rootObj.end()) { loadInstructions((*it).second); } + + octree->sort(); } void draw(Scalar alpha, const Camera& cam) const { - //QuadVector::const_iterator it; - glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); octree->drawIfVisible(alpha, cam); - //int objectsDrawn = 0; + //glDisableClientState(GL_VERTEX_ARRAY); + //glDisableClientState(GL_TEXTURE_COORD_ARRAY); - //for (it = objects.begin(); it != objects.end(); ++it) - //{ - //if ((*it)->isVisible(cam)) - //{ - ////std::cout << "draw object"; - //(*it)->draw(); + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - //objectsDrawn++; - //} - //} + //Texture::resetBind(); + //glColor3f(0.0f, 1.0f, 0.0f); + //playfieldBounds.draw(); + //glColor3f(0.0f, 0.0f, 1.0f); + //maximumBounds.draw(); - //std::cout << objectsDrawn << std::endl; - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - Texture::resetBind(); - glColor3f(0.0f, 1.0f, 0.0f); - playfieldBounds.draw(); - glColor3f(0.0f, 0.0f, 1.0f); - maximumBounds.draw(); - - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } Aabb playfieldBounds; Aabb maximumBounds; - //typedef std::vector< boost::shared_ptr > QuadVector; - //QuadVector objects; OctreePtr octree; }; Scene::Scene(const std::string& name) : // pass through - impl_(Scene::SceneImpl::retain(name), &Scene::SceneImpl::release) {} + impl_(Scene::Impl::retain(name), &Scene::Impl::release) {} void Scene::draw(Scalar alpha, const Camera& cam) const @@ -573,14 +557,20 @@ void Scene::refresh() } +OctreePtr Scene::getOctree() const +{ + // pass through + return impl_->octree; +} + /** * Specialized search location for scene files. They can be found in the * "scenes" subdirectory of any of the searched directories. */ -std::string Scene::getPathToResource(const std::string& name) +std::string Scene::getPath(const std::string& name) { - return Resource::getPathToResource("scenes/" + name + ".json"); + return Resource::getPath("scenes/" + name + ".json"); } diff --git a/src/Moof/Scene.hh b/src/Moof/Scene.hh index 08ab6cc..4c4f297 100644 --- a/src/Moof/Scene.hh +++ b/src/Moof/Scene.hh @@ -34,6 +34,7 @@ #include #include +#include #include @@ -50,11 +51,13 @@ public: void draw(Scalar alpha, const Camera& cam) const; void refresh(); - static std::string getPathToResource(const std::string& name); + OctreePtr getOctree() const; + + static std::string getPath(const std::string& name); private: - class SceneImpl; - boost::shared_ptr impl_; + class Impl; + boost::shared_ptr impl_; }; diff --git a/src/Moof/Sound.cc b/src/Moof/Sound.cc new file mode 100644 index 0000000..9a632eb --- /dev/null +++ b/src/Moof/Sound.cc @@ -0,0 +1,194 @@ + +/******************************************************************************* + + 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 +#include + +#include +#include +#include + +#include "Mippleton.hh" +#include "Sound.hh" + + +namespace Mf { + + +struct Sound::Impl +{ + + static ALenum getAudioFormat(const Sound_AudioInfo& audioInfo) + { + if (audioInfo.format == AUDIO_U8 || audioInfo.format == AUDIO_S8) + { + if (audioInfo.channels == 1) return AL_FORMAT_MONO8; + else return AL_FORMAT_STEREO8; + } + else + { + if (audioInfo.channels == 1) return AL_FORMAT_MONO16; + else return AL_FORMAT_STEREO16; + } + } + + struct Buffer : public Mippleton + { + Buffer(const std::string& name) : + Mippleton(name), + object(0) + {} + + ~Buffer() + { + alDeleteBuffers(1, &object); + } + void loadFromFile(const std::string& filePath, bool stream) + { + if (object != 0) return; + + Sound_Sample* sound = Sound_NewSampleFromFile(filePath.c_str(), + NULL, 8096); + + if (!sound) + { + std::cerr << "could not load sound from file" << std::endl; + exit(1); + } + + unsigned decoded = Sound_DecodeAll(sound); + if (decoded == 0) + { + std::cout << "decoded no bytes" << std::endl; + exit(1); + } + std::cerr << "buffer size: " << sound->buffer_size << std::endl; + std::cerr << "channels: " << (int)sound->actual.channels << std::endl; + std::cerr << "format: " << sound->actual.format << std::endl; + std::cerr << "frequency: " << sound->actual.rate << std::endl; + + alGenBuffers(1, &object); + alBufferData(object, getAudioFormat(sound->actual), sound->buffer, + sound->buffer_size, sound->actual.rate); + + Sound_FreeSample(sound); + } + + ALuint object; + + //ALfloat location[] = {0.0f, 0.0f, 0.0f}; + //ALfloat location2[] = {0.0f, 0.0f, 0.0f}; + //ALfloat orient[] = {0.0f, 0.0f, -1.0f, 0.0, 1.0, 0.0}; + + + //alListenerfv(AL_POSITION, location); + //alListenerfv(AL_VELOCITY, location); + //alListenerfv(AL_VELOCITY, orient); + }; + + Impl(const std::string& name, bool stream = false) : + buffer_(Buffer::retain(name), Buffer::release) + { + if (!stream) buffer_->loadFromFile(Sound::getPath(name), stream); + else buffer_->loadFromFile(SoundStream::getPath(name), stream); + + ALfloat location[] = {0.0f, 0.0f, 0.0f}; + + alGenSources(1, &source_); + alSourcei(source_, AL_BUFFER, buffer_->object); + alSourcef(source_, AL_PITCH, 1.0f); + alSourcef(source_, AL_GAIN, 1.0f); + alSourcefv(source_, AL_POSITION, location); + alSourcefv(source_, AL_VELOCITY, location); + alSourcei(source_, AL_LOOPING, AL_FALSE); + } + + ~Impl() + { + alDeleteSources(1, &source_); + } + + + void update() + { + } + + + boost::shared_ptr buffer_; + ALuint source_; +}; + + +Sound::Sound(const std::string& name) : + // pass through + impl_(new Sound::Impl(name)) {} + + +void Sound::play() +{ + alSourceRewind(impl_->source_); + alSourcePlay(impl_->source_); +} + + +std::string Sound::getPath(const std::string& name) +{ + std::string path = Resource::getPath("sounds/" + name + ".ogg"); + return path; +} + + +//############################################################################## + + +SoundStream::SoundStream(const std::string& name) + // pass through + //impl_(name, true) {} +{ + impl_ = boost::shared_ptr(new Sound::Impl(name, true)); +} + + +void SoundStream::update(Scalar t, Scalar dt) +{ + // pass through + impl_->update(); +} + + +std::string SoundStream::getPath(const std::string& name) +{ + std::string path = Resource::getPath("sounds/" + name + ".xm"); + return path; +} + + +} // namespace Mf + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Moof/Sound.hh b/src/Moof/Sound.hh new file mode 100644 index 0000000..cca7dc7 --- /dev/null +++ b/src/Moof/Sound.hh @@ -0,0 +1,86 @@ + +/******************************************************************************* + + 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_SOUND_HH_ +#define _MOOF_SOUND_HH_ + +/** + * @file Sound.hh + * Image-loading and OpenGL texture loading. + */ + +#include + +#include + +#include +#include + + +namespace Mf { + + +class Sound : public Resource +{ +public: + Sound(const std::string& name); + + void play(); + + static std::string getPath(const std::string& name); + + struct Exception : std::runtime_error + { + explicit Exception(const std::string& what_arg) : + std::runtime_error(what_arg) {} + }; + +protected: + Sound() {} + class Impl; + boost::shared_ptr impl_; +}; + + +class SoundStream : public Sound +{ +public: + SoundStream(const std::string& name); + + void update(Scalar t, Scalar dt); + + static std::string getPath(const std::string& name); +}; + + +} // namespace Mf + +#endif // _MOOF_SOUND_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Moof/State.hh b/src/Moof/State.hh new file mode 100644 index 0000000..8280edf --- /dev/null +++ b/src/Moof/State.hh @@ -0,0 +1,100 @@ + +/******************************************************************************* + + 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_STATE_HH_ +#define _MOOF_STATE_HH_ + +#include + + +namespace Mf { + + +template +struct Derivative +{ + inline virtual ~Derivative() {} + + virtual T operator*(Scalar dt) const = 0; + virtual T operator+(const T& other) const = 0; +}; + + +/** + * Structure containing any information needed to place and orient an animate + * object in 3-space as well as predict future locations and orientations. + */ + +template +struct State +{ + inline virtual ~State() {} + + inline D evaluate(Scalar t) + { + D derivative; + calculateDerivatives(derivative, t); + return derivative; + } + + inline D evaluate(Scalar t, Scalar dt, const D& derivative) + { + T state = *this; + state += derivative * dt; + state.recalculate(); + + D newDerivative; + calculateDerivatives(newDerivative, t); + return newDerivative; + } + + inline void integrate(Scalar t, Scalar dt) + { + D a = evaluate(t); + D b = evaluate(t, dt * 0.5, a); + D c = evaluate(t, dt * 0.5, b); + D d = evaluate(t, dt, c); + + *this += (a + (b + c) * 2.0 + d) * (1.0/6.0) * dt; + } + + virtual void recalculate() {} + + virtual void calculateDerivatives(D& derivative, Scalar t) = 0; + virtual T interpolate(Scalar alpha, const T& prevState) const = 0; + + virtual T& operator+=(const D& derivative) = 0; +}; + + +} // namespace Mf + +#endif // _MOOF_STATE_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Moof/Texture.cc b/src/Moof/Texture.cc index dc9407a..e8f5d86 100644 --- a/src/Moof/Texture.cc +++ b/src/Moof/Texture.cc @@ -51,7 +51,7 @@ namespace Mf { * objects and avoid having duplicate textures loaded to GL. */ -class Texture::TextureImpl : public Mippleton +class Texture::Impl : public Mippleton { /** @@ -129,8 +129,8 @@ public: * Construction is initialization. */ - explicit TextureImpl(const std::string& name) : - Mippleton(name), + explicit Impl(const std::string& name) : + Mippleton(name), surface_(0), width_(0), height_(0), @@ -145,10 +145,10 @@ public: // we want to know when the GL context is recreated Dispatcher::instance().addHandler("video.context_recreated", - boost::bind(&TextureImpl::contextRecreated, this, _1), this); + boost::bind(&Impl::contextRecreated, this, _1), this); } - ~TextureImpl() + ~Impl() { if (surface_) { @@ -239,7 +239,7 @@ public: { SDL_Surface* surface; - surface = IMG_Load(Texture::getPathToResource(getName()).c_str()); + surface = IMG_Load(Texture::getPath(getName()).c_str()); if (!surface) { @@ -383,13 +383,12 @@ public: static GLuint globalObject_; ///< Global GL texture handle. }; -GLuint Texture::TextureImpl::globalObject_ = 0; +GLuint Texture::Impl::globalObject_ = 0; Texture::Texture(const std::string& name) : // pass through - impl_(Texture::TextureImpl::retain(name), &Texture::TextureImpl::release) -{} + impl_(Texture::Impl::retain(name), &Texture::Impl::release) {} /** @@ -417,7 +416,7 @@ GLuint Texture::getObject() const void Texture::resetBind() { glBindTexture(GL_TEXTURE_2D, 0); - TextureImpl::globalObject_ = 0; + Impl::globalObject_ = 0; } @@ -459,10 +458,10 @@ void Texture::setWrapT(GLuint wrap) } -std::string Texture::getPathToResource(const std::string& name) +std::string Texture::getPath(const std::string& name) { - // TODO named texture resources must be png for now - return Resource::getPathToResource("textures/" + name + ".png"); + std::string path = Resource::getPath("textures/" + name + ".png"); + return path; } diff --git a/src/Moof/Texture.hh b/src/Moof/Texture.hh index 9d17eb8..cdb6059 100644 --- a/src/Moof/Texture.hh +++ b/src/Moof/Texture.hh @@ -63,7 +63,7 @@ public: void setWrapS(GLuint wrap); void setWrapT(GLuint wrap); - static std::string getPathToResource(const std::string& name); + static std::string getPath(const std::string& name); struct Exception : std::runtime_error { @@ -72,8 +72,8 @@ public: }; private: - class TextureImpl; - boost::shared_ptr impl_; + class Impl; + boost::shared_ptr impl_; }; diff --git a/src/Moof/Tilemap.cc b/src/Moof/Tilemap.cc index 9f24b1b..17642c7 100644 --- a/src/Moof/Tilemap.cc +++ b/src/Moof/Tilemap.cc @@ -36,7 +36,7 @@ namespace Mf { -class Tilemap::TilemapImpl : public Mippleton +class Tilemap::Impl : public Mippleton { static GLint filterFromString(const std::string& filter) { @@ -75,8 +75,8 @@ class Tilemap::TilemapImpl : public Mippleton } public: - TilemapImpl(const std::string& name) : - Mippleton(name), + Impl(const std::string& name) : + Mippleton(name), magFilter_(GL_NEAREST), minFilter_(GL_NEAREST), nTilesS_(1), @@ -89,7 +89,7 @@ public: void loadFromFile() { - Deserializer deserializer(Tilemap::getPathToResource(getName())); + Deserializer deserializer(Tilemap::getPath(getName())); SerializablePtr root = deserializer.deserialize(); @@ -164,10 +164,8 @@ public: Tilemap::Tilemap(const std::string& name) : Texture(name), - impl_(Tilemap::TilemapImpl::retain(name), &Tilemap::TilemapImpl::release) + impl_(Tilemap::Impl::retain(name), &Tilemap::Impl::release) { - bind(); - setMinFilter(impl_->minFilter_); setMagFilter(impl_->magFilter_); setWrapS(impl_->wrapS_); @@ -225,9 +223,9 @@ bool Tilemap::getTileCoords(unsigned index, Scalar coords[8], } -std::string Tilemap::getPathToResource(const std::string& name) +std::string Tilemap::getPath(const std::string& name) { - return Resource::getPathToResource("tilemaps/" + name + ".json"); + return Resource::getPath("tilemaps/" + name + ".json"); } diff --git a/src/Moof/Tilemap.hh b/src/Moof/Tilemap.hh index 80bede9..942a5e9 100644 --- a/src/Moof/Tilemap.hh +++ b/src/Moof/Tilemap.hh @@ -97,11 +97,11 @@ public: bool getTileCoords(Index index, Scalar coords[8], Orientation what) const; - static std::string getPathToResource(const std::string& name); + static std::string getPath(const std::string& name); private: - class TilemapImpl; - boost::shared_ptr impl_; + class Impl; + boost::shared_ptr impl_; }; diff --git a/src/YoinkApp.cc b/src/YoinkApp.cc index 493e615..a1c2dbb 100644 --- a/src/YoinkApp.cc +++ b/src/YoinkApp.cc @@ -40,6 +40,10 @@ #include "YoinkApp.hh" +#include +#include +#include + #if HAVE_CONFIG_H #include "config.h" #endif @@ -94,42 +98,45 @@ static std::string iconFile() // then look in the configured data directory Mf::Resource::addSearchPath(YOINK_DATADIR); - return Mf::Resource::getPathToResource("yoink.png"); + return Mf::Resource::getPath("yoink.png"); } YoinkApp::YoinkApp(int argc, char* argv[]) : - Mf::Engine(argc, argv, configFiles(), PACKAGE_STRING, iconFile()) + Mf::Engine(argc, argv, configFiles(), PACKAGE_STRING, iconFile()), + music("NightFusion"), + punchSound("RobotPunch") { Mf::Dispatcher::instance().addHandler("video.context_recreated", boost::bind(&YoinkApp::contextRecreated, this, _1), this); setupGL(); + music.play(); + state = 0.0; - someChar = new Character("RobotTrooper"); - someChar->getAnimation().startSequence("Run"); + heroine = CharacterPtr(new Character("RobotTrooper")); + heroine->getAnimation().startSequence("Run"); font = new TilemapFont; - Mf::Vector2 coeffs[4]; - coeffs[0] = Mf::Vector2(0.0, 0.0); - coeffs[1] = Mf::Vector2(0.5, 0.0); - coeffs[2] = Mf::Vector2(0.5, 0.0); - coeffs[3] = Mf::Vector2(1.0, 0.0); + Mf::Scalar coeffs[4]; + coeffs[0] = 0.0; + coeffs[1] = 1.5; + coeffs[2] = -0.5; + coeffs[3] = 1.0; interp.init(coeffs, 1.0, Mf::Interpolator::OSCILLATE); Mf::Scalar coeff[2] = {1.0, 0.0}; - fadeIn.init(coeff, 0.5f); + fadeIn.init(coeff, 0.1); testScene = new Mf::Scene("Test"); - - x = y = z = 0.0; + heroine->treeNode = testScene->getOctree()->insert(heroine); } YoinkApp::~YoinkApp() { - delete someChar; + //delete heroine; delete font; delete testScene; @@ -185,8 +192,15 @@ void YoinkApp::update(Mf::Scalar t, Mf::Scalar dt) camera.update(t, dt); - someChar->getAnimation().update(t, dt); + heroine->update(t, dt); + heroine->treeNode = testScene->getOctree()->reinsert(heroine, heroine->treeNode); + + //camera.lookAt(heroine->getSphere().point); + camera.setPosition(Mf::Vector3(-heroine->current.position[0], -heroine->current.position[1], -256)); + interp.update(dt); + hud.setBar1Progress(interp.getValue()); + hud.setBar2Progress(1.0 - interp.getValue()); prevstate = state; state += dt; @@ -206,19 +220,50 @@ void YoinkApp::draw(Mf::Scalar alpha) //Mf::Scalar cosstate = std::cos(drawstate); - glMatrixMode(GL_MODELVIEW); //glLoadIdentity(); - glBindTexture(GL_TEXTURE_2D, 0); //glRotatef(drawstate*15.0f, 0.0, 1.0, 0.0); //glTranslatef(x, y, z); glLoadMatrix(camera.getModelviewMatrix().data()); // DRAW THE SCENE + Mf::Texture::resetBind(); testScene->draw(alpha, camera); + + //heroine->draw(alpha); + + + hud.draw(); + + + 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); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + /* glLoadIdentity(); @@ -350,9 +395,10 @@ void YoinkApp::handleEvent(const Mf::Event& event) { getVideo().toggleFull(); } - else if (event.key.keysym.sym == SDLK_a) + else if (event.key.keysym.sym == SDLK_SPACE) { - someChar->getAnimation().startSequence("Punch"); + heroine->getAnimation().startSequence("Punch"); + punchSound.play(); } else if (event.key.keysym.sym == SDLK_r) { @@ -363,30 +409,9 @@ void YoinkApp::handleEvent(const Mf::Event& event) getVideo().toggleCursorGrab(); getVideo().toggleCursorVisible(); } - //else if (event.key.keysym.sym == SDLK_RIGHT) - //{ - //x -= 50.0; - //} - //else if (event.key.keysym.sym == SDLK_LEFT) - //{ - //x += 50.0; - //} - //else if (event.key.keysym.sym == SDLK_UP) - //{ - //y -= 50.0; - //} - //else if (event.key.keysym.sym == SDLK_DOWN) - //{ - //y += 50.0; - //} - //else if (event.key.keysym.sym == SDLK_PAGEUP) - //{ - //z += 50.0; - //} - //else if (event.key.keysym.sym == SDLK_PAGEDOWN) - //{ - //z -= 50.0; - //} + + case SDL_KEYUP: + heroine->handleEvent(event); case SDL_MOUSEMOTION: case SDL_MOUSEBUTTONDOWN: @@ -399,6 +424,7 @@ void YoinkApp::handleEvent(const Mf::Event& event) case SDL_VIDEORESIZE: glViewport(0, 0, event.resize.w, event.resize.h); + hud.resize(event.resize.w, event.resize.h); camera.setProjection(cml::rad(60.0), double(event.resize.w / event.resize.h), 32.0, 2500.0); camera.uploadProjectionToGL(); break; @@ -411,7 +437,7 @@ int main(int argc, char* argv[]) { std::cout << PACKAGE_STRING << std::endl << "Compiled " << __TIME__ " " __DATE__ << std::endl - << "Send requests, patches, and bug reports to <" + << "Send patches and bug reports to <" PACKAGE_BUGREPORT << ">." << std::endl << std::endl; int status = 0; diff --git a/src/YoinkApp.hh b/src/YoinkApp.hh index 66406d2..1613707 100644 --- a/src/YoinkApp.hh +++ b/src/YoinkApp.hh @@ -47,6 +47,10 @@ #include "Character.hh" #include "TilemapFont.hh" +#include + +#include "Hud.hh" + class YoinkApp : public Mf::Engine { @@ -65,19 +69,22 @@ private: void setupGL(); void contextRecreated(const Mf::Notification& note); - Character* someChar; + Mf::SoundStream music; + + CharacterPtr heroine; + Mf::Sound punchSound; TilemapFont *font; - Mf::Cerpv2 interp; + Mf::Cerps interp; Mf::Lerps fadeIn; Mf::Camera camera; Mf::Scene* testScene; - Mf::Scalar x, y, z; - Mf::Scalar state; Mf::Scalar prevstate; + + Hud hud; };