textures, lightmaps, hardcoded texture hack for testing
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 1 Nov 2016 03:16:41 +0000 (05:16 +0200)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 1 Nov 2016 03:16:41 +0000 (05:16 +0200)
13 files changed:
sdr/test.p.glsl [new file with mode: 0644]
sdr/test.v.glsl [new file with mode: 0644]
src/app.cc
src/datamap.cc
src/datamap.h
src/material.cc
src/material.h
src/mesh.cc
src/mesh.h
src/scene.cc
src/scene.h
src/sceneload.cc
src/texture.cc

diff --git a/sdr/test.p.glsl b/sdr/test.p.glsl
new file mode 100644 (file)
index 0000000..87ca201
--- /dev/null
@@ -0,0 +1,51 @@
+/* vi: set ft=glsl */
+uniform sampler2D texmap;
+uniform sampler2D lightmap;
+
+varying vec3 vdir, ldir[3], normal;
+
+//#define KD gl_FrontMaterial.diffuse.rgb
+#define KD vec3(1.0, 1.0, 1.0)
+
+#define KS gl_FrontMaterial.specular.rgb
+#define SPOW gl_FrontMaterial.shininess
+
+#define LD(i) gl_LightSource[i].diffuse.rgb
+#define LS(i) gl_LightSource[i].specular.rgb
+
+vec3 calc_diffuse(in vec3 n, in vec3 l, in vec3 lcol)
+{
+       float ndotl = max(dot(n, l), 0.0);
+       return KD * lcol * ndotl;
+}
+
+vec3 calc_specular(in vec3 n, in vec3 l, in vec3 v, in vec3 lcol)
+{
+       vec3 h = normalize(l + v);
+       float ndoth = max(dot(n, h), 0.0);
+       return KS * lcol * pow(ndoth, SPOW);
+}
+
+void main()
+{
+       vec3 texel = texture2D(texmap, gl_TexCoord[0].st).rgb;
+       vec3 lumel = texture2D(lightmap, gl_TexCoord[1].st).rgb;
+
+       vec3 n = normalize(normal);
+       vec3 v = normalize(vdir);
+
+       vec3 diffuse = lumel * texel * 1.8;
+       vec3 specular = vec3(0.0, 0.0, 0.0);
+
+       /*
+       for(int i=0; i<3; i++) {
+               vec3 l = normalize(ldir[i]);
+               diffuse += calc_diffuse(n, l, LD(i)) * texel;
+               specular += calc_specular(n, l, v, LS(i));
+       }
+       */
+
+       vec3 ambient = gl_LightModel.ambient.rgb * KD * texel;
+       gl_FragColor.rgb = ambient + diffuse;// + specular;
+       gl_FragColor.a = gl_FrontMaterial.diffuse.a;
+}
diff --git a/sdr/test.v.glsl b/sdr/test.v.glsl
new file mode 100644 (file)
index 0000000..a8c7159
--- /dev/null
@@ -0,0 +1,15 @@
+varying vec3 vdir, ldir[3], normal;
+
+void main()
+{
+       gl_Position = ftransform();
+       vec3 vpos = (gl_ModelViewMatrix * gl_Vertex).xyz;
+       normal = gl_NormalMatrix * gl_Normal;
+       vdir = -vpos;
+       ldir[0] = gl_LightSource[0].position.xyz - vpos;
+       ldir[1] = gl_LightSource[1].position.xyz - vpos;
+       ldir[2] = gl_LightSource[2].position.xyz - vpos;
+
+       gl_TexCoord[0] = gl_MultiTexCoord0;
+       gl_TexCoord[1] = gl_MultiTexCoord1;
+}
index 0869399..3426c99 100644 (file)
@@ -14,7 +14,7 @@ long time_msec;
 int win_width, win_height;
 bool opt_gear_wireframe;
 
-static float cam_dist = 10.0;
+static float cam_dist = 0.0;
 static float cam_theta, cam_phi = 20;
 static Vec3 cam_pos;
 static int prev_mx, prev_my;
@@ -24,12 +24,14 @@ static bool keystate[256];
 static Mat4 view_matrix;
 static TextureSet texman;
 static Scene *scn;
