tavli
changeset 6:a0d30f6f20d4
- texture coordinate generation in class Mesh
- wood texture
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 26 Jun 2015 04:22:06 +0300 |
parents | e48b40a3c82a |
children | f1ecc2439802 |
files | Makefile src/board.cc src/game.cc src/mesh.cc src/mesh.h src/object.cc src/object.h src/pnoise.cc src/pnoise.h |
diffstat | 9 files changed, 350 insertions(+), 16 deletions(-) [+] |
line diff
1.1 --- a/Makefile Thu Jun 25 20:43:34 2015 +0300 1.2 +++ b/Makefile Fri Jun 26 04:22:06 2015 +0300 1.3 @@ -2,6 +2,7 @@ 1.4 1.5 src = $(wildcard src/*.cc) 1.6 obj = $(src:.cc=.o) 1.7 +dep = $(obj:.o=.d) 1.8 1.9 bin = tavli 1.10 1.11 @@ -17,10 +18,19 @@ 1.12 $(bin): $(obj) 1.13 $(CXX) -o $@ $(obj) $(LDFLAGS) 1.14 1.15 +-include $(dep) 1.16 + 1.17 +%.d: %.cc 1.18 + @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ 1.19 + 1.20 .PHONY: clean 1.21 clean: 1.22 rm -f $(obj) $(bin) 1.23 1.24 +.PHONY: cleandep 1.25 +cleandep: 1.26 + rm -f $(dep) 1.27 + 1.28 .PHONY: install 1.29 install: $(bin) 1.30 mkdir -p $(PREFIX)/bin
2.1 --- a/src/board.cc Thu Jun 25 20:43:34 2015 +0300 2.2 +++ b/src/board.cc Fri Jun 26 04:22:06 2015 +0300 2.3 @@ -1,7 +1,7 @@ 2.4 #include "opengl.h" 2.5 #include "board.h" 2.6 #include "meshgen.h" 2.7 - 2.8 +#include "pnoise.h" 2.9 2.10 Board::Board() 2.11 { 2.12 @@ -109,9 +109,15 @@ 2.13 sides->append(tmp); 2.14 tmp.clear(); 2.15 2.16 + // generate texture coordinates 2.17 + sides->texcoord_gen_box(); 2.18 + 2.19 Object *osides = new Object; 2.20 osides->set_mesh(sides); 2.21 osides->xform() = obottom->xform(); 2.22 + osides->set_texture(img_wood.texture()); 2.23 + osides->tex_xform().set_scaling(Vector3(2, 2, 2)); 2.24 + osides->tex_xform().rotate(-Vector3(1, 0, 0.5), M_PI / 4.0); 2.25 obj.push_back(osides); 2.26 2.27 } 2.28 @@ -137,6 +143,17 @@ 2.29 ohinges->set_mesh(hinges); 2.30 obj.push_back(ohinges); 2.31 2.32 + // debug object 2.33 + /*Mesh *dbgmesh = new Mesh; 2.34 + gen_box(dbgmesh, 0.5, 0.5, 0.5); 2.35 + xform.set_translation(Vector3(0, 0.4, 0)); 2.36 + xform.set_scaling(Vector3(4, 1, 4)); 2.37 + dbgmesh->apply_xform(xform); 2.38 + Object *dbgobj = new Object; 2.39 + dbgobj->set_mesh(dbgmesh); 2.40 + dbgobj->set_texture(img_wood.texture()); 2.41 + dbgobj->tex_xform().set_scaling(Vector3(3, 3, 3)); 2.42 + obj.push_back(dbgobj);*/ 2.43 2.44 return true; 2.45 } 2.46 @@ -157,6 +174,20 @@ 2.47 return val < 0.0 ? 0.0 : (val > 1.0 ? 1.0 : val); 2.48 } 2.49 2.50 +static float wood_tile(float x, float y) 2.51 +{ 2.52 + float u = x; 2.53 + float v = y; 2.54 + x *= 10.0; 2.55 + y *= 10.0; 2.56 + 2.57 + float val = x + pnoise2(u * 6.0, v, 6, 1) * 3.0 + 2.58 + pturbulence2(u * 4, v * 2, 4, 2, 2) * 1.5 + pturbulence2(u * 8, v * 8, 8, 8, 2) * 0.5; 2.59 + 2.60 + val = fmod(val, 1.0); 2.61 + return val < 0.0 ? 0.0 : (val > 1.0 ? 1.0 : val); 2.62 +} 2.63 + 2.64 static bool spike(float x, float y) 2.65 { 2.66 x = fmod(x * 5.0, 1.0); 2.67 @@ -185,20 +216,18 @@ 2.68 2.69 bool Board::generate_textures() 2.70 { 2.71 + // ---- board field texture ---- 2.72 static const Vector3 wcol1 = Vector3(0.6, 0.4, 0.2); 2.73 - static const Vector3 wcol2 = Vector3(0.53, 0.32, 0.1);//Vector3(0.38, 0.25, 0.08); 2.74 + static const Vector3 wcol2 = Vector3(0.53, 0.32, 0.1); 2.75 + static const Vector3 wcol3 = Vector3(0.38, 0.25, 0.08); 2.76 2.77 - const int xsz = 512; 2.78 - const int ysz = 1024; 2.79 + img_field.create(512, 1024); 2.80 + unsigned char *pptr = img_field.pixels; 2.81 + for(int i=0; i<img_field.height; i++) { 2.82 + float v = (float)i / (float)img_field.height; 2.83 2.84 - img_field.create(xsz, ysz); 2.85 - 2.86 - unsigned char *pptr = img_field.pixels; 2.87 - for(int i=0; i<ysz; i++) { 2.88 - float v = (float)i / (float)ysz; 2.89 - 2.90 - for(int j=0; j<xsz; j++) { 2.91 - float u = (float)j / (float)xsz; 2.92 + for(int j=0; j<img_field.width; j++) { 2.93 + float u = (float)j / (float)img_field.width; 2.94 2.95 int r = 0, g = 0, b = 0; 2.96 2.97 @@ -231,7 +260,29 @@ 2.98 pptr += 3; 2.99 } 2.100 } 2.101 + img_field.texture(); 2.102 2.103 - img_field.texture(); 2.104 + // ---- generic wood texture ---- 2.105 + img_wood.create(256, 256); 2.106 + pptr = img_wood.pixels; 2.107 + for(int i=0; i<img_wood.height; i++) { 2.108 + float v = (float)i / (float)img_wood.height; 2.109 + for(int j=0; j<img_wood.width; j++) { 2.110 + float u = (float)j / (float)img_wood.width; 2.111 + 2.112 + float wood_val = wood_tile(u, v); 2.113 + Vector3 wood_color = lerp(wcol2, wcol3, wood_val) * 0.7; 2.114 + 2.115 + int r = (int)(wood_color.x * 255.0); 2.116 + int g = (int)(wood_color.y * 255.0); 2.117 + int b = (int)(wood_color.z * 255.0); 2.118 + 2.119 + pptr[0] = r > 255 ? 255 : r; 2.120 + pptr[1] = g > 255 ? 255 : g; 2.121 + pptr[2] = b > 255 ? 255 : b; 2.122 + pptr += 3; 2.123 + } 2.124 + } 2.125 + img_wood.texture(); 2.126 return true; 2.127 }
3.1 --- a/src/game.cc Thu Jun 25 20:43:34 2015 +0300 3.2 +++ b/src/game.cc Fri Jun 26 04:22:06 2015 +0300 3.3 @@ -52,8 +52,10 @@ 3.4 glRotatef(cam_phi, 1, 0, 0); 3.5 glRotatef(cam_theta, 0, 1, 0); 3.6 3.7 + float ldir[] = {-1, 2, 1, 0}; 3.8 + glLightfv(GL_LIGHT0, GL_POSITION, ldir); 3.9 + 3.10 draw_backdrop(); 3.11 - 3.12 board.draw(); 3.13 } 3.14
4.1 --- a/src/mesh.cc Thu Jun 25 20:43:34 2015 +0300 4.2 +++ b/src/mesh.cc Fri Jun 26 04:22:06 2015 +0300 4.3 @@ -931,6 +931,72 @@ 4.4 } 4.5 4.6 4.7 +// texture coordinate manipulation 4.8 +void Mesh::texcoord_apply_xform(const Matrix4x4 &xform) 4.9 +{ 4.10 + if(!has_attrib(MESH_ATTR_TEXCOORD)) { 4.11 + return; 4.12 + } 4.13 + 4.14 + for(unsigned int i=0; i<nverts; i++) { 4.15 + Vector4 tc = get_attrib(MESH_ATTR_TEXCOORD, i); 4.16 + set_attrib(MESH_ATTR_TEXCOORD, i, tc.transformed(xform)); 4.17 + } 4.18 +} 4.19 + 4.20 +void Mesh::texcoord_gen_plane(const Vector3 &norm, const Vector3 &tang) 4.21 +{ 4.22 + if(!nverts) return; 4.23 + 4.24 + if(!has_attrib(MESH_ATTR_TEXCOORD)) { 4.25 + // allocate texture coordinate attribute array 4.26 + set_attrib_data(MESH_ATTR_TEXCOORD, 2, nverts); 4.27 + } 4.28 + 4.29 + Vector3 n = norm.normalized(); 4.30 + Vector3 b = cross_product(n, tang).normalized(); 4.31 + Vector3 t = cross_product(b, n); 4.32 + 4.33 + for(unsigned int i=0; i<nverts; i++) { 4.34 + Vector3 pos = get_attrib(MESH_ATTR_VERTEX, i); 4.35 + 4.36 + // distance along the tangent direction 4.37 + float u = dot_product(pos, t); 4.38 + // distance along the bitangent direction 4.39 + float v = dot_product(pos, b); 4.40 + 4.41 + set_attrib(MESH_ATTR_TEXCOORD, i, Vector4(u, v, 0, 1)); 4.42 + } 4.43 +} 4.44 + 4.45 +void Mesh::texcoord_gen_box() 4.46 +{ 4.47 + if(!nverts || !has_attrib(MESH_ATTR_NORMAL)) return; 4.48 + 4.49 + if(!has_attrib(MESH_ATTR_TEXCOORD)) { 4.50 + // allocate texture coordinate attribute array 4.51 + set_attrib_data(MESH_ATTR_TEXCOORD, 2, nverts); 4.52 + } 4.53 + 4.54 + for(unsigned int i=0; i<nverts; i++) { 4.55 + Vector3 pos = Vector3(get_attrib(MESH_ATTR_VERTEX, i)) * 0.5 + Vector3(0.5, 0.5, 0.5); 4.56 + Vector3 norm = get_attrib(MESH_ATTR_NORMAL, i); 4.57 + 4.58 + float abs_nx = fabs(norm.x); 4.59 + float abs_ny = fabs(norm.y); 4.60 + float abs_nz = fabs(norm.z); 4.61 + int dom = abs_nx > abs_ny && abs_nx > abs_nz ? 0 : (abs_ny > abs_nz ? 1 : 2); 4.62 + 4.63 + float uv[2], *uvptr = uv; 4.64 + for(int j=0; j<3; j++) { 4.65 + if(j == dom) continue; // skip dominant axis 4.66 + 4.67 + *uvptr++ = pos[j]; 4.68 + } 4.69 + set_attrib(MESH_ATTR_TEXCOORD, i, Vector4(uv[0], uv[1], 0, 1)); 4.70 + } 4.71 +} 4.72 + 4.73 // ------ private member functions ------ 4.74 4.75 void Mesh::calc_aabb()
5.1 --- a/src/mesh.h Thu Jun 25 20:43:34 2015 +0300 5.2 +++ b/src/mesh.h Fri Jun 26 04:22:06 2015 +0300 5.3 @@ -220,6 +220,11 @@ 5.4 * If you intend to use it in a speed-critical part of the code, you'll *have* to optimize it! 5.5 */ 5.6 bool intersect(const Ray &ray, HitPoint *hit = 0) const; 5.7 + 5.8 + // texture coordinate manipulation 5.9 + void texcoord_apply_xform(const Matrix4x4 &xform); 5.10 + void texcoord_gen_plane(const Vector3 &norm, const Vector3 &tang); 5.11 + void texcoord_gen_box(); 5.12 }; 5.13 5.14 #endif // MESH_H_
6.1 --- a/src/object.cc Thu Jun 25 20:43:34 2015 +0300 6.2 +++ b/src/object.cc Fri Jun 26 04:22:06 2015 +0300 6.3 @@ -5,6 +5,11 @@ 6.4 { 6.5 mesh = 0; 6.6 tex = 0; 6.7 + 6.8 + mtl.diffuse = Vector3(1, 1, 1); 6.9 + mtl.specular = Vector3(0, 0, 0); 6.10 + mtl.shininess = 60.0; 6.11 + mtl.alpha = 1.0; 6.12 } 6.13 6.14 Object::~Object() 6.15 @@ -22,6 +27,16 @@ 6.16 return matrix; 6.17 } 6.18 6.19 +Matrix4x4 &Object::tex_xform() 6.20 +{ 6.21 + return tex_matrix; 6.22 +} 6.23 + 6.24 +const Matrix4x4 &Object::tex_xform() const 6.25 +{ 6.26 + return tex_matrix; 6.27 +} 6.28 + 6.29 void Object::set_mesh(Mesh *m) 6.30 { 6.31 this->mesh = m; 6.32 @@ -44,6 +59,10 @@ 6.33 if(tex) { 6.34 glBindTexture(GL_TEXTURE_2D, tex); 6.35 glEnable(GL_TEXTURE_2D); 6.36 + 6.37 + glMatrixMode(GL_TEXTURE); 6.38 + glPushMatrix(); 6.39 + glLoadTransposeMatrixf(tex_matrix[0]); 6.40 } else { 6.41 glDisable(GL_TEXTURE_2D); 6.42 } 6.43 @@ -52,13 +71,23 @@ 6.44 glPushMatrix(); 6.45 glMultTransposeMatrixf(matrix[0]); 6.46 6.47 + float dcol[] = {mtl.diffuse.x, mtl.diffuse.y, mtl.diffuse.z, mtl.alpha}; 6.48 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dcol); 6.49 + float scol[] = {mtl.specular.x, mtl.specular.y, mtl.specular.z, 1.0f}; 6.50 + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, scol); 6.51 + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mtl.shininess); 6.52 + 6.53 mesh->draw(); 6.54 6.55 - glPopMatrix(); 6.56 - 6.57 if(tex) { 6.58 glDisable(GL_TEXTURE_2D); 6.59 + 6.60 + glMatrixMode(GL_TEXTURE); 6.61 + glPopMatrix(); 6.62 } 6.63 + 6.64 + glMatrixMode(GL_MODELVIEW); 6.65 + glPopMatrix(); 6.66 } 6.67 6.68 bool Object::intersect(const Ray &ray, HitPoint *hit) const
7.1 --- a/src/object.h Thu Jun 25 20:43:34 2015 +0300 7.2 +++ b/src/object.h Fri Jun 26 04:22:06 2015 +0300 7.3 @@ -3,20 +3,34 @@ 7.4 7.5 #include "mesh.h" 7.6 #include "geom.h" 7.7 +#include "vmath/vmath.h" 7.8 + 7.9 +struct Material { 7.10 + Vector3 diffuse; 7.11 + Vector3 specular; 7.12 + float shininess; 7.13 + float alpha; 7.14 +}; 7.15 7.16 class Object { 7.17 private: 7.18 Mesh *mesh; 7.19 Matrix4x4 matrix; 7.20 unsigned int tex; 7.21 + Matrix4x4 tex_matrix; 7.22 7.23 public: 7.24 + Material mtl; 7.25 + 7.26 Object(); 7.27 ~Object(); 7.28 7.29 Matrix4x4 &xform(); 7.30 const Matrix4x4 &xform() const; 7.31 7.32 + Matrix4x4 &tex_xform(); 7.33 + const Matrix4x4 &tex_xform() const; 7.34 + 7.35 void set_mesh(Mesh *m); 7.36 Mesh *get_mesh() const; 7.37
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/pnoise.cc Fri Jun 26 04:22:06 2015 +0300 8.3 @@ -0,0 +1,149 @@ 8.4 +#include <stdlib.h> 8.5 +#include "pnoise.h" 8.6 +#include "vmath/vmath.h" 8.7 + 8.8 +#define B 0x100 8.9 +#define BM 0xff 8.10 +#define N 0x1000 8.11 +#define NP 12 8.12 +#define NM 0xfff 8.13 + 8.14 +#define s_curve(t) ((t) * (t) * (3.0f - 2.0f * (t))) 8.15 +#define setup(elem, b0, b1, r0, r1) \ 8.16 + do { \ 8.17 + float t = elem + N; \ 8.18 + b0 = ((int)t) & BM; \ 8.19 + b1 = (b0 + 1) & BM; \ 8.20 + r0 = t - (int)t; \ 8.21 + r1 = r0 - 1.0f; \ 8.22 + } while(0) 8.23 + 8.24 +#define setup_p(elem, b0, b1, r0, r1, p) \ 8.25 + do { \ 8.26 + float t = elem + N; \ 8.27 + b0 = (((int)t) & BM) % p; \ 8.28 + b1 = ((b0 + 1) & BM) % p; \ 8.29 + r0 = t - (int)t; \ 8.30 + r1 = r0 - 1.0f; \ 8.31 + } while(0) 8.32 + 8.33 +static int perm[B + B + 2]; 8.34 +static vec2_t grad2[B + B + 2]; 8.35 +static bool tables_valid; 8.36 + 8.37 +static void init_noise() 8.38 +{ 8.39 + for(int i=0; i<B; i++) { 8.40 + perm[i] = i; 8.41 + 8.42 + grad2[i].x = (float)((rand() % (B + B)) - B) / B; 8.43 + grad2[i].y = (float)((rand() % (B + B)) - B) / B; 8.44 + grad2[i] = v2_normalize(grad2[i]); 8.45 + } 8.46 + 8.47 + for(int i=0; i<B; i++) { 8.48 + int rand_idx = rand() % B; 8.49 + 8.50 + int tmp = perm[i]; 8.51 + perm[i] = perm[rand_idx]; 8.52 + perm[rand_idx] = tmp; 8.53 + } 8.54 + 8.55 + for(int i=0; i<B+2; i++) { 8.56 + perm[B + i] = perm[i]; 8.57 + grad2[B + i] = grad2[i]; 8.58 + } 8.59 +} 8.60 + 8.61 +#define lerp(a, b, t) ((a) + ((b) - (a)) * t) 8.62 + 8.63 +float dbg_noise2(float x, float y) 8.64 +{ 8.65 + if(!tables_valid) { 8.66 + init_noise(); 8.67 + tables_valid = true; 8.68 + } 8.69 + 8.70 + int bx0, bx1, by0, by1; 8.71 + float rx0, rx1, ry0, ry1; 8.72 + setup(x, bx0, bx1, rx0, rx1); 8.73 + setup(y, by0, by1, ry0, ry1); 8.74 + 8.75 + int i = perm[bx0]; 8.76 + int j = perm[bx1]; 8.77 + 8.78 + int b00 = perm[i + by0]; 8.79 + int b10 = perm[j + by0]; 8.80 + int b01 = perm[i + by1]; 8.81 + int b11 = perm[j + by1]; 8.82 + 8.83 + float sx = s_curve(rx0); 8.84 + float sy = s_curve(ry0); 8.85 + 8.86 + vec2_t g00 = grad2[b00]; 8.87 + vec2_t g10 = grad2[b10]; 8.88 + vec2_t g01 = grad2[b01]; 8.89 + vec2_t g11 = grad2[b11]; 8.90 + 8.91 + float u = g00.x * rx0 + g00.y * ry0; 8.92 + float v = g10.x * rx1 + g10.y * ry0; 8.93 + float a = lerp(u, v, sx); 8.94 + 8.95 + u = g01.x * rx0 + g01.y * ry1; 8.96 + v = g11.x * rx1 + g11.y * ry1; 8.97 + float b = lerp(u, v, sx); 8.98 + 8.99 + return lerp(a, b, sy); 8.100 +} 8.101 + 8.102 +float pnoise2(float x, float y, int periodx, int periody) 8.103 +{ 8.104 + if(!tables_valid) { 8.105 + init_noise(); 8.106 + tables_valid = true; 8.107 + } 8.108 + 8.109 + int bx0, bx1, by0, by1; 8.110 + float rx0, rx1, ry0, ry1; 8.111 + setup_p(x, bx0, bx1, rx0, rx1, periodx); 8.112 + setup_p(y, by0, by1, ry0, ry1, periody); 8.113 + 8.114 + int i = perm[bx0]; 8.115 + int j = perm[bx1]; 8.116 + 8.117 + int b00 = perm[i + by0]; 8.118 + int b10 = perm[j + by0]; 8.119 + int b01 = perm[i + by1]; 8.120 + int b11 = perm[j + by1]; 8.121 + 8.122 + float sx = s_curve(rx0); 8.123 + float sy = s_curve(ry0); 8.124 + 8.125 + vec2_t g00 = grad2[b00]; 8.126 + vec2_t g10 = grad2[b10]; 8.127 + vec2_t g01 = grad2[b01]; 8.128 + vec2_t g11 = grad2[b11]; 8.129 + 8.130 + float u = g00.x * rx0 + g00.y * ry0; 8.131 + float v = g10.x * rx1 + g10.y * ry0; 8.132 + float a = lerp(u, v, sx); 8.133 + 8.134 + u = g01.x * rx0 + g01.y * ry1; 8.135 + v = g11.x * rx1 + g11.y * ry1; 8.136 + float b = lerp(u, v, sx); 8.137 + 8.138 + return lerp(a, b, sy); 8.139 +} 8.140 + 8.141 +float pturbulence2(float x, float y, int periodx, int periody, int octaves) 8.142 +{ 8.143 + int i; 8.144 + float res = 0.0f, freq = 1.0f; 8.145 + for(i=0; i<octaves; i++) { 8.146 + res += fabs(pnoise2(x * freq, y * freq, periodx, periody) / freq); 8.147 + freq *= 2.0f; 8.148 + periodx *= 2; 8.149 + periody *= 2; 8.150 + } 8.151 + return res; 8.152 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/pnoise.h Fri Jun 26 04:22:06 2015 +0300 9.3 @@ -0,0 +1,8 @@ 9.4 +#ifndef PNOISE_H_ 9.5 +#define PNOISE_H_ 9.6 + 9.7 +float dbg_noise2(float x, float y); 9.8 +float pnoise2(float x, float y, int periodx, int periody); 9.9 +float pturbulence2(float x, float y, int periodx, int periody, int octaves); 9.10 + 9.11 +#endif // PNOISE_H_