From: Charles McGarvey Date: Sun, 13 Dec 2009 18:24:55 +0000 (-0700) Subject: ray-scene intersection X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=commitdiff_plain;h=7e84479de612a4ce287c6f63deb014b447a993ec ray-scene intersection --- diff --git a/data/scenes/Classic.lua b/data/scenes/Classic.lua index 68b7b66..e8ba272 100644 --- a/data/scenes/Classic.lua +++ b/data/scenes/Classic.lua @@ -197,9 +197,11 @@ DrawTilemap({ 18, 18, 18}) -- Cheaty invisible platform +-- This draws nothing but creates a platform on the roof for walking. ResetTransform() -Translate(10, 4, 3) +Rotate(X, 90) +Translate(10, 5, 0) DrawTilemap({ width = 3, surface = TOP, @@ -811,7 +813,7 @@ end function GetZCoord(x, y) - return 3 + return 3.00001 end @@ -892,3 +894,6 @@ function RandomSkillLevel() return "dumb" end + +-- vim: tw=80 ts=4 + diff --git a/src/GameLayer.cc b/src/GameLayer.cc index 41000f3..1e60758 100644 --- a/src/GameLayer.cc +++ b/src/GameLayer.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "GameLayer.hh" @@ -92,7 +93,16 @@ void GameLayer::advanceScene() { mState.scene = Scene::alloc(mState.sceneList[0]); mState.sceneList.erase(mState.sceneList.begin()); - mState.scene->load(mState.script); + + Mf::Script::Status status = mState.scene->load(mState.script); + if (status != Mf::Script::SUCCESS) + { + std::string str; + mState.script[-1].get(str); + + Mf::logScript("%s", str.c_str()); + throw Mf::Exception(Mf::ErrorCode::SCRIPT_ERROR, str); + } } } @@ -103,7 +113,10 @@ GameLayer::GameLayer() : { mMusic.setLooping(true); mMusic.enqueue("NightFusionLoop"); - mMusic.stream(); + + bool isMute = false; + Mf::Settings::getInstance().get("nomusic", isMute); + if (!isMute) mMusic.play(); loadSceneLoader(); advanceScene(); // load the first scene @@ -123,6 +136,7 @@ void GameLayer::pushed(Mf::Engine& engine) engine.push(Hud::alloc(mState)); mRay.direction.set(1.0, 0.0); + mRay3.direction.set(1.0, 0.0, 0.0); mLine.a.set(20, 10); mLine.b.set(19, 14); @@ -150,8 +164,11 @@ void GameLayer::update(Mf::Engine& engine, Mf::Scalar t, Mf::Scalar dt) //Mf::Sound::setListenerPosition(heroinePosition); mRay.point = mState.heroine->getState().position; + mRay3.point = Mf::promote(mRay.point); + mRay3.direction = Mf::promote(mRay.direction); Mf::Ray<2>::Intersection meh; + Mf::Ray<3>::Intersection meh3; Mf::Scalar d = mLine.intersectRay(mRay, meh); if (d > 0.0) @@ -160,12 +177,12 @@ void GameLayer::update(Mf::Engine& engine, Mf::Scalar t, Mf::Scalar dt) Mf::logDebug(" P = <%f,%f>", meh.point[0], meh.point[1]); Mf::logDebug(" n = <%f,%f>", meh.normal[0], meh.normal[1]); } - //d = mPlane.intersectRay(mRay, meh); + //d = mPlane.intersectRay(mRay3, meh3); //if (d > 0.0) //{ //Mf::logDebug("plane: d = %f", d); - //Mf::logDebug(" P = <%f,%f>", meh.point[0], meh.point[1]); - //Mf::logDebug(" n = <%f,%f>", meh.normal[0], meh.normal[1]); + //Mf::logDebug(" P = <%f,%f>", meh3.point[0], meh3.point[1]); + //Mf::logDebug(" n = <%f,%f>", meh3.normal[0], meh3.normal[1]); //} d = mSphere.intersectRay(mRay, meh); if (d > 0.0) @@ -174,6 +191,14 @@ void GameLayer::update(Mf::Engine& engine, Mf::Scalar t, Mf::Scalar dt) Mf::logDebug(" P = <%f,%f>", meh.point[0], meh.point[1]); Mf::logDebug(" n = <%f,%f>", meh.normal[0], meh.normal[1]); } + + std::list::Intersection> hits; + if (mState.scene->castRay(mRay, hits)) + { + Mf::logDebug("scene: d = %f", d); + Mf::logDebug(" P = <%f,%f>", hits.front().point[0], hits.front().point[1]); + Mf::logDebug(" n = <%f,%f>", hits.front().normal[0], hits.front().normal[1]); + } } diff --git a/src/GameLayer.hh b/src/GameLayer.hh index f966c70..4692611 100644 --- a/src/GameLayer.hh +++ b/src/GameLayer.hh @@ -102,13 +102,14 @@ private: void setProjection(); void setProjection(Mf::Scalar width, Mf::Scalar height); - State mState; - Mf::Sound mMusic; - Mf::Sound mPunchSound; - - Mf::Ray<2> mRay; - Mf::Line<2> mLine; - Mf::Plane mPlane; + State mState; + Mf::SoundStream mMusic; + Mf::Sound mPunchSound; + + Mf::Ray<2> mRay; + Mf::Ray<3> mRay3; + Mf::Line<2> mLine; + Mf::Plane mPlane; Mf::Sphere<2> mSphere; }; diff --git a/src/Moof/Line.hh b/src/Moof/Line.hh index 4a54e2d..33eecb9 100644 --- a/src/Moof/Line.hh +++ b/src/Moof/Line.hh @@ -49,7 +49,15 @@ struct Line : public Drawable, public Shape Vector a; Vector b; - Scalar intersectRay(const Ray<2>& ray, Ray<2>::Intersection& intersection) + + Line() {} + + Line(const Vector& point1, const Vector& point2) : + a(point1), + b(point2) {} + + Scalar intersectRay(const Ray<2>& ray, + Ray<2>::Intersection& intersection) const { // solve: Cx + r*Dx = Ax + s(Bx - Ax) // Cy + r*Dy = Ay + s(By - Ay) diff --git a/src/Moof/Math.hh b/src/Moof/Math.hh index ae747ec..05aa9ec 100644 --- a/src/Moof/Math.hh +++ b/src/Moof/Math.hh @@ -91,12 +91,12 @@ inline Vector2 demote(const Vector3& vec) return Vector2(vec[0], vec[1]); } -inline Vector4 promote(const Vector3& vec, Scalar extra = 1.0) +inline Vector4 promote(const Vector3& vec, Scalar extra = 0.0) { return Vector4(vec[0], vec[1], vec[2], extra); } -inline Vector3 promote(const Vector2& vec, Scalar extra = 1.0) +inline Vector3 promote(const Vector2& vec, Scalar extra = 0.0) { return Vector3(vec[0], vec[1], extra); } diff --git a/src/Moof/Plane.hh b/src/Moof/Plane.hh index 5ec59ea..11cd63e 100644 --- a/src/Moof/Plane.hh +++ b/src/Moof/Plane.hh @@ -79,7 +79,8 @@ struct Plane : public Shape<3> { // the ray lies on the plane intersection.point = ray.point; - intersection.normal = normal; + intersection.normal.set(0.0, 0.0, 0.0); + //intersection.normal = normal; return SCALAR(0.0); } @@ -87,11 +88,14 @@ struct Plane : public Shape<3> return SCALAR(-1.0); } - Scalar t = (cml::dot(ray.point, normal) + d) / denominator; + Scalar distance = cml::dot(ray.point, normal) + d; + Scalar t = -distance / denominator; if (t > SCALAR(0.0)) { ray.solve(intersection.point, t); - intersection.normal = normal; + + if (distance >= 0.0) intersection.normal = normal; + else intersection.normal = -normal; } return t; diff --git a/src/Moof/Script.hh b/src/Moof/Script.hh index 2f285ce..f67c62c 100644 --- a/src/Moof/Script.hh +++ b/src/Moof/Script.hh @@ -125,7 +125,7 @@ public: */ Value(lua_State* s = 0, int i = 0) : index(i), - state(s) {} + mState(s) {} /** * A copied value presently points to the same value, except the real @@ -136,22 +136,22 @@ public: Value(const Value& copy) : index(copy.getRealIndex()), - state(copy.state) {} + mState(copy.mState) {} // check the type of the value - bool isBoolean() const { return (bool)lua_isboolean(state, index); } - bool isFunction() const { return (bool)lua_isfunction(state, index); } - bool isNil() const { return (bool)lua_isnil(state, index); } - bool isNone() const { return (bool)lua_isnone(state, index); } - bool isValid() const { return state != 0 && !isNone(); } - bool isNoneOrNil() const { return (bool)lua_isnoneornil(state, index); } - bool isNumber() const { return (bool)lua_isnumber(state, index); } - bool isString() const { return (bool)lua_isstring(state, index); } - bool isTable() const { return (bool)lua_istable(state, index); } - bool isThread() const { return (bool)lua_isthread(state, index); } - bool isData() const { return (bool)lua_isuserdata(state, index); } - bool isLightData() const { return (bool)lua_islightuserdata(state, index); } + bool isBoolean() const { return (bool)lua_isboolean(mState, index); } + bool isFunction() const { return (bool)lua_isfunction(mState, index); } + bool isNil() const { return (bool)lua_isnil(mState, index); } + bool isNone() const { return (bool)lua_isnone(mState, index); } + bool isValid() const { return mState != 0 && !isNone(); } + bool isNoneOrNil() const { return (bool)lua_isnoneornil(mState, index); } + bool isNumber() const { return (bool)lua_isnumber(mState, index); } + bool isString() const { return (bool)lua_isstring(mState, index); } + bool isTable() const { return (bool)lua_istable(mState, index); } + bool isThread() const { return (bool)lua_isthread(mState, index); } + bool isData() const { return (bool)lua_isuserdata(mState, index); } + bool isLightData() const { return (bool)lua_islightuserdata(mState, index); } /** * Check the value and throw an error if its the wrong type. There's a @@ -170,54 +170,54 @@ public: { if (type != getType()) { - luaL_typerror(state, index, lua_typename(state, type)); + luaL_typerror(mState, index, lua_typename(mState, type)); } } void throwError(const char* error) { - luaL_argerror(state, index, error); + luaL_argerror(mState, index, error); } Value& requireBoolean() { - if (!isBoolean()) luaL_typerror(state, index, "boolean"); + if (!isBoolean()) luaL_typerror(mState, index, "boolean"); return *this; } Value& requireNumber() { - if (!isNumber()) luaL_typerror(state, index, "number"); + if (!isNumber()) luaL_typerror(mState, index, "number"); return *this; } Value& requireString() { - if (!isString()) luaL_typerror(state, index, "string"); + if (!isString()) luaL_typerror(mState, index, "string"); return *this; } Value& requireTable() { - if (!isTable()) luaL_typerror(state, index, "table"); + if (!isTable()) luaL_typerror(mState, index, "table"); return *this; } Value& requireFunction() { - if (!isFunction()) luaL_typerror(state, index, "function"); + if (!isFunction()) luaL_typerror(mState, index, "function"); return *this; } Value& requireData() { - if (!isData()) luaL_typerror(state, index, "data"); + if (!isData()) luaL_typerror(mState, index, "data"); return *this; } Value& requireNil() { - if (!isNil()) luaL_typerror(state, index, "nil"); + if (!isNil()) luaL_typerror(mState, index, "nil"); return *this; } Value& requireThread() { - if (!isThread()) luaL_typerror(state, index, "thread"); + if (!isThread()) luaL_typerror(mState, index, "thread"); return *this; } @@ -228,7 +228,7 @@ public: Type getType() const { - return (Type)lua_type(state, index); + return (Type)lua_type(mState, index); } /** @@ -237,7 +237,7 @@ public: std::string getTypeName() const { - return std::string(luaL_typename(state, index)); + return std::string(luaL_typename(mState, index)); } @@ -247,12 +247,12 @@ public: size_t getLength() const { - return lua_objlen(state, index); + return lua_objlen(mState, index); } int getRealIndex() const { - if (index < 0) return lua_gettop(state) + 1 + index; + if (index < 0) return lua_gettop(mState) + 1 + index; else return index; } @@ -263,13 +263,13 @@ public: const void* getIdentifier() const { - return lua_topointer(state, index); + return lua_topointer(mState, index); } bool operator == (const Value& rhs) const { - return (bool)lua_equal(state, index, rhs.index); + return (bool)lua_equal(mState, index, rhs.index); } bool operator != (const Value& rhs) const { @@ -277,7 +277,7 @@ public: } bool operator < (const Value& rhs) const { - return (bool)lua_lessthan(state, index, rhs.index); + return (bool)lua_lessthan(mState, index, rhs.index); } bool operator <= (const Value& rhs) const { @@ -293,7 +293,7 @@ public: } operator bool () const { - return (bool)lua_toboolean(state, index); + return (bool)lua_toboolean(mState, index); } Value& operator = (const Value& rhs) @@ -313,7 +313,7 @@ public: { if (isNumber()) { - value = (T)lua_tointeger(state, index); + value = (T)lua_tointeger(mState, index); return true; } return false; @@ -323,7 +323,7 @@ public: { if (isNumber()) { - value = (float)lua_tonumber(state, index); + value = (float)lua_tonumber(mState, index); return true; } return false; @@ -332,7 +332,7 @@ public: { if (isNumber()) { - value = (double)lua_tonumber(state, index); + value = (double)lua_tonumber(mState, index); return true; } return false; @@ -342,7 +342,7 @@ public: { if (isBoolean()) { - value = (bool)lua_toboolean(state, index); + value = (bool)lua_toboolean(mState, index); return true; } return false; @@ -353,7 +353,7 @@ public: if (isString()) { size_t size; - const char* str = lua_tolstring(state, index, &size); + const char* str = lua_tolstring(mState, index, &size); value.assign(str, size); return true; } @@ -367,19 +367,19 @@ public: array.clear(); - Value value(state, -1); + Value value(mState, -1); int realIndex = getRealIndex(); bool done = false; for (int i = 1; !done; ++i) { - lua_rawgeti(state, realIndex, i); + lua_rawgeti(mState, realIndex, i); T v; if (value.get(v)) array.push_back(v); else done = true; - lua_pop(state, 1); + lua_pop(mState, 1); } return true; @@ -392,12 +392,12 @@ public: dictionary.clear(); - Value key(state, -2); - Value value(state, -1); + Value key(mState, -2); + Value value(mState, -1); int realIndex = getRealIndex(); - lua_pushnil(state); - while (lua_next(state, realIndex) != 0) + lua_pushnil(mState); + while (lua_next(mState, realIndex) != 0) { std::string k; if (!key.isNumber() && key.get(k)) @@ -405,9 +405,9 @@ public: T v; if (value.get(v)) dictionary[k] = v; } - lua_pop(state, 1); + lua_pop(mState, 1); } - lua_pop(state, 1); + lua_pop(mState, 1); return true; } @@ -420,7 +420,7 @@ public: void pushCopy() const { - lua_pushvalue(state, index); + lua_pushvalue(mState, index); } /** @@ -429,12 +429,12 @@ public: void replaceWithTop() { - lua_replace(state, index); + lua_replace(mState, index); } void remove() { - lua_remove(state, index); + lua_remove(mState, index); } /** @@ -444,29 +444,35 @@ public: void insertTopHere() { - lua_insert(state, index); + lua_insert(mState, index); } void pushMetatable() const { - lua_getmetatable(state, index); + lua_getmetatable(mState, index); } void pushField() const { - lua_gettable(state, index); + lua_gettable(mState, index); } void pushField(const std::string& name) const { - lua_getfield(state, index, name.c_str()); + lua_getfield(mState, index, name.c_str()); + } + + void pushField(size_t index) const + { + lua_pushinteger(mState, lua_Integer(index)); + pushField(); } private: - lua_State* state; + lua_State* mState; }; diff --git a/src/Moof/Shape.hh b/src/Moof/Shape.hh index b78eaad..c67a779 100644 --- a/src/Moof/Shape.hh +++ b/src/Moof/Shape.hh @@ -58,6 +58,9 @@ namespace Mf { template class Shape { +public: + + virtual ~Shape() {} /** * Checks if this shape is intersected by a given ray. If so, returns the * distance from the start of the ray to the shape and information about the diff --git a/src/Moof/Sound.cc b/src/Moof/Sound.cc index 4275ea4..3aec3f6 100644 --- a/src/Moof/Sound.cc +++ b/src/Moof/Sound.cc @@ -28,8 +28,8 @@ #include #include +#include #include -#include #include #include @@ -209,17 +209,19 @@ public: // make sure the engine is initialized Engine::getInstance(); - ALfloat zero[] = {0.0f, 0.0f, 0.0f}; - + mIsLoaded = false; + mIsPlaying = false; + mIsLooping = false; + alGenSources(1, &mSource); + ALfloat zero[] = {0.0f, 0.0f, 0.0f}; alSourcef(mSource, AL_PITCH, 1.0f); alSourcef(mSource, AL_GAIN, 1.0f); alSourcefv(mSource, AL_POSITION, zero); alSourcefv(mSource, AL_VELOCITY, zero); - mIsPlaying = false; - mIsLooping = false; + alSourcei(mSource, AL_LOOPING, mIsLooping); } ~Impl() @@ -228,10 +230,10 @@ public: alDeleteSources(1, &mSource); - while (!mBufferObjects.empty()) + while (!mBuffers.empty()) { - alDeleteBuffers(1, &mBufferObjects.back()); - mBufferObjects.pop_back(); + alDeleteBuffers(1, &mBuffers.back()); + mBuffers.pop_back(); } } @@ -240,49 +242,50 @@ public: { if (mQueue.empty()) return; - ALenum type; - alGetSourcei(mSource, AL_SOURCE_TYPE, &type); - - if (type != AL_STATIC) - { - mQueue.front()->loadAll(mSource); - } + if (!mIsLoaded) mQueue.front()->loadAll(mSource); - alSourcei(mSource, AL_LOOPING, mIsLooping); alSourcePlay(mSource); - mIsPlaying = true; + mIsLoaded = true; } - void stream() + void playStream() { - stop(); + if (mQueue.empty()) return; - alSourcei(mSource, AL_BUFFER, AL_NONE); - mQueue.front()->rewind(); - beginStream(); + if (!mIsPlaying) + { + alSourcei(mSource, AL_LOOPING, false); + bufferStream(); + } + + if (!mStreamTimer.isValid()) + { + mStreamTimer.init(boost::bind(&Impl::streamUpdate, this, _1, _2), + 1.0, Timer::REPEAT); + } - alSourcei(mSource, AL_LOOPING, AL_FALSE); alSourcePlay(mSource); mIsPlaying = true; - - mStreamTimer.init(boost::bind(&Impl::streamUpdate, this, _1, _2), 1.0, - Timer::REPEAT); } - void beginStream() + void bufferStream() { ALuint buffer; - for (int i = mBufferObjects.size(); i < 8; ++i) + for (int i = mBuffers.size(); i <= 8; ++i) { alGenBuffers(1, &buffer); - mBufferObjects.push_back(buffer); - } - for (int i = 0; i < 8; ++i) - { - buffer = mBufferObjects[i]; - mQueue.front()->stream(buffer); - alSourceQueueBuffers(mSource, 1, &buffer); + + if (mQueue.front()->stream(buffer)) + { + alSourceQueueBuffers(mSource, 1, &buffer); + mBuffers.push_back(buffer); + } + else + { + alDeleteBuffers(1, &buffer); + break; + } } } @@ -317,6 +320,9 @@ public: mQueue.front()->stream(bufferObj); alSourceQueueBuffers(mSource, 1, &bufferObj); logInfo("loading new buffer"); + + // queue up any unused buffers + bufferStream(); } else if (mIsLooping) { @@ -327,6 +333,12 @@ public: alSourceQueueBuffers(mSource, 1, &bufferObj); logInfo("looping same buffer"); } + else + { + // nothing more to play, stopping... + mIsPlaying = false; + std::remove(mBuffers.begin(), mBuffers.end(), bufferObj); + } } } @@ -358,38 +370,21 @@ public: mStreamTimer.invalidate(); } - void resume() - { - alSourcePlay(mSource); - mIsPlaying = true; - - ALenum type; - alGetSourcei(mSource, AL_SOURCE_TYPE, &type); - - if (type == AL_STREAMING) - { - mStreamTimer.init(boost::bind(&Impl::streamUpdate, this, _1, _2), - 1.0, Timer::REPEAT); - } - } - void setSample(const std::string& name) { - bool playing = isPlaying(); - ALenum type; - alGetSourcei(mSource, AL_SOURCE_TYPE, &type); - stop(); + alSourcei(mSource, AL_BUFFER, AL_NONE); + mQueue.clear(); + mIsLoaded = false; - //alSourcei(mSource, AL_BUFFER, AL_NONE); enqueue(name); - if (playing) + while (!mBuffers.empty()) { - if (type == AL_STREAMING) stream(); - else play(); + alDeleteBuffers(1, &mBuffers.back()); + mBuffers.pop_back(); } } @@ -435,8 +430,9 @@ public: ALuint mSource; - std::vector mBufferObjects; + std::list mBuffers; + bool mIsLoaded; bool mIsPlaying; bool mIsLooping; @@ -455,19 +451,19 @@ Sound::Sound(const std::string& name) : mImpl(new Sound::Impl(name)) {} -void Sound::play() +void Sound::setSample(const std::string& name) { // pass through - mImpl->play(); + mImpl->setSample(name); } -void Sound::stream() + +void Sound::play() { // pass through - mImpl->stream(); + mImpl->play(); } - void Sound::stop() { // pass through @@ -480,48 +476,30 @@ void Sound::pause() mImpl->pause(); } -void Sound::resume() -{ - // pass through - mImpl->resume(); -} void Sound::toggle() { - if (mImpl->mIsPlaying) pause(); - else resume(); + if (isPlaying()) pause(); + else play(); } - -void Sound::setSample(const std::string& name) -{ - // pass through - mImpl->setSample(name); -} - -void Sound::enqueue(const std::string& name) -{ - // pass through - mImpl->enqueue(name); -} - - bool Sound::isPlaying() const { // pass through return mImpl->isPlaying(); } + void Sound::setPosition(const Vector3& position) { - float p[3] = {position[0], position[1], position[2]}; - alSourcefv(mImpl->mSource, AL_POSITION, p); + float vec[3] = {position[0], position[1], position[2]}; + alSourcefv(mImpl->mSource, AL_POSITION, vec); } void Sound::setVelocity(const Vector3& velocity) { - float v[3] = {velocity[0], velocity[1], velocity[2]}; - alSourcefv(mImpl->mSource, AL_VELOCITY, v); + float vec[3] = {velocity[0], velocity[1], velocity[2]}; + alSourcefv(mImpl->mSource, AL_VELOCITY, vec); } void Sound::setGain(Scalar gain) @@ -543,14 +521,18 @@ void Sound::setLooping(bool looping) void Sound::setListenerPosition(const Vector3& position) { - alListener3f(AL_POSITION, float(position[0]), float(position[1]), - float(position[2])); + //alListener3f(AL_POSITION, float(position[0]), float(position[1]), + //float(position[2])); + float vec[] = {position[0], position[1], position[2]}; + alListenerfv(AL_POSITION, vec); } void Sound::setListenerVelocity(const Vector3& velocity) { - alListener3f(AL_VELOCITY, float(velocity[0]), float(velocity[1]), - float(velocity[2])); + //alListener3f(AL_VELOCITY, float(velocity[0]), float(velocity[1]), + //float(velocity[2])); + float vec[] = {velocity[0], velocity[1], velocity[2]}; + alListenerfv(AL_VELOCITY, vec); } void Sound::setListenerOrientation(const Vector3& forward, const Vector3& up) @@ -573,6 +555,23 @@ std::string Sound::getPath(const std::string& name) } +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +void SoundStream::enqueue(const std::string& name) +{ + // pass through + mImpl->enqueue(name); +} + + +void SoundStream::play() +{ + // pass through + mImpl->playStream(); +} + + } // namespace Mf /** vim: set ts=4 sw=4 tw=80: *************************************************/ diff --git a/src/Moof/Sound.hh b/src/Moof/Sound.hh index 982e9b4..6e5f78a 100644 --- a/src/Moof/Sound.hh +++ b/src/Moof/Sound.hh @@ -47,6 +47,9 @@ namespace Mf { class Sound; typedef boost::shared_ptr SoundP; +class SoundStream; +typedef boost::shared_ptr SoundStreamP; + class Sound : public Resource { @@ -60,20 +63,16 @@ public: Sound(); explicit Sound(const std::string& name); + virtual ~Sound() {} - void play(); - void stream(); - - // TODO this API sucks... refactor me!! + // this implicitly stops the sound if it is playing + void setSample(const std::string& name); + virtual void play(); void stop(); void pause(); - void resume(); - void toggle(); - - void setSample(const std::string& name); - void enqueue(const std::string& name); + void toggle(); bool isPlaying() const; void setPosition(const Vector3& position); @@ -89,13 +88,32 @@ public: static std::string getPath(const std::string& name); -private: +protected: class Impl; boost::shared_ptr mImpl; }; +class SoundStream : public Sound +{ +public: + + static SoundStreamP alloc(const std::string& name) + { + return SoundStreamP(new SoundStream(name)); + } + + SoundStream(); + explicit SoundStream(const std::string& name) : + Sound(name) {} + + void enqueue(const std::string& name); + + void play(); +}; + + } // namespace Mf #endif // _MOOF_SOUND_HH_ diff --git a/src/Scene.cc b/src/Scene.cc index 452cc13..fce4517 100644 --- a/src/Scene.cc +++ b/src/Scene.cc @@ -27,7 +27,6 @@ *******************************************************************************/ #include -#include #include #include @@ -50,7 +49,7 @@ struct Scene::Impl : public Mf::Library { struct Quad : public Mf::Entity { - enum SURFACE + enum Surface { NONE = 0, LEFT = 1, @@ -58,19 +57,20 @@ struct Scene::Impl : public Mf::Library TOP = 3 }; - Quad(const Mf::Vector3 vertices[4], const std::string& texture, + Quad(const Mf::Vector3* vertices[4], const std::string& texture, Tilemap::Index tileIndex) : mTilemap(texture), mBlending(false), mFog(false), mSurface(NONE) { - for (int i = 0, num = 0; i < 4; ++i) + for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 3; ++j, ++num) - { - mVertices[num] = vertices[i][j]; - } + mVertices[i] = *vertices[i]; + //for (int j = 0; j < 3; ++j, ++num) + //{ + //mVertices[num] = (*vertices[i])[j]; + //} } if (!mTilemap.getTileCoords(tileIndex, mTexCoords)) @@ -84,7 +84,7 @@ struct Scene::Impl : public Mf::Library mTexCoords[5] = mTexCoords[7] = 1.0; } - mAabb.encloseVertices(vertices, 4); + mAabb.encloseVertices(mVertices, 4); mSphere.point = mAabb.getCenter(); mSphere.radius = (mAabb.min - mSphere.point).length(); } @@ -99,12 +99,12 @@ struct Scene::Impl : public Mf::Library mFog = fog; } - void setSurface(SURFACE type) + void setSurface(Surface type) { mSurface = type; } - SURFACE getSurface() const + Surface getSurface() const { return mSurface; } @@ -126,7 +126,7 @@ struct Scene::Impl : public Mf::Library //glColor4f(1.0f, 1.0f, 1.0f, 1.0f); mTilemap.bind(); - glVertexPointer(3, GL_SCALAR, 0, mVertices); + glVertexPointer(3, GL_SCALAR, 0, mVertices[0].data()); glTexCoordPointer(2, GL_SCALAR, 0, mTexCoords); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -141,14 +141,14 @@ struct Scene::Impl : public Mf::Library } - Mf::Scalar mVertices[12]; + Mf::Vector3 mVertices[4]; Mf::Scalar mTexCoords[8]; Tilemap mTilemap; bool mBlending; bool mFog; - SURFACE mSurface; + Surface mSurface; }; @@ -214,7 +214,11 @@ struct Scene::Impl : public Mf::Library Mf::Script::Status load(Mf::Script& script) { std::string filePath = Scene::getPath(getName()); - if (filePath == "") return Mf::Script::FILE_ERROR; + if (filePath == "") + { + script.push("the scene file could not be found"); + return Mf::Script::FILE_ERROR; + } importSceneBindings(script); return script.doFile(filePath); @@ -336,97 +340,105 @@ struct Scene::Impl : public Mf::Library Mf::Script::Value table = script[1].requireTable(); Mf::Script::Value top = script[-1]; - Quad::SURFACE surface; - table.pushField("surface"); - top.get(surface); - script.pop(); - - int width = 1; - int height = 1; + int width = 1; + int height = 1; + int nTiles = 0; table.pushField("width"); top.get(width); script.pop(); - int nTiles = 0; - - //table.pushField("tiles"); - Mf::Script::Value tiles = script.getTop(); - nTiles = tiles.getLength(); - + nTiles = table.getLength(); if (nTiles % width != 0) table.throwError("invalid number of tiles"); - std::vector< std::vector > indices; - - int i, w, h; - + if (width == 0) table.throwError("width field must not be zero"); height = nTiles / width; - indices.resize(height); + + Mf::Vector3 vertices[height+1][width+1]; // 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) + // do first row and first column of vertices + + for (int w = 0; w <= width; ++w) + { + vertices[height][w] = Mf::demote(mTransform * + Mf::Vector4(w, height, 0.0, 1.0)); + } + for (int h = 0; h < height; ++h) { - std::vector row; + vertices[h][0] = Mf::demote(mTransform * + Mf::Vector4(0.0, h, 0.0, 1.0)); + } - for (w = 0; w < width; ++w, ++i) + size_t i = 1; + for (int h = height - 1; h >= 0; --h) + { + for (int w = 0; w < width; ++w, ++i) { - script.checkStack(2); - script.push(i); - tiles.pushField(); + int wPlus1 = w + 1; + int hPlus1 = h + 1; + + table.pushField(i); Tilemap::Index index; top.get(index); - row.push_back(index); - } + script.pop(); - indices[h] = row; - } + vertices[h][wPlus1] = Mf::demote(mTransform * + Mf::Vector4(wPlus1, h, 0.0, 1.0)); - Mf::Vector4 vertices[height+1][width+1]; + if (index == Tilemap::NO_TILE) continue; - Mf::Matrix4 transposedTransform = mTransform; - transposedTransform.transpose(); + const Mf::Vector3* corners[4] = { + &vertices[h][w], + &vertices[h][wPlus1], + &vertices[hPlus1][wPlus1], + &vertices[hPlus1][w] + }; - for (int h = 0; h <= height; ++h) - { - for (int w = 0; w <= width; ++w) - { - vertices[h][w] = Mf::Vector4(w, h, 0.0, 1.0) * transposedTransform; + Quad* quad = new Quad(corners, mTexture, index); + //quad->setSurface(surface); + + boost::shared_ptr quadPtr(quad); + mObjects.push_back(quadPtr); } } - for (int h = 0; h < height; ++h) - { - for (int w = 0; w < width; ++w) - { - if (indices[h][w] == Tilemap::NO_TILE) continue; + Quad::Surface surface = Quad::NONE; - Mf::Vector3 demotedVertices[4]; + table.pushField("surface"); + top.get(surface); + script.pop(); - demotedVertices[0] = Mf::demote(vertices[h][w]); - demotedVertices[1] = Mf::demote(vertices[h][w+1]); - demotedVertices[2] = Mf::demote(vertices[h+1][w+1]); - demotedVertices[3] = Mf::demote(vertices[h+1][w]); + if (surface != Quad::NONE) + { + // need a 2d line for collisions + // assuming the camera always looks directly to -z when the + // scene is built, simply demoting the vector again should + // project the points to the xy-plane - Quad* quad = new Quad(demotedVertices, mTexture, indices[h][w]); - quad->setSurface(surface); + //Mf::Vector2 tr = Mf::demote(vertices[height+1][width+1]); + //Mf::Vector2 bl = Mf::demote(vertices[0][0]); - if (surface != Quad::NONE) - { - // need a 2d line for collisions - // assuming the camera always looks directly to -z when the - // scene is built, simply demoting the vector again should - // project the points to the xy-plane - } + Mf::Vector2 bl = Mf::demote(vertices[0][0]); + Mf::Vector2 tr = Mf::demote(vertices[height][width]); + //Mf::logInfo("pt1: %f, %f", bl[0], bl[1]); + //Mf::logInfo("pt2: %f, %f", tr[0], tr[1]); - boost::shared_ptr quadPtr(quad); - //mOctree->insert(quadPtr); - mObjects.push_back(quadPtr); - } + mLines.push_back(Mf::Line<2>(bl, tr)); + Mf::logInfo("new line"); + + //if (tl == tr) + //{ + //mLines.push_back(Mf::Line<2>(bl, tl)); + //} + //else + //{ + //mLines.push_back(Mf::Line<2>(bl, tl)); + //} } return 0; @@ -462,10 +474,7 @@ struct Scene::Impl : public Mf::Library param.get(index); } - Mf::Vector4 vertices[2][width+1]; - - Mf::Matrix4 transposedTransform = mTransform; - transposedTransform.transpose(); + Mf::Vector3 vertices[2][width+1]; Mf::Scalar xf; Mf::Scalar increment = 1.0 / Mf::Scalar(width); @@ -475,26 +484,27 @@ struct Scene::Impl : public Mf::Library xf = 0.0; for (int w = 0; w <= width; ++w, xf += increment) { - vertices[h][w] = Mf::Vector4(xf, Mf::Scalar(h), 0.0, 1.0) * - transposedTransform; + vertices[h][w] = Mf::demote(mTransform * + Mf::Vector4(xf, Mf::Scalar(h), 0.0, 1.0)); } } for (int w = 0; w < width; ++w) { - Mf::Vector3 demotedVertices[4]; + int wPlus1 = w + 1; - demotedVertices[0] = Mf::demote(vertices[0][w]); - demotedVertices[1] = Mf::demote(vertices[0][w+1]); - demotedVertices[2] = Mf::demote(vertices[1][w+1]); - demotedVertices[3] = Mf::demote(vertices[1][w]); + const Mf::Vector3* corners[4] = { + &vertices[0][w], + &vertices[0][wPlus1], + &vertices[1][wPlus1], + &vertices[1][w] + }; - Quad* quad = new Quad(demotedVertices, mTexture, index); + Quad* quad = new Quad(corners, mTexture, index); quad->setBlending(blending); quad->setFog(fog); boost::shared_ptr quadPtr(quad); - //mOctree->insert(quadPtr); mObjects.push_back(quadPtr); } @@ -517,7 +527,6 @@ Mf::Script::Status Scene::load(Mf::Script& script) void Scene::draw(Mf::Scalar alpha) const { - //mImpl->mOctree->draw(alpha); std::list< boost::shared_ptr >& objects = mImpl->mObjects; std::list< boost::shared_ptr >::const_iterator it; @@ -531,7 +540,6 @@ void Scene::draw(Mf::Scalar alpha) const void Scene::drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const { - //mImpl->mOctree->drawIfVisible(alpha, frustum); std::list< boost::shared_ptr >& objects = mImpl->mObjects; std::list< boost::shared_ptr >::const_iterator it; @@ -540,10 +548,38 @@ void Scene::drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const (*it)->drawIfVisible(alpha, frustum); } + std::list< Mf::Line<2> >& lines = mImpl->mLines; + std::list< Mf::Line<2> >::const_iterator lit; + + for (lit = lines.begin(); lit != lines.end(); ++lit) + { + (*lit).draw(alpha); + } + mImpl->mBounds.draw(); } +bool Scene::castRay(const Mf::Ray<2>& ray, + std::list::Intersection>& hits) const +{ + std::list< Mf::Line<2> >& lines = mImpl->mLines; + std::list< Mf::Line<2> >::const_iterator it; + + for (it = lines.begin(); it != lines.end(); ++it) + { + Mf::Ray<2>::Intersection hit; + Mf::Scalar d = (*it).intersectRay(ray, hit); + if (d > 0.0) + { + hits.push_back(hit); + return true; + } + } + + return false; +} + bool Scene::checkForCollision(Character& character) { return false; @@ -559,7 +595,7 @@ bool Scene::checkForCollision(Character& character) for (it = objects.begin(); it != objects.end(); ++it) { - Impl::Quad::SURFACE type = (*it)->getSurface(); + Impl::Quad::Surface type = (*it)->getSurface(); if (type == Impl::Quad::NONE) continue; if (Mf::checkCollision(sphere, (*it)->getSphere())) diff --git a/src/Scene.hh b/src/Scene.hh index f9963e8..316f25b 100644 --- a/src/Scene.hh +++ b/src/Scene.hh @@ -29,6 +29,7 @@ #ifndef _SCENE_HH_ #define _SCENE_HH_ +#include #include #include @@ -66,6 +67,8 @@ public: Mf::Scalar getZCoord(const Mf::Vector2& position) const; + bool castRay(const Mf::Ray<2>& ray, + std::list::Intersection>& hits) const; bool checkForCollision(Character& character); static std::string getPath(const std::string& name); diff --git a/win32/mkpackage.sh.in b/win32/mkpackage.sh.in index 2051a22..e6dffa2 100644 --- a/win32/mkpackage.sh.in +++ b/win32/mkpackage.sh.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # # Yoink