+static unsigned int sdr;
 
 static long prev_msec;
 
 
 bool app_init()
 {
+       glEnable(GL_FRAMEBUFFER_SRGB);
        glEnable(GL_MULTISAMPLE);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
@@ -38,17 +40,57 @@ bool app_init()
 
        Mesh::use_custom_sdr_attr = false;
 
-       float ambient[] = {0.1, 0.1, 0.1, 0.0};
+       float ambient[] = {0.0, 0.0, 0.0, 0.0};
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
 
-       unsigned int sflags = 0;
-       scn = new Scene;
+       unsigned int sflags = SCNLOAD_FLIPTEX;
+       scn = new Scene(&texman);
        if(!(scn->load("data/testscene/patoma.fbx", sflags)) ||
                        !(scn->load("data/testscene/kolones.fbx", sflags))) {
                fprintf(stderr, "failed to load test scene\n");
                return false;
        }
 
+       // hardcoded texture assignment hack
+       Texture *tex_girogiromarmaro = texman.get("data/testscene/girogiromarmarodiffuse.jpg");
+       Texture *tex_kafemarble = texman.get("data/testscene/kafemarblediffuse.jpg");
+       Texture *tex_kentrikokafemarble = texman.get("data/testscene/kentrikokafemarblediffuse.jpg");
+       Texture *tex_paliomarmaro = texman.get("data/testscene/paliomarmarodiffuse.jpg");
+       Texture *tex_steelgreygranite = texman.get("data/testscene/steel-grey-granitediffuse.jpg");
+       Texture *tex_whitemarble = texman.get("data/testscene/whitemarblediffuse.jpg");
+       Texture *tex_kolones_lightmap = texman.get("data/testscene/kolones_lighmap.jpg");
+       Texture *tex_patoma_lightmap = texman.get("data/testscene/patomacorona_lightmap.jpg");
+
+       for(int i=0; i<(int)scn->objects.size(); i++) {
+               Object *obj = scn->objects[i];
+               if(obj->mtl.name == "WiteMarble") {
+                       obj->mtl.add_texture(tex_whitemarble, MTL_TEX_DIFFUSE);
+                       obj->mtl.add_texture(tex_patoma_lightmap, MTL_TEX_LIGHTMAP);
+               } else if(obj->mtl.name == "BrownMarble") {
+                       obj->mtl.add_texture(tex_kafemarble, MTL_TEX_DIFFUSE);
+                       obj->mtl.add_texture(tex_patoma_lightmap, MTL_TEX_LIGHTMAP);
+               } else if(obj->mtl.name == "GiroGiroMarmaro") {
+                       obj->mtl.add_texture(tex_girogiromarmaro, MTL_TEX_DIFFUSE);
+                       obj->mtl.add_texture(tex_patoma_lightmap, MTL_TEX_LIGHTMAP);
+               } else if(obj->mtl.name == "KentrikoKafeMarmaro") {
+                       obj->mtl.add_texture(tex_kentrikokafemarble, MTL_TEX_DIFFUSE);
+                       obj->mtl.add_texture(tex_patoma_lightmap, MTL_TEX_LIGHTMAP);
+               } else if(obj->mtl.name == "SkouroGrizoMarmaro") {
+                       obj->mtl.add_texture(tex_steelgreygranite, MTL_TEX_DIFFUSE);
+                       obj->mtl.add_texture(tex_kolones_lightmap, MTL_TEX_LIGHTMAP);
+               } else if(obj->mtl.name == "PalioMarmaro") {
+                       obj->mtl.add_texture(tex_paliomarmaro, MTL_TEX_DIFFUSE);
+                       obj->mtl.add_texture(tex_kolones_lightmap, MTL_TEX_LIGHTMAP);
+               }
+       }
+
+       if(!(sdr = create_program_load("sdr/test.v.glsl", "sdr/test.p.glsl"))) {
+               fprintf(stderr, "failed to load test shaders\n");
+               return false;
+       }
+       set_uniform_int(sdr, "texmap", 0);
+       set_uniform_int(sdr, "lightmap", 1);
+
        glUseProgram(0);
        return true;
 }
@@ -79,6 +121,12 @@ static void update(float dt)
        if(keystate[(int)'a']) {
                dir.x -= walk_speed;
        }
+       if(keystate[(int)'q']) {
+               cam_pos.y += walk_speed;
+       }
+       if(keystate[(int)'z']) {
+               cam_pos.y -= walk_speed;
+       }
 
        float theta = M_PI * cam_theta / 180.0f;
        cam_pos.x += cos(theta) * dir.x - sin(theta) * dir.z;
@@ -108,7 +156,7 @@ void app_display()
        view_matrix.pre_translate(0, 0, -cam_dist);
        view_matrix.pre_rotate(deg_to_rad(cam_phi), 1, 0, 0);
        view_matrix.pre_rotate(deg_to_rad(cam_theta), 0, 1, 0);
-       view_matrix.pre_translate(-cam_pos.x, 0, -cam_pos.z);
+       view_matrix.pre_translate(-cam_pos.x, -cam_pos.y, -cam_pos.z);
 
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(view_matrix[0]);
@@ -138,7 +186,10 @@ static void draw_scene()
        glVertex3f(-30, -10, -30);
        glEnd();
        */
+
+       glUseProgram(sdr);
        scn->draw();
+       glUseProgram(0);
 }
 
 
index bf8854c..626c47f 100644 (file)
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <vector>
 #include <map>
 #include <string>
+#include <regex>
 #include "datamap.h"
 
-static std::vector<std::pair<std::string, std::string>> dmap;
+#ifdef WIN32
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
+
+static char *clean_line(char *s);
+
+static std::vector<std::pair<std::regex, std::string>> dmap;
 static std::map<std::string, std::string> cache;
 static std::string root;
 
-void datmap_reset()
+void datamap_reset()
 {
        root.clear();
        dmap.clear();
        cache.clear();
 }
 
-void datmap_set_path(const char *path)
+void datamap_set_path(const char *path)
 {
        root = std::string(path);
 }
 
-bool datmap_load_map(const char *fname)
+bool datamap_load_map(const char *fname)
 {
        std::string path = root.empty() ? fname : root + std::string("/") + fname;
-       return false;   // TODO cont...
+       fname = path.c_str();
+
+       FILE *fp = fopen(fname, "r");
+       if(!fp) {
+               fprintf(stderr, "failed to open data map: %s\n", fname);
+               return false;
+       }
+
+       char buf[256];
+       if(fread(buf, 1, 8, fp) < 8 || memcmp(buf, "DATAMAP0", 8) != 0) {
+               fprintf(stderr, "invalid datamap file: %s\n", fname);
+               fclose(fp);
+               return false;
+       }
+
+       datamap_reset();
+
+       char *line;
+       int nline = 0;
+       while(fgets(buf, sizeof buf, fp)) {
+               ++nline;
+               line = clean_line(buf);
+               if(!line || !*line) continue;
+
+               char *colon = strchr(line, ':');
+               if(!colon) {
+                       goto err;
+               }
+               *colon = 0;
+
+               std::pair<std::regex, std::string> pair;
+               pair.first = std::regex(line);
+
+               char *value = clean_line(colon + 1);
+               if(!value || !*value) {
+                       goto err;
+               }
+               pair.second = std::string(value);
+               dmap.push_back(pair);
+       }
+       fclose(fp);
+
+       printf("loaded datamap %s: %d mappings\n", fname, (int)dmap.size());
+       return true;
+
+err:
+       fprintf(stderr, "error while parsing %s, invalid line %d: %s\n", fname, nline, line);
+       datamap_reset();
+       fclose(fp);
+       return false;
 }
 
-void datmap_map(const char *re, const char *path)
+void datamap_map(const char *re, const char *path)
 {
-       std::pair<std::string, std::string> mapping;
-       mapping.first = std::string(re);
+       std::pair<std::regex, std::string> mapping;
+       mapping.first = std::regex(re);
        mapping.second = std::string(path);
-       dmap.push_back(mapping);
+       dmap.push_back(std::move(mapping));
+}
+
+int datamap_lookup(const char *in, char *buf, int bsz)
+{
+       std::string res;
+
+       char *inbuf = (char*)alloca(strlen(in) + 1);
+       strcpy(inbuf, in);
+       in = clean_line(inbuf);
+
+       // first check the cache
+       std::map<std::string, std::string>::iterator it = cache.find(in);
+       if(it != cache.end()) {
+               res = it->second;
+       } else {
+               // try matching with the available mappings
+               int num = dmap.size();
+               for(int i=0; i<num; i++) {
+                       if(std::regex_match(in, dmap[i].first)) {
+                               res = root.empty() ? dmap[i].second : root + "/" + dmap[i].second;
+                               cache[in] = res;        // add it to the cache
+                               break;
+                       }
+               }
+               return 0;
+       }
+
+       // copy result in buf, truncating if necessary and return the size of the
+       // buffer required to hold it
+       if(buf) {
+               int n = std::min(bsz - 1, (int)res.length());
+               memcpy(buf, res.c_str(), n);
+               buf[bsz - 1] = 0; // make sure it's null-terminated even if it got truncated
+       }
+       return res.length() + 1;
 }
 
-int datmap_lookup(const char *in, char *buf, int bsz)
+int datamap_path_size(const char *in)
 {
-       return -1;      // TODO
+       return datamap_lookup(in, 0, 0);
 }
 
-int datmap_path_size(const char *in)
+static char *clean_line(char *s)
 {
-       return datmap_lookup(in, 0, 0);
+       while(*s && isspace(*s)) ++s;
+       if(!*s) return 0;
+
+       char *end;
+       if(!(end = strchr(s, '#'))) {
+               end = s + strlen(s) - 1;
+       }
+       while(end > s && isspace(*end)) --end;
+       if(s == end) return 0;
+       end[1] = 0;
+
+       // app-specific: convert backslashes
+       char *c = s;
+       while(*c) {
+               if(*c == '\\') *c = '/';
+               ++c;
+       }
+
+       return s;
 }
index 4cbc44b..47e7d49 100644 (file)
@@ -1,13 +1,13 @@
 #ifndef DATAMAP_H_
 #define DATAMAP_H_
 
-void datmap_reset();
-void datmap_set_path(const char *path);
+void datamap_reset();
+void datamap_set_path(const char *path);
 
-bool datmap_load_map(const char *fname);
-void datmap_map(const char *re, const char *path);
+bool datamap_load_map(const char *fname);
+void datamap_map(const char *re, const char *path);
 
-int datmap_lookup(const char *in, char *buf, int bsz);
-int datmap_path_size(const char *in);
+int datamap_lookup(const char *in, char *buf, int bsz);
+int datamap_path_size(const char *in);
 
 #endif // DATAMAP_H_
index 962b10c..ac8c112 100644 (file)
@@ -1,3 +1,5 @@
+#include <algorithm>
+#include <string.h>
 #include "opengl.h"
 #include "material.h"
 
@@ -6,6 +8,7 @@ Material::Material()
 {
        shininess = 0.0f;
        alpha = 1.0f;
+       memset(stdtex, 0, sizeof stdtex);
 }
 
 void Material::setup() const
@@ -16,4 +19,18 @@ void Material::setup() const
        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, kd);
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ks);
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
+
+       int ntex = std::min((int)textures.size(), 8);   // TODO: use max texture units
+       for(int i=0; i<ntex; i++) {
+               bind_texture(textures[i], i);
+       }
+}
+
+void Material::add_texture(Texture *tex, int type)
+{
+       textures.push_back(tex);
+
+       if(type != MTL_TEX_UNKNOWN) {
+               stdtex[type] = tex;
+       }
 }
index f5c26ae..979bbd9 100644 (file)
@@ -1,16 +1,37 @@
 #ifndef MATERIAL_H_
 #define MATERIAL_H_
 
+#include <vector>
+#include <string>
 #include <gmath/gmath.h>
+#include "texture.h"
+
+enum {
+       MTL_TEX_DIFFUSE,
+       MTL_TEX_SPECULAR,
+       MTL_TEX_NORMALMAP,
+       MTL_TEX_LIGHTMAP,
+       MTL_TEX_ENVMAP,
+
+       MTL_TEX_UNKNOWN
+};
+
+#define NUM_MTL_TEXTURES       MTL_TEX_UNKNOWN
 
 class Material {
 public:
+       std::string name;
        Vec3 diffuse, specular;
        float shininess;
        float alpha;
 
+       Texture *stdtex[NUM_MTL_TEXTURES];
+       std::vector<Texture*> textures;
+
        Material();
        void setup() const;
+
+       void add_texture(Texture *tex, int type = MTL_TEX_UNKNOWN);
 };
 
 #endif // MATERIAL_H_
index beb5b49..e17b909 100644 (file)
@@ -9,15 +9,7 @@
 #define USE_OLDGL
 
 bool Mesh::use_custom_sdr_attr = true;
-int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 0, 1, 2, 3, 4, 5, 6 };
-/*
-       (int)SDR_ATTR_VERTEX,
-       (int)SDR_ATTR_NORMAL,
-       (int)SDR_ATTR_TANGENT,
-       (int)SDR_ATTR_TEXCOORD,
-       (int)SDR_ATTR_COLOR,
-       -1, -1};
-*/
+int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 unsigned int Mesh::intersect_mode = ISECT_DEFAULT;
 float Mesh::vertex_sel_dist = 0.01;
 float Mesh::vis_vecsize = 1.0;
@@ -680,6 +672,13 @@ bool Mesh::pre_draw() const
                        glColorPointer(vattr[MESH_ATTR_COLOR].nelem, GL_FLOAT, 0, 0);
                        glEnableClientState(GL_COLOR_ARRAY);
                }
+               if(vattr[MESH_ATTR_TEXCOORD2].vbo_valid) {
+                       glClientActiveTexture(GL_TEXTURE1);
+                       glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_TEXCOORD2].vbo);
+                       glTexCoordPointer(vattr[MESH_ATTR_TEXCOORD2].nelem, GL_FLOAT, 0, 0);
+                       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+                       glClientActiveTexture(GL_TEXTURE0);
+               }
 #endif
        }
        glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -725,6 +724,11 @@ void Mesh::post_draw() const
                if(vattr[MESH_ATTR_COLOR].vbo_valid) {
                        glDisableClientState(GL_COLOR_ARRAY);
                }
+               if(vattr[MESH_ATTR_TEXCOORD2].vbo_valid) {
+                       glClientActiveTexture(GL_TEXTURE1);
+                       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+                       glClientActiveTexture(GL_TEXTURE0);
+               }
 #endif
        }
 }
@@ -1087,7 +1091,7 @@ bool Mesh::dump(FILE *fp) const
        }
 
        fprintf(fp, "VERTEX ATTRIBUTES\n");
-       static const char *label[] = { "pos", "nor", "tan", "tex", "col", "bw", "bid" };
+       static const char *label[] = { "pos", "nor", "tan", "tex", "col", "bw", "bid", "tex2" };
        static const char *elemfmt[] = { 0, " %s(%g)", " %s(%g, %g)", " %s(%g, %g, %g)", " %s(%g, %g, %g, %g)", 0 };
 
        for(int i=0; i<(int)nverts; i++) {
index 50a0d61..90cd1e7 100644 (file)
@@ -15,6 +15,7 @@ enum {
        MESH_ATTR_COLOR,
        MESH_ATTR_BONEWEIGHTS,
        MESH_ATTR_BONEIDX,
+       MESH_ATTR_TEXCOORD2,
 
        NUM_MESH_ATTR
 };
index 27be807..8132fe9 100644 (file)
@@ -2,9 +2,17 @@
 
 static void destroy_node_tree(SceneNode *n);
 
-Scene::Scene()
+Scene::Scene(TextureSet *tset)
 {
        nodes = 0;
+
+       if(tset) {
+               texset = tset;
+               own_texset = false;
+       } else {
+               texset = new TextureSet;
+               own_texset = true;
+       }
 }
 
 Scene::~Scene()
@@ -16,6 +24,11 @@ void Scene::destroy()
 {
        destroy_node_tree(nodes);
        nodes = 0;
+
+       if(own_texset) {
+               delete texset;
+       }
+       texset = 0;
 }
 
 // Scene::load defined in sceneload.cc
index 066d9dc..808b3e6 100644 (file)
@@ -4,6 +4,7 @@
 #include <vector>
 #include "mesh.h"
 #include "snode.h"
+#include "texture.h"
 
 enum {
        SCNLOAD_FLIPYZ = 1,
@@ -11,12 +12,17 @@ enum {
 };
 
 class Scene {
+private:
+       bool own_texset;
+
 public:
        std::vector<Mesh*> meshes;
        std::vector<Object*> objects;
        SceneNode *nodes;
 
-       Scene();
+       TextureSet *texset;
+
+       explicit Scene(TextureSet *tset = 0);
        ~Scene();
 
        Scene(const Scene &rhs) = delete;
index 5179e4a..865a4c8 100644 (file)
 #include <assimp/quaternion.h>
 #include "scene.h"
 #include "objmesh.h"
+#include "datamap.h"
 
-static bool load_material(Material *mat, const aiMaterial *aimat);
-static SceneNode *load_node(const aiScene *aiscn, unsigned int flags, const aiNode *ainode);
-static Mesh *load_mesh(const aiScene *aiscn, unsigned int flags, const aiMesh *aimesh);
+static bool load_material(Scene *scn, Material *mat, const aiMaterial *aimat);
+static SceneNode *load_node(Scene *scn, const aiScene *aiscn, unsigned int flags, const aiNode *ainode);
+static Mesh *load_mesh(Scene *scn, const aiScene *aiscn, unsigned int flags, const aiMesh *aimesh);
+/*static const char *mprop_semantic(int x);
+static int count_textures(const aiMaterial *aimat);*/
+static int assimp_textype(aiTextureType type);
 
 /*static Vec3 assimp_vector(const aiVector3D &v);
 static Quat assimp_quat(const aiQuaternion &q);
@@ -65,7 +69,7 @@ bool Scene::load(const char *fname, unsigned int flags)
 
                switch(aimesh->mPrimitiveTypes) {
                case aiPrimitiveType_TRIANGLE:
-                       if((mesh = load_mesh(aiscn, flags, aimesh))) {
+                       if((mesh = load_mesh(this, aiscn, flags, aimesh))) {
                                mesh_by_aimesh[aimesh] = mesh;
                                meshes.push_back(mesh);
                        }
@@ -81,7 +85,7 @@ bool Scene::load(const char *fname, unsigned int flags)
 
        // load all the nodes recursively
        for(unsigned int i=0; i<aiscn->mRootNode->mNumChildren; i++) {
-               SceneNode *node = load_node(aiscn, flags, aiscn->mRootNode->mChildren[i]);
+               SceneNode *node = load_node(this, aiscn, flags, aiscn->mRootNode->mChildren[i]);
                if(node) {
                        root->add_child(node);
                }
@@ -106,11 +110,19 @@ bool Scene::load(const char *fname, unsigned int flags)
        return true;
 }
 
-static bool load_material(Material *mat, const aiMaterial *aimat)
+static bool load_material(Scene *scn, Material *mat, const aiMaterial *aimat)
 {
+       aiString name;
        aiColor4D aicol;
        float shin, shin_str;
 
+       if(aiGetMaterialString(aimat, AI_MATKEY_NAME, &name) == 0) {
+               mat->name = name.data;
+       } else {
+               mat->name = "unknown";
+       }
+       printf("load_material: %s\n", mat->name.c_str());
+
        if(aiGetMaterialColor(aimat, AI_MATKEY_COLOR_DIFFUSE, &aicol) == 0) {
                mat->diffuse = Vec3(aicol[0], aicol[1], aicol[2]);
        }
@@ -127,14 +139,51 @@ static bool load_material(Material *mat, const aiMaterial *aimat)
                mat->shininess = shin * shin_str * 0.0001 * 128.0;
        }
 
-       /*
        // load textures
-       struct { int type; aiTextureType aitype; } textypes[] = {
-               {TEX_DIFFUSE, aiTextureType_DIFFUSE},
-               {TEX_NORMAL, aiTextureType_NORMALS},
-               {TEX_SPECULAR, aiTextureType_SPECULAR}
-       };
 
+       const int num_tex_types = aiTextureType_UNKNOWN + 1;
+       for(int i=0; i<num_tex_types; i++) {
+               aiTextureType aitype = (aiTextureType)i;
+               int count = aiGetMaterialTextureCount(aimat, aitype);
+
+               for(int j=0; j<count; j++) {
+                       aiString aipath;
+                       if(aiGetMaterialTexture(aimat, aitype, j, &aipath) != 0) {
+                               continue;
+                       }
+
+                       char *fname;
+                       int nsize = datamap_path_size(aipath.data);
+                       if(nsize) {
+                               fname = new char[nsize];
+                               datamap_lookup(aipath.data, fname, nsize);
+                       } else {
+                               fname = new char[strlen(aipath.data) + 1];
+                               char *dptr = fname;
+                               char *sptr = aipath.data;
+                               do {
+                                       *dptr++ = *sptr == '\\' ? '/' : *sptr;
+                               } while(*sptr++);
+                       }
+
+                       Texture *tex = scn->texset->get(fname);
+                       if(!tex) {
+                               fprintf(stderr, "failed to load texture: %s\n", fname);
+                               delete [] fname;
+                               continue;
+                       }
+                       delete [] fname;
+
+                       mat->textures.push_back(tex);
+
+                       int textype = assimp_textype(aitype);
+                       if(textype != MTL_TEX_UNKNOWN && !mat->stdtex[textype]) {
+                               mat->stdtex[textype] = tex;
+                       }
+               }
+       }
+
+       /*
        for(size_t i=0; i<sizeof textypes / sizeof *textypes; i++) {
                aiString aipath;
 
@@ -158,7 +207,7 @@ static bool load_material(Material *mat, const aiMaterial *aimat)
        return true;
 }
 
-static SceneNode *load_node(const aiScene *aiscn, unsigned int flags, const aiNode *ainode)
+static SceneNode *load_node(Scene *scn, const aiScene *aiscn, unsigned int flags, const aiNode *ainode)
 {
        SceneNode *node = new SceneNode;
        node->set_name(ainode->mName.data);
@@ -171,15 +220,16 @@ static SceneNode *load_node(const aiScene *aiscn, unsigned int flags, const aiNo
                        ObjMesh *obj = new ObjMesh;
                        obj->mesh = mesh;
                        // also grab the material of this mesh
-                       load_material(&obj->mtl, aiscn->mMaterials[aimesh->mMaterialIndex]);
+                       load_material(scn, &obj->mtl, aiscn->mMaterials[aimesh->mMaterialIndex]);
 
                        node->add_object(obj);
+                       scn->objects.push_back(obj);
                }
        }
 
        /* recurse to all children */
        for(unsigned int i=0; i<ainode->mNumChildren; i++) {
-               SceneNode *child = load_node(aiscn, flags, ainode->mChildren[i]);
+               SceneNode *child = load_node(scn, aiscn, flags, ainode->mChildren[i]);
                if(child) {
                        node->add_child(child);
                }
@@ -189,7 +239,7 @@ static SceneNode *load_node(const aiScene *aiscn, unsigned int flags, const aiNo
        return node;
 }
 
-static Mesh *load_mesh(const aiScene *aiscn, unsigned int flags, const aiMesh *aimesh)
+static Mesh *load_mesh(Scene *scn, const aiScene *aiscn, unsigned int flags, const aiMesh *aimesh)
 {
        Mesh *mesh = new Mesh;
 
@@ -207,6 +257,9 @@ static Mesh *load_mesh(const aiScene *aiscn, unsigned int flags, const aiMesh *a
        if(aimesh->mTextureCoords[0]) {
                mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 3, num_verts, (float*)aimesh->mTextureCoords[0]);
        }
+       if(aimesh->mTextureCoords[1]) {
+               mesh->set_attrib_data(MESH_ATTR_TEXCOORD2, 3, num_verts, (float*)aimesh->mTextureCoords[1]);
+       }
 
        if(flags & SCNLOAD_FLIPYZ) {
                Vec3 *vptr = (Vec3*)mesh->get_attrib_data(MESH_ATTR_VERTEX);
@@ -239,62 +292,21 @@ static Mesh *load_mesh(const aiScene *aiscn, unsigned int flags, const aiMesh *a
        return mesh;
 }
 
-#if 0
-static Vec3 assimp_vector(const aiVector3D &v)
+static int assimp_textype(aiTextureType type)
 {
-       return Vec3(v[0], v[1], v[2]);
-}
-
-static Quat assimp_quat(const aiQuaternion &q)
-{
-       return Quat(q.x, q.y, q.z, q.w);
-}
-
-static Mat4 assimp_matrix(const aiMatrix4x4 &aim)
-{
-       Mat4 m;
-       memcpy(m[0], &aim, 16 * sizeof(float));
-       m.transpose();
-       return m;
-}
-
-/* convert an assimp keyframe time (ticks) into milliseconds */
-static long assimp_time(const aiAnimation *anim, double aitime)
-{
-       double sec;
-       if(anim->mTicksPerSecond < 1e-6) {
-               // assume time is in frames?
-               sec = aitime / 30.0;
-       } else {
-               sec = aitime / anim->mTicksPerSecond;
-       }
-       return (long)(sec * 1000.0);
-}
-
-static void print_hierarchy(const aiNode *node)
-{
-       static int lvl;
-       static int lvlopen[256];
-
-       for(int i=0; i<lvl; i++) {
-               putchar(' ');
-               if(lvlopen[i]) {
-                       putchar(i >= lvl - 1 ? '+' : '|');
-               } else {
-                       putchar(i >= lvl - 1 ? '+' : ' ');
-               }
-       }
-       printf("- \"%s\"\n", node->mName.data);
-
-       lvlopen[lvl] = 1;
-
-       lvl++;
-       for(unsigned int i=0; i<node->mNumChildren; i++) {
-               if(i == node->mNumChildren - 1) {
-                       lvlopen[lvl - 1] = 0;
-               }
-               print_hierarchy(node->mChildren[i]);
+       switch(type) {
+       case aiTextureType_DIFFUSE:
+               return MTL_TEX_DIFFUSE;
+       case aiTextureType_SPECULAR:
+               return MTL_TEX_SPECULAR;
+       case aiTextureType_NORMALS:
+               return MTL_TEX_NORMALMAP;
+       case aiTextureType_LIGHTMAP:
+               return MTL_TEX_LIGHTMAP;
+       case aiTextureType_REFLECTION:
+               return MTL_TEX_ENVMAP;
+       default:
+               break;
        }
-       lvl--;
+       return MTL_TEX_UNKNOWN;
 }
-#endif /* 0 */
index a787abd..5bf291d 100644 (file)
@@ -381,14 +381,17 @@ static int glfmt_from_ifmt(unsigned int ifmt)
        switch(ifmt) {
        case GL_LUMINANCE16F_ARB:
        case GL_LUMINANCE32F_ARB:
+       case GL_SLUMINANCE:
                return GL_LUMINANCE;
 
        case GL_RGB16F:
        case GL_RGB32F:
+       case GL_SRGB:
                return GL_RGB;
 
        case GL_RGBA16F:
        case GL_RGBA32F:
+       case GL_SRGB_ALPHA:
                return GL_RGBA;
 
        default:
@@ -421,15 +424,15 @@ static int glifmt_from_imgfmt(Image::Format fmt)
 {
        switch(fmt) {
        case Image::FMT_GREY:
-               return GL_LUMINANCE;
+               return GL_SLUMINANCE;
        case Image::FMT_GREY_FLOAT:
                return GL_LUMINANCE16F_ARB;
        case Image::FMT_RGB:
-               return GL_RGB;
+               return GL_SRGB;
        case Image::FMT_RGB_FLOAT:
                return GL_RGB16F;
        case Image::FMT_RGBA:
-               return GL_RGBA;
+               return GL_SRGB_ALPHA;
        case Image::FMT_RGBA_FLOAT:
                return GL_RGBA16F;
        default: