=== added file 'data/textures/nasa1.png'
Binary files data/textures/nasa1.png 1970-01-01 00:00:00 +0000 and data/textures/nasa1.png 2012-05-15 18:35:35 +0000 differ
=== added file 'data/textures/nasa2.png'
Binary files data/textures/nasa2.png 1970-01-01 00:00:00 +0000 and data/textures/nasa2.png 2012-05-15 18:35:35 +0000 differ
=== added file 'data/textures/nasa3.png'
Binary files data/textures/nasa3.png 1970-01-01 00:00:00 +0000 and data/textures/nasa3.png 2012-05-15 18:35:35 +0000 differ
=== modified file 'src/model.cpp'
@@ -28,6 +28,7 @@
#include "options.h"
#include "util.h"
#include "float.h"
+#include "math.h"
#include <fstream>
#include <sstream>
#include <memory>
@@ -35,7 +36,6 @@
using std::string;
using std::vector;
using LibMatrix::vec3;
-using LibMatrix::vec2;
using LibMatrix::uvec3;
#define read_or_fail(file, dst, size) do { \
@@ -222,6 +222,34 @@
}
}
+void
+Model::calculate_texcoords()
+{
+ // Since the model didn't come with texcoords, and we don't actually know
+ // if it came with normals, either, we'll use positional spherical mapping
+ // to generate texcoords for the model. See:
+ // http://www.mvps.org/directx/articles/spheremap.htm for more details.
+ vec3 centerVec = maxVec_ + minVec_;
+ centerVec *= 0.5;
+
+ for (std::vector<Object>::iterator iter = objects_.begin();
+ iter != objects_.end();
+ iter++)
+ {
+ Object &object = *iter;
+ for (vector<Vertex>::iterator vertexIt = object.vertices.begin();
+ vertexIt != object.vertices.end();
+ vertexIt++)
+ {
+ Vertex& curVertex = *vertexIt;
+ vec3 vnorm(curVertex.v - centerVec);
+ vnorm.normalize();
+ curVertex.t.x(asinf(vnorm.x()) / M_PI + 0.5);
+ curVertex.t.y(asinf(vnorm.y()) / M_PI + 0.5);
+ }
+ }
+}
+
/**
* Calculates the normal vectors of the model vertices.
*/
@@ -443,6 +471,7 @@
object->vertices[i].t.y(f[1]);
}
}
+ gotTexcoords_ = true;
break;
//----------- Skip unknow chunks ------------
=== modified file 'src/model.h'
@@ -77,11 +77,13 @@
AttribTypeCustom
} AttribType;
- Model() {}
+ Model() : gotTexcoords_(false) {}
~Model() {}
bool load(const std::string& name);
+ bool needTexcoords() const { return !gotTexcoords_; }
+ void calculate_texcoords();
void calculate_normals();
void convert_to_mesh(Mesh &mesh);
void convert_to_mesh(Mesh &mesh,
@@ -90,6 +92,8 @@
const LibMatrix::vec3& maxVec() const { return maxVec_; }
static const ModelMap& find_models();
private:
+ // If the model we loaded contained texcoord data...
+ bool gotTexcoords_;
struct Face {
uint32_t a, b, c;
uint16_t face_flags;
=== modified file 'src/scene-build.cpp'
@@ -132,6 +132,12 @@
orientationAngle_ = -90.0;
orientationVec_ = vec3(1.0, 0.0, 0.0);
}
+ else if (whichModel == "armadillo")
+ {
+ orientModel_ = true;
+ orientationAngle_ = 180.0;
+ orientationVec_ = vec3(0.0, 1.0, 0.0);
+ }
model.calculate_normals();
=== modified file 'src/scene-bump.cpp'
@@ -154,7 +154,7 @@
attrib_locations.push_back(program_["texcoord"].location());
mesh_.set_attrib_locations(attrib_locations);
- Texture::load(GLMARK_DATA_PATH"/textures/asteroid-normal-map.png", &texture_,
+ Texture::load("asteroid-normal-map", &texture_,
GL_NEAREST, GL_NEAREST, 0);
}
@@ -206,7 +206,7 @@
attrib_locations.push_back(program_["tangent"].location());
mesh_.set_attrib_locations(attrib_locations);
- Texture::load(GLMARK_DATA_PATH"/textures/asteroid-normal-map-tangent.png", &texture_,
+ Texture::load("asteroid-normal-map-tangent", &texture_,
GL_NEAREST, GL_NEAREST, 0);
}
@@ -260,7 +260,7 @@
attrib_locations.push_back(program_["tangent"].location());
mesh_.set_attrib_locations(attrib_locations);
- Texture::load(GLMARK_DATA_PATH"/textures/asteroid-height-map.png", &texture_,
+ Texture::load("asteroid-height-map", &texture_,
GL_NEAREST, GL_NEAREST, 0);
}
@@ -270,7 +270,7 @@
Scene::setup();
const std::string &bump_render = options_["bump-render"].value;
-
+ Texture::find_textures();
Model::find_models();
if (bump_render == "normals")
setup_model_normals();
=== modified file 'src/scene-desktop.cpp'
@@ -726,12 +726,12 @@
};
int RenderWindowBlur::use_count = 0;
-RenderClearImage RenderWindowBlur::window_contents_(GLMARK_DATA_PATH"/textures/desktop-window.png");
+RenderClearImage RenderWindowBlur::window_contents_("desktop-window");
int RenderWindowShadow::use_count = 0;
-RenderClearImage RenderWindowShadow::window_contents_(GLMARK_DATA_PATH"/textures/desktop-window.png");
-RenderClearImage RenderWindowShadow::shadow_h_(GLMARK_DATA_PATH"/textures/desktop-shadow.png");
-RenderClearImage RenderWindowShadow::shadow_v_(GLMARK_DATA_PATH"/textures/desktop-shadow.png");
-RenderClearImage RenderWindowShadow::shadow_corner_(GLMARK_DATA_PATH"/textures/desktop-shadow-corner.png");
+RenderClearImage RenderWindowShadow::window_contents_("desktop-window");
+RenderClearImage RenderWindowShadow::shadow_h_("desktop-shadow");
+RenderClearImage RenderWindowShadow::shadow_v_("desktop-shadow");
+RenderClearImage RenderWindowShadow::shadow_corner_("desktop-shadow-corner");
/*******************************
* SceneDesktop implementation *
@@ -748,7 +748,7 @@
std::vector<RenderObject *> windows;
SceneDesktopPrivate(Canvas &canvas) :
- screen(canvas), desktop(GLMARK_DATA_PATH"/textures/effect-2d.png") {}
+ screen(canvas), desktop("effect-2d") {}
~SceneDesktopPrivate() { Util::dispose_pointer_vector(windows); }
@@ -810,6 +810,9 @@
blur_radius = Util::fromString<unsigned int>(options_["blur-radius"].value);
shadow_size = Util::fromString<unsigned int>(options_["shadow-size"].value);
+ // Make sure the Texture object knows where to find our images.
+ Texture::find_textures();
+
/* Ensure we get a transparent clear color for all following operations */
glClearColor(0.0, 0.0, 0.0, 0.0);
glDisable(GL_DEPTH_TEST);
=== modified file 'src/scene-effect-2d.cpp'
@@ -281,7 +281,7 @@
bool
SceneEffect2D::load()
{
- Texture::load(GLMARK_DATA_PATH"/textures/effect-2d.png", &texture_,
+ Texture::load("effect-2d", &texture_,
GL_NEAREST, GL_NEAREST, 0);
running_ = false;
@@ -299,6 +299,8 @@
{
Scene::setup();
+ Texture::find_textures();
+
static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/effect-2d.vert");
std::vector<float> kernel;
=== modified file 'src/scene-pulsar.cpp'
@@ -115,7 +115,8 @@
if (options_["texture"].value == "true") {
frg_shader_filename = GLMARK_DATA_PATH"/shaders/light-basic-tex.frag";
- Texture::load(GLMARK_DATA_PATH"/textures/crate-base.png", &texture_,
+ Texture::find_textures();
+ Texture::load("crate-base", &texture_,
GL_NEAREST, GL_NEAREST, 0);
} else {
=== modified file 'src/scene-shading.cpp'
@@ -212,6 +212,12 @@
orientationAngle_ = -90.0;
orientationVec_ = vec3(1.0, 0.0, 0.0);
}
+ else if (whichModel == "armadillo")
+ {
+ orientModel_ = true;
+ orientationAngle_ = 180.0;
+ orientationVec_ = vec3(0.0, 1.0, 0.0);
+ }
model.calculate_normals();
=== modified file 'src/scene-texture.cpp'
@@ -34,11 +34,50 @@
#include "util.h"
#include <cmath>
+using LibMatrix::vec3;
+using std::string;
+
SceneTexture::SceneTexture(Canvas &pCanvas) :
Scene(pCanvas, "texture")
{
+ const ModelMap& modelMap = Model::find_models();
+ string optionDesc("Which model to use [");
+ for (ModelMap::const_iterator modelIt = modelMap.begin();
+ modelIt != modelMap.end();
+ modelIt++)
+ {
+ static bool doSeparator(false);
+ if (doSeparator)
+ {
+ optionDesc += ", ";
+ }
+ const std::string& curName = modelIt->first;
+ optionDesc += curName;
+ doSeparator = true;
+ }
+ optionDesc += "]";
+ options_["model"] = Scene::Option("model", "cube",
+ optionDesc);
options_["texture-filter"] = Scene::Option("texture-filter", "nearest",
"[nearest, linear, linear-shader, mipmap]");
+ optionDesc = "Which texture to use [";
+ const TextureMap& textureMap = Texture::find_textures();
+ for (TextureMap::const_iterator textureIt = textureMap.begin();
+ textureIt != textureMap.end();
+ textureIt++)
+ {
+ static bool doSeparator(false);
+ if (doSeparator)
+ {
+ optionDesc += ", ";
+ }
+ const std::string& curName = textureIt->first;
+ optionDesc += curName;
+ doSeparator = true;
+ }
+ optionDesc += "]";
+ options_["texture"] = Scene::Option("texture", "crate-base",
+ optionDesc);
}
SceneTexture::~SceneTexture()
@@ -48,16 +87,6 @@
bool
SceneTexture::load()
{
- Model::find_models();
- Model model;
-
- if(!model.load("cube"))
- return false;
-
- model.calculate_normals();
- model.convert_to_mesh(mesh_);
- mesh_.build_vbo();
-
rotationSpeed_ = LibMatrix::vec3(36.0f, 36.0f, 36.0f);
running_ = false;
@@ -104,7 +133,8 @@
mag_filter = GL_LINEAR;
}
- Texture::load(GLMARK_DATA_PATH"/textures/crate-base.png", &texture_,
+ const string& whichTexture(options_["texture"].value);
+ Texture::load(whichTexture, &texture_,
min_filter, mag_filter, 0);
// Load shaders
@@ -129,14 +159,69 @@
return;
}
+ Model model;
+ const string& whichModel(options_["model"].value);
+ bool modelLoaded = model.load(whichModel);
+ if(!modelLoaded)
+ return;
+
+ // Now that we're successfully loaded, there are a few quirks about
+ // some of the known models that we need to account for. The draw
+ // logic for the scene wants to rotate the model around the Y axis.
+ // Most of our models are described this way. Some need adjustment
+ // (an additional rotation that gets the model into the correct
+ // orientation).
+ //
+ // Here's a summary:
+ //
+ // Angel rotates around the Y axis
+ // Armadillo rotates around the Y axis
+ // Buddha rotates around the X axis
+ // Bunny rotates around the Y axis
+ // Dragon rotates around the X axis
+ // Horse rotates around the Y axis
+ if (whichModel == "buddha" || whichModel == "dragon")
+ {
+ orientModel_ = true;
+ orientationAngle_ = -90.0;
+ orientationVec_ = vec3(1.0, 0.0, 0.0);
+ }
+ else if (whichModel == "armadillo")
+ {
+ orientModel_ = true;
+ orientationAngle_ = 180.0;
+ orientationVec_ = vec3(0.0, 1.0, 0.0);
+ }
+
+ if (model.needTexcoords())
+ model.calculate_texcoords();
+ model.calculate_normals();
+ model.convert_to_mesh(mesh_);
+ mesh_.build_vbo();
+
+ // Calculate a projection matrix that is a good fit for the model
+ vec3 maxVec = model.maxVec();
+ vec3 minVec = model.minVec();
+ vec3 diffVec = maxVec - minVec;
+ centerVec_ = maxVec + minVec;
+ centerVec_ /= 2.0;
+ float diameter = diffVec.length();
+ radius_ = diameter / 2;
+ float fovy = 2.0 * atanf(radius_ / (2.0 + radius_));
+ fovy /= M_PI;
+ fovy *= 180.0;
+ float aspect(static_cast<float>(canvas_.width())/static_cast<float>(canvas_.height()));
+ perspective_.setIdentity();
+ perspective_ *= LibMatrix::Mat4::perspective(fovy, aspect, 2.0, 2.0 + diameter);
+
+ program_.start();
+
std::vector<GLint> attrib_locations;
attrib_locations.push_back(program_["position"].location());
attrib_locations.push_back(program_["normal"].location());
attrib_locations.push_back(program_["texcoord"].location());
mesh_.set_attrib_locations(attrib_locations);
- program_.start();
-
currentFrame_ = 0;
rotation_ = LibMatrix::vec3();
running_ = true;
@@ -170,12 +255,15 @@
{
// Load the ModelViewProjectionMatrix uniform in the shader
LibMatrix::Stack4 model_view;
- LibMatrix::mat4 model_view_proj(canvas_.projection());
-
- model_view.translate(0.0f, 0.0f, -5.0f);
+ model_view.translate(-centerVec_.x(), -centerVec_.y(), -(centerVec_.z() + 2.5 + radius_));
model_view.rotate(rotation_.x(), 1.0f, 0.0f, 0.0f);
model_view.rotate(rotation_.y(), 0.0f, 1.0f, 0.0f);
model_view.rotate(rotation_.z(), 0.0f, 0.0f, 1.0f);
+ if (orientModel_)
+ {
+ model_view.rotate(orientationAngle_, orientationVec_.x(), orientationVec_.y(), orientationVec_.z());
+ }
+ LibMatrix::mat4 model_view_proj(perspective_);
model_view_proj *= model_view.getCurrent();
program_["ModelViewProjectionMatrix"] = model_view_proj;
=== modified file 'src/scene.h'
@@ -281,6 +281,12 @@
Program program_;
Mesh mesh_;
GLuint texture_;
+ float radius_;
+ bool orientModel_;
+ float orientationAngle_;
+ LibMatrix::vec3 orientationVec_;
+ LibMatrix::mat4 perspective_;
+ LibMatrix::vec3 centerVec_;
LibMatrix::vec3 rotation_;
LibMatrix::vec3 rotationSpeed_;
};
=== modified file 'src/text-renderer.cpp'
@@ -67,7 +67,8 @@
glUseProgram(prev_program);
/* Load the glyph texture atlas */
- Texture::load(GLMARK_DATA_PATH"/textures/glyph-atlas.png", &texture_,
+ Texture::find_textures();
+ Texture::load("glyph-atlas", &texture_,
GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,0);
}
=== modified file 'src/texture.cpp'
@@ -28,6 +28,7 @@
#include <cstdarg>
#include <png.h>
#include <memory>
+#include <vector>
class PNGState
{
@@ -177,9 +178,24 @@
}
}
+namespace TexturePrivate
+{
+TextureMap textureMap;
+}
+
bool
-Texture::load(const std::string &filename, GLuint *pTexture, ...)
+Texture::load(const std::string &textureName, GLuint *pTexture, ...)
{
+ // Make sure the named texture is in the map.
+ TextureMap::const_iterator textureIt = TexturePrivate::textureMap.find(textureName);
+ if (textureIt == TexturePrivate::textureMap.end())
+ {
+ return false;
+ }
+
+ // Pull the pathname out of the descriptor and use it for the PNG load.
+ TextureDescriptor* desc = textureIt->second;
+ const std::string& filename = desc->pathname();
ImageData image;
if (!image.load_png(filename))
@@ -199,3 +215,46 @@
return true;
}
+
+const TextureMap&
+Texture::find_textures()
+{
+ using std::vector;
+ using std::string;
+ if (!TexturePrivate::textureMap.empty())
+ {
+ return TexturePrivate::textureMap;
+ }
+ vector<string> pathVec;
+ string dataDir(GLMARK_DATA_PATH"/textures");
+ Util::list_files(dataDir, pathVec);
+ // Now that we have a list of all of the model files available to us,
+ // let's go through and pull out the names and what format they're in
+ // so the scene can decide which ones to use.
+ for(vector<string>::const_iterator pathIt = pathVec.begin();
+ pathIt != pathVec.end();
+ pathIt++)
+ {
+ const string& curPath = *pathIt;
+ string::size_type namePos(0);
+ string::size_type slashPos = curPath.rfind("/");
+ if (slashPos != string::npos)
+ {
+ // Advance to the first character after the last slash
+ namePos = slashPos + 1;
+ }
+
+ string::size_type extPos = curPath.rfind(".png");
+ if (extPos == string::npos)
+ {
+ // We can't trivially determine it's a PNG file so skip it...
+ continue;
+ }
+
+ string name(curPath, namePos, extPos - namePos);
+ TextureDescriptor* desc = new TextureDescriptor(name, curPath);
+ TexturePrivate::textureMap.insert(std::make_pair(name, desc));
+ }
+
+ return TexturePrivate::textureMap;
+}
=== modified file 'src/texture.h'
@@ -27,11 +27,50 @@
#include "gl-headers.h"
#include <string>
+#include <map>
+
+/**
+ * A descriptor for a texture file.
+ */
+class TextureDescriptor
+{
+ std::string name_;
+ std::string pathname_;
+ TextureDescriptor();
+public:
+ TextureDescriptor(const std::string& name, const std::string& pathname) :
+ name_(name),
+ pathname_(pathname) {}
+ ~TextureDescriptor() {}
+ const std::string& pathname() const { return pathname_; }
+};
+
+typedef std::map<std::string, TextureDescriptor*> TextureMap;
class Texture
{
public:
- static bool load(const std::string &filename, GLuint *pTexture, ...);
+ /**
+ * Load a texture by name.
+ *
+ * You must initialize the available texture collection using
+ * Texture::find_textures() before using this method.
+ *
+ * @name: the texture name
+ *
+ * @return: true if the operation succeeded, false otherwise
+ */
+ static bool load(const std::string &name, GLuint *pTexture, ...);
+ /**
+ * Locate all available textures.
+ *
+ * This method scans the built-in data paths and builds a database of usable
+ * textures available to scenes. Map is available on a read-only basis to
+ * scenes that might find it useful for listing textures, etc.
+ *
+ * @return: a map containing information about the located textures
+ */
+ static const TextureMap& find_textures();
};
#endif