From 87bc17e55b0c1dc73ecc66df856d3f08fd7a7724 Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Tue, 28 Jul 2009 23:51:42 -0600 Subject: [PATCH] beginnings of scene rendering --- configure.ac | 3 + doc/yoink.6.in | 37 +++-- src/Makefile.am | 5 +- src/YoinkApp.cc | 64 ++++++-- src/YoinkApp.hh | 2 + src/opengl.hh | 6 +- src/scene.cc | 377 ++++++++++++++++++++++++++++++++++++++++++++++-- src/tilemap.cc | 51 ++++--- src/tilemap.hh | 6 +- 9 files changed, 481 insertions(+), 70 deletions(-) diff --git a/configure.ac b/configure.ac index 63f2034..cc0e8be 100644 --- a/configure.ac +++ b/configure.ac @@ -101,6 +101,9 @@ AC_SEARCH_LIBS([IMG_Load], [SDL_image],, 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([clock_gettime], [rt], [AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [Define to 1 if you have the 'clock_gettime' function.])]) diff --git a/doc/yoink.6.in b/doc/yoink.6.in index 5425c3a..c5eec63 100644 --- a/doc/yoink.6.in +++ b/doc/yoink.6.in @@ -85,11 +85,12 @@ looks for configuration files and loads them in this order, with the options in prior configuration files taking precedence over the same options if they exist in multiple configuration files: .TP -1. $YOINK_CONFIGFILE -This is an optional environment variable. +1. $YOINKRC +This is an optional environment variable you can set to point to a configuration +file. .TP 2. $HOME/.yoinkrc -This is a specific user's configuration file. +This is a specific user's personal configuration file. .TP 3. /etc/yoinkrc This is the system-wide configuration file. @@ -213,29 +214,33 @@ responds to some variables in the environment: HOME If set to a path of a valid directory (presumably a user's home directory), .B yoink -will load options from the configuration file at $HOME/.yoinkrc, if it exists. -Saving options within the game will cause this file to be over-written with the -new options. +will look for a file at +.I $HOME/.yoinkrc +and load it as a configuration file. Saving options within the game will cause +this file to be over-written with the new options, unless the +.I YOINKRC +variable is set. .TP USER .B yoink uses this variable to guess the user's nickname, for a high score entry or whatever. .TP -YOINK_CONFIGFILE -If set to a path of a valid configuration file, -.B yoink -will load the options from that file, and those options will take precedence -over options loaded from other configuration files. Any in-game saving will -cause this file to be over-written by the new options rather than the file at -$HOME/.yoinkrc. -.TP YOINK_DATADIR If set to a path of a valid directory, .B yoink will look in this directory first when it is loading game assets. Set this -variable if you move the game's assets to another directory or want to load your -own assets. +variable if you move the game's assets to another directory or perhaps want to +load your own custom assets rather than the defaults. +.TP +YOINKRC +If set to a path of a valid configuration file, +.B yoink +will load the options from that file, and those options will take precedence +over options loaded from other configuration files. Any in-game saving will +cause this file to be over-written by the new options rather than the +.I $HOME/.yoinkrc +config file. .br .SH NOTES .PP diff --git a/src/Makefile.am b/src/Makefile.am index ca4f81e..0c9b062 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -48,7 +48,7 @@ libdc_la_SOURCES = \ video.hh \ $(ENDLIST) -libdc_la_CPPFLAGS = -I/usr/include/SDL -I$(top_srcdir)/yajl/src +libdc_la_CPPFLAGS = -I$(top_srcdir)/yajl/src libdc_la_LIBADD = $(top_srcdir)/yajl/libyajl.la @@ -65,7 +65,6 @@ yoink_SOURCES = \ YoinkApp.hh \ $(ENDLIST) -yoink_CPPFLAGS = -I/usr/include/SDL yoink_LDADD = libdc.la @@ -73,7 +72,7 @@ EXTRA_DIST = cml YOINK_ENVIRONMENT = YOINK_DATADIR="$(top_srcdir)/data" \ - YOINK_CONFIGFILE="$(top_srcdir)/data/yoinkrc" + YOINKRC="$(top_srcdir)/data/yoinkrc" run: all $(YOINK_ENVIRONMENT) ./yoink diff --git a/src/YoinkApp.cc b/src/YoinkApp.cc index f0a1ad9..655aa34 100644 --- a/src/YoinkApp.cc +++ b/src/YoinkApp.cc @@ -33,16 +33,14 @@ #include +#include "math.hh" #include "opengl.hh" -#include "video.hh" #include "settings.hh" - -#include "math.hh" +#include "timer.hh" +#include "video.hh" #include "YoinkApp.hh" -#include "timer.hh" - #if HAVE_CONFIG_H #include "config.h" #endif @@ -52,12 +50,12 @@ static std::string configFiles() { std::string files; - char* configFile = getenv("YOINK_CONFIGFILE"); + char* configFile = getenv("YOINKRC"); if (configFile) { // if a config file from the environment variable is specified, we want - // to load it first + // to load it first so it has precedence files += configFile; files += ":"; } @@ -135,7 +133,7 @@ void YoinkApp::setupGL() glClearColor(0.0, 0.0, 1.0, 1.0); - glLineWidth(10.0f); + //glLineWidth(10.0f); } void YoinkApp::contextRecreated(const dc::notification& note) @@ -162,21 +160,33 @@ void YoinkApp::update(dc::scalar t, dc::scalar dt) void YoinkApp::draw(dc::scalar alpha) { - dc::vector4 meh; - meh.random(0.0, 1.0); - static dc::vector4 c1(meh); + //dc::vector4 meh; + //meh.random(0.0, 1.0); + //static dc::vector4 c1(meh); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - dc::scalar drawstate = cml::lerp(prevstate, state, alpha); - dc::scalar sinstate = std::sin(drawstate); - dc::scalar cosstate = std::cos(drawstate); + //dc::scalar drawstate = cml::lerp(prevstate, state, alpha); + //dc::scalar sinstate = std::sin(drawstate); + //dc::scalar cosstate = std::cos(drawstate); + + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60.0, 1.33333, 1.0, 2000.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glBindTexture(GL_TEXTURE_2D, 0); + //glRotatef(drawstate*15.0f, 0.0, 1.0, 0.0); + glTranslatef(x, y, z); // DRAW THE SCENE testScene->draw(alpha); + /* someChar->getTilemap().bind(); glColor3f(1.0, 1.0, 1.0); @@ -289,7 +299,7 @@ void YoinkApp::draw(dc::scalar alpha) glRectf(-1.0f, -1.0f, 1.0f, 1.0f); glDisable(GL_BLEND); - glEnable(GL_DEPTH_TEST); + glEnable(GL_DEPTH_TEST);*/ } void YoinkApp::handleEvent(const dc::event& e) @@ -309,6 +319,30 @@ void YoinkApp::handleEvent(const dc::event& e) { someChar->getAnimation().startSequence("Punch"); } + else if (e.key.keysym.sym == SDLK_RIGHT) + { + x -= 50.0; + } + else if (e.key.keysym.sym == SDLK_LEFT) + { + x += 50.0; + } + else if (e.key.keysym.sym == SDLK_UP) + { + y -= 50.0; + } + else if (e.key.keysym.sym == SDLK_DOWN) + { + y += 50.0; + } + else if (e.key.keysym.sym == SDLK_PAGEUP) + { + z += 50.0; + } + else if (e.key.keysym.sym == SDLK_PAGEDOWN) + { + z -= 50.0; + } break; case SDL_QUIT: diff --git a/src/YoinkApp.hh b/src/YoinkApp.hh index 055a64c..475dca3 100644 --- a/src/YoinkApp.hh +++ b/src/YoinkApp.hh @@ -77,6 +77,8 @@ private: TilemapFont *font; + dc::scalar x, y, z; + dc::scalar state; dc::scalar prevstate; }; diff --git a/src/opengl.hh b/src/opengl.hh index 287918d..aa95164 100644 --- a/src/opengl.hh +++ b/src/opengl.hh @@ -26,8 +26,8 @@ *******************************************************************************/ -#ifndef _GL_HH_ -#define _GL_HH_ +#ifndef _OPENGL_HH_ +#define _OPENGL_HH_ #ifdef __APPLE__ #include @@ -39,7 +39,7 @@ #include #endif -#endif // _GL_HH_ +#endif // _OPENGL_HH_ /** vim: set ts=4 sw=4 tw=80: *************************************************/ diff --git a/src/scene.cc b/src/scene.cc index 7dd102b..04754ea 100644 --- a/src/scene.cc +++ b/src/scene.cc @@ -26,13 +26,20 @@ *******************************************************************************/ +#include #include #include -#include "mippleton.hh" +#include "aabb.hh" +#include "camera.hh" +#include "cullable.hh" #include "deserializer.hh" +#include "drawable.hh" +#include "math.hh" +#include "mippleton.hh" +#include "opengl.hh" #include "serializable.hh" -#include "aabb.hh" +#include "tilemap.hh" #include "scene.hh" @@ -42,6 +49,186 @@ namespace dc { class scene::scene_impl : public mippleton { + class scenery : public drawable, public cullable + { + public: + scenery(const matrix4& transform, const std::string& textureName) : + transformation(transform), + image(textureName) {} + + protected: + matrix4 transformation; + tilemap image; + bool blending; + long detail; + bool fog; + }; + + class tiles : public scenery + { + public: + tiles(const matrix4& transform, const std::string& textureName, + serializable_ptr root) : + scenery(transform, textureName), + width(1), + height(1) + { + std::map rootObj; + + if (root->get(rootObj)) + { + std::map::iterator it; + + if ((it = rootObj.find("width")) != rootObj.end()) + { + (*it).second->get(width); + } + if ((it = rootObj.find("tiles")) != rootObj.end()) + { + std::vector theTiles; + + if ((*it).second->get(theTiles)) + { + std::vector::iterator jt; + + height = theTiles.size() / width; + int w, h; + + indices.resize(height); + + for (h = height - 1, jt = theTiles.begin(); + jt != theTiles.end(); h--) + { + std::vector row; + + for (w = 0; w < width && jt != theTiles.end(); + w++, jt++) + { + long index; + + if ((*jt)->get(index)) + { + row.push_back(unsigned(index)); + } + } + + indices[h] = row; + } + } + } + } + } + + void draw(scalar alpha) + { + glPushMatrix(); + //std::cout << "transforming..." << std::endl; + //std::cout << transformation << std::endl; + glMultMatrixf(transformation.data()); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + image.bind(); + + long x, y; + scalar xf, yf; + + for (y = 0, yf = 0.0; y < height; y++, yf += 1.0) + { + for (x = 0, xf = 0.0; x < width; x++, xf += 1.0) + { + scalar texCoords[8]; + + unsigned index = indices[y][x]; + + if (image.getTileCoords(index, texCoords)) + { + glBegin(GL_TRIANGLE_FAN); + glTexCoord2f(texCoords[0], texCoords[1]); + glVertex3f(xf, yf, 0.0f); + glTexCoord2f(texCoords[2], texCoords[3]); + glVertex3f(xf+1.0, yf, 0.0f); + glTexCoord2f(texCoords[4], texCoords[5]); + glVertex3f(xf+1.0, yf+1.0, 0.0f); + glTexCoord2f(texCoords[6], texCoords[7]); + glVertex3f(xf, yf+1.0, 0.0f); + glEnd(); + } + } + } + + glPopMatrix(); + } + + bool isVisible(const camera& cam) + { + return true; + } + + private: + long width, height; + std::vector > indices; + }; + + class billboard : public scenery + { + public: + billboard(const matrix4& transform, const std::string& textureName, + serializable_ptr root) : + scenery(transform, textureName), + index(0) + { + std::map rootObj; + + if (root->get(rootObj)) + { + std::map::iterator it; + + if ((it = rootObj.find("tile")) != rootObj.end()) + { + long value; + if ((*it).second->get(value)) + { + index = unsigned(value); + } + } + } + + image.getTileCoords(index, texCoords); + } + + void draw(scalar alpha) + { + glPushMatrix(); + glMultMatrixf(transformation.data()); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + image.bind(); + + glBegin(GL_TRIANGLE_FAN); + glTexCoord2f(texCoords[0], texCoords[1]); + glVertex2f(0.0f, 0.0f); + glTexCoord2f(texCoords[2], texCoords[3]); + glVertex2f(1.0f, 0.0f); + glTexCoord2f(texCoords[4], texCoords[5]); + glVertex2f(1.0f, 1.0f); + glTexCoord2f(texCoords[6], texCoords[7]); + glVertex2f(0.0f, 1.0f); + glEnd(); + + glPopMatrix(); + } + + bool isVisible(const camera& cam) + { + return false; + } + + private: + unsigned index; + scalar texCoords[8]; + }; + + static bool loadBox(aabb& theBox, serializable_ptr obj) { std::vector numbers; @@ -63,7 +250,6 @@ class scene::scene_impl : public mippleton } public: - scene_impl(const std::string& name) : mippleton(name) { @@ -71,6 +257,164 @@ public: } + void loadInstructions(serializable_ptr root) + { + std::vector rootObj; + + if (root->get(rootObj)) + { + std::vector::iterator it; + + matrix4 transform; + std::string texture; + + for (it = rootObj.begin(); it != rootObj.end(); it++) + { + std::string instruction; + + if ((*it)->get(instruction)) + { + if (instruction == "reset_transform") + { + transform.identity(); + //std::cout << "===================RESET=====================" << std::endl; + } + else if (instruction == "translate") + { + std::vector values; + + it++; + if ((*it)->get(values)) + { + vector3 vec; + + for (unsigned i = 0; i < values.size(); i++) + { + double value; + + if (values[i]->getNumber(value)) + { + vec[i] = value; + } + } + + matrix4 translation; + cml::matrix_translation(translation, vec); + transform = translation * transform; + //std::cout << "TRANSLATE\t" << vec << std::endl + //<< transform << std::endl; + } + } + else if (instruction == "scale") + { + std::vector values; + + it++; + if ((*it)->get(values)) + { + if (values.size() == 1) + { + double value = 1.0; + + values[0]->getNumber(value); + + matrix4 scaling; + cml::matrix_uniform_scale(scaling, scalar(value)); + transform = scaling * transform; + //std::cout << "SCALE\t\t" << value << std::endl + //<< transform << std::endl; + } + else if (values.size() == 3) + { + vector3 vec; + + for (unsigned i = 0; i < values.size(); i++) + { + double value; + + if (values[i]->getNumber(value)) + { + vec[i] = value; + } + } + + matrix4 scaling; + cml::matrix_scale(scaling, vec); + transform = scaling * transform; + //std::cout << "SCALE\t\t" << vec << std::endl + //<< transform << std::endl; + } + } + } + else if (instruction == "rotate") + { + std::vector values; + + it++; + if ((*it)->get(values)) + { + if (values.size() == 2) + { + std::string axis; + size_t axisIndex = 0; + double value = 0.0; + + if (values[0]->get(axis)) + { + if (axis == "x") + { + axisIndex = 0; + } + else if (axis == "y") + { + axisIndex = 1; + } + else if (axis == "z") + { + axisIndex = 2; + } + values[1]->getNumber(value); + } + + cml::matrix_rotate_about_local_axis(transform, + axisIndex, scalar(value * cml::constantsd::rad_per_deg())); + //std::cout << "ROTATE\t" << axis << " " << value << std::endl + //<< transform << std::endl; + } + } + } + else if (instruction == "texture") + { + it++; + (*it)->get(texture); + } + else if (instruction == "tilemap") + { + //std::cout << "TILEMAP\t" << texture<< std::endl; + //std::cout << transform << std::endl; + + it++; + tiles* newTiles = new tiles(transform, texture, *it); + boost::shared_ptr sceneItem(newTiles); + objects.push_back(sceneItem); + } + else if (instruction == "billboard") + { + //std::cout << "BILLBOARD\t" << texture << std::endl; + //std::cout << transform << std::endl; + + it++; + billboard* newBB = new billboard(transform, texture, + *it); + boost::shared_ptr sceneItem(newBB); + objects.push_back(sceneItem); + } + } + } + } + } + + void loadFromFile() { std::string filePath = scene::getPathToResource(getName()); @@ -95,19 +439,32 @@ public: { loadBox(maximumBounds, (*it).second); } - - //for (i = rootObj.begin(); i != rootObj.end(); i++) - //{ - //sequences.insert(std::pair((*i).first, - //sequence((*i).second))); - //} + if ((it = rootObj.find("instructions")) != rootObj.end()) + { + loadInstructions((*it).second); + } } } } + + void draw(scalar alpha) + { + scenery_list::iterator it; + + for (it = objects.begin(); it != objects.end(); it++) + { + //std::cout << "draw object"; + (*it)->draw(alpha); + } + } + + aabb playfieldBounds; aabb maximumBounds; + typedef std::vector > scenery_list; + scenery_list objects; }; @@ -118,6 +475,8 @@ scene::scene(const std::string& name) : void scene::draw(scalar alpha) { + // pass through + impl->draw(alpha); } diff --git a/src/tilemap.cc b/src/tilemap.cc index 0852f98..4a55c65 100644 --- a/src/tilemap.cc +++ b/src/tilemap.cc @@ -26,13 +26,10 @@ *******************************************************************************/ -#include - -#include "mippleton.hh" -#include "serializable.hh" #include "deserializer.hh" - +#include "mippleton.hh" #include "opengl.hh" +#include "serializable.hh" #include "tilemap.hh" @@ -154,9 +151,10 @@ tilemap::tilemap(const std::string& name) : } -void tilemap::getTileCoords(unsigned index, scalar coords[8]) +bool tilemap::getTileCoords(unsigned index, scalar coords[8]) { - assert(index < impl->tilesU_ * impl->tilesV_); + // make sure the index represents a real tile + if (index >= impl->tilesU_ * impl->tilesV_) return false; scalar w = 1.0 / scalar(impl->tilesU_); scalar h = 1.0 / scalar(impl->tilesV_); @@ -169,26 +167,35 @@ void tilemap::getTileCoords(unsigned index, scalar coords[8]) coords[5] = coords[1] + h; coords[6] = coords[0]; coords[7] = coords[5]; + + return true; } -void tilemap::getTileCoords(unsigned index, scalar coords[8], orientation what) +bool tilemap::getTileCoords(unsigned index, scalar coords[8], orientation what) { - getTileCoords(index, coords); - - if (what & flip) + if (getTileCoords(index, coords)) { - coords[1] = coords[5]; - coords[5] = coords[3]; - coords[3] = coords[7]; - coords[7] = coords[5]; - } - if (what & reverse) - { - coords[0] = coords[2]; - coords[2] = coords[6]; - coords[4] = coords[6]; - coords[6] = coords[0]; + if (what & flip) + { + // this looks kinda weird, but it's just swapping in a way that + // doesn't require an intermediate variable + coords[1] = coords[5]; + coords[5] = coords[3]; + coords[3] = coords[7]; + coords[7] = coords[5]; + } + if (what & reverse) + { + coords[0] = coords[2]; + coords[2] = coords[6]; + coords[4] = coords[6]; + coords[6] = coords[0]; + } + + return true; } + + return false; } diff --git a/src/tilemap.hh b/src/tilemap.hh index f2f76ab..df8d9af 100644 --- a/src/tilemap.hh +++ b/src/tilemap.hh @@ -77,9 +77,10 @@ public: * two places and so on until all four coordinates are stored, therefore * requiring enough room for an array of eight scalars. The winding of the * coordinates is always counter-clockwise (the GL default). + * @return True if index is valid, false otherwise. */ - void getTileCoords(unsigned index, scalar coords[8]); + bool getTileCoords(unsigned index, scalar coords[8]); /** @@ -87,9 +88,10 @@ public: * the texture coordinates. This allows you to easily map a texture * backwards or upside-down. * @param what The orientation; can be flip, reverse, or flip_and_reverse. + * @return True if index is valid, false otherwise. */ - void getTileCoords(unsigned index, scalar coords[8], orientation what); + bool getTileCoords(unsigned index, scalar coords[8], orientation what); static std::string getPathToResource(const std::string& name); -- 2.45.2