ld33_umonster
changeset 0:4a6683050e29
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 22 Aug 2015 07:15:00 +0300 |
parents | |
children | bed0e207acb6 |
files | .hgignore Makefile sdr/shadow-notex.p.glsl sdr/shadow.p.glsl sdr/shadow.v.glsl src/game.cc src/game.h src/geom.cc src/geom.h src/light.cc src/light.h src/main.cc src/mesh.cc src/mesh.h src/meshgen.cc src/meshgen.h src/object.cc src/object.h src/opengl.c src/opengl.h src/opt.cc src/opt.h src/pnoise.cc src/pnoise.h src/scene.cc src/scene.h src/sdr.c src/sdr.h src/shader.cc src/shader.h src/shadow.cc src/shadow.h src/snode.cc src/snode.h |
diffstat | 34 files changed, 4450 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Sat Aug 22 07:15:00 2015 +0300 1.3 @@ -0,0 +1,4 @@ 1.4 +\.o$ 1.5 +\.d$ 1.6 +\.swp$ 1.7 +^umonster$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Sat Aug 22 07:15:00 2015 +0300 2.3 @@ -0,0 +1,35 @@ 2.4 +ccsrc = $(wildcard src/*.cc) 2.5 +csrc = $(wildcard src/*.c) 2.6 +obj = $(csrc:.c=.o) $(ccsrc:.cc=.o) 2.7 +dep = $(obj:.o=.d) 2.8 + 2.9 +bin = umonster 2.10 + 2.11 +sys = $(shell uname -s) 2.12 + 2.13 +CFLAGS = -pedantic -Wall -g 2.14 +CXXFLAGS = $(CFLAGS) 2.15 +LDFLAGS = $(libgl_$(sys)) -lvmath -limago -lpsys -lanim -lm 2.16 + 2.17 +libgl_Linux = -lGL -lGLU -lglut -lGLEW 2.18 +libgl_Darwin = -framework OpenGL -framework GLUT -lGLEW 2.19 + 2.20 + 2.21 +$(bin): $(obj) 2.22 + $(CXX) -o $@ $(obj) $(LDFLAGS) 2.23 + 2.24 +-include $(dep) 2.25 + 2.26 +%.d: %.c 2.27 + @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ 2.28 + 2.29 +%.d: %.cc 2.30 + @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ 2.31 + 2.32 +.PHONY: clean 2.33 +clean: 2.34 + rm -f $(obj) $(bin) 2.35 + 2.36 +.PHONY: cleandep 2.37 +cleandep: 2.38 + rm -f $(dep)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/sdr/shadow-notex.p.glsl Sat Aug 22 07:15:00 2015 +0300 3.3 @@ -0,0 +1,29 @@ 3.4 +/* vi: set ft=glsl */ 3.5 +uniform sampler2DShadow shadowmap; 3.6 + 3.7 +varying vec3 vdir, ldir, normal; 3.8 +varying vec4 shadow_tc; 3.9 + 3.10 +#define KD gl_FrontMaterial.diffuse.rgb 3.11 +#define KS gl_FrontMaterial.specular.rgb 3.12 +#define SPOW gl_FrontMaterial.shininess 3.13 + 3.14 +void main() 3.15 +{ 3.16 + float shadow = shadow2DProj(shadowmap, shadow_tc).x; 3.17 + 3.18 + vec3 n = normalize(normal); 3.19 + vec3 v = normalize(vdir); 3.20 + vec3 l = normalize(ldir); 3.21 + vec3 h = normalize(l + v); 3.22 + 3.23 + float ndotl = max(dot(n, l), 0.0); 3.24 + float ndoth = max(dot(n, h), 0.0); 3.25 + 3.26 + vec3 diffuse = KD * gl_LightSource[0].diffuse.rgb * ndotl; 3.27 + vec3 specular = KS * gl_LightSource[0].specular.rgb * pow(ndoth, SPOW); 3.28 + 3.29 + vec3 ambient = gl_LightModel.ambient.rgb * KD; 3.30 + gl_FragColor.rgb = ambient + (diffuse + specular) * shadow; 3.31 + gl_FragColor.a = gl_FrontMaterial.diffuse.a; 3.32 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/sdr/shadow.p.glsl Sat Aug 22 07:15:00 2015 +0300 4.3 @@ -0,0 +1,32 @@ 4.4 +/* vi: set ft=glsl */ 4.5 +uniform sampler2D tex; 4.6 +uniform sampler2DShadow shadowmap; 4.7 + 4.8 +varying vec3 vdir, ldir, normal; 4.9 +varying vec4 shadow_tc; 4.10 + 4.11 +#define KD gl_FrontMaterial.diffuse.rgb 4.12 +#define KS gl_FrontMaterial.specular.rgb 4.13 +#define SPOW gl_FrontMaterial.shininess 4.14 + 4.15 +void main() 4.16 +{ 4.17 + float shadow = shadow2DProj(shadowmap, shadow_tc).x; 4.18 + vec4 texel = texture2D(tex, gl_TexCoord[0].st); 4.19 + 4.20 + vec3 n = normalize(normal); 4.21 + vec3 v = normalize(vdir); 4.22 + vec3 l = normalize(ldir); 4.23 + vec3 h = normalize(l + v); 4.24 + 4.25 + float ndotl = max(dot(n, l), 0.0); 4.26 + float ndoth = max(dot(n, h), 0.0); 4.27 + 4.28 + vec3 albedo = KD * texel.rgb; 4.29 + vec3 diffuse = albedo * gl_LightSource[0].diffuse.rgb * ndotl; 4.30 + vec3 specular = KS * gl_LightSource[0].specular.rgb * pow(ndoth, SPOW); 4.31 + 4.32 + vec3 ambient = gl_LightModel.ambient.rgb * albedo; 4.33 + gl_FragColor.rgb = ambient + (diffuse + specular) * shadow; 4.34 + gl_FragColor.a = gl_FrontMaterial.diffuse.a * texel.a; 4.35 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/sdr/shadow.v.glsl Sat Aug 22 07:15:00 2015 +0300 5.3 @@ -0,0 +1,21 @@ 5.4 +varying vec3 vdir, ldir, normal; 5.5 +varying vec4 shadow_tc; 5.6 + 5.7 +void main() 5.8 +{ 5.9 + gl_Position = ftransform(); 5.10 + 5.11 + vec3 vpos = (gl_ModelViewMatrix * gl_Vertex).xyz; 5.12 + normal = gl_NormalMatrix * gl_Normal; 5.13 + vdir = -vpos; 5.14 + ldir = gl_LightSource[0].position.xyz - vpos; 5.15 + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; 5.16 + 5.17 + mat4 offmat = mat4(0.5, 0.0, 0.0, 0.0, 5.18 + 0.0, 0.5, 0.0, 0.0, 5.19 + 0.0, 0.0, 0.5, 0.0, 5.20 + 0.5, 0.5, 0.5, 1.0); 5.21 + mat4 tex_matrix = offmat * gl_TextureMatrix[1]; 5.22 + 5.23 + shadow_tc = tex_matrix * vec4(vpos, 1.0); 5.24 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/game.cc Sat Aug 22 07:15:00 2015 +0300 6.3 @@ -0,0 +1,219 @@ 6.4 +#include <stdio.h> 6.5 +#include <assert.h> 6.6 +#include "opengl.h" 6.7 +#include "game.h" 6.8 +#include "sdr.h" 6.9 +#include "shader.h" 6.10 +#include "shadow.h" 6.11 +#include "opt.h" 6.12 + 6.13 +static void draw_scene(); 6.14 + 6.15 +int win_width, win_height; 6.16 +unsigned long cur_time; 6.17 +bool dbg_wireframe; 6.18 +int dbg_int; 6.19 + 6.20 +unsigned int sdr_shadow, sdr_shadow_notex; 6.21 + 6.22 +static float cam_theta, cam_phi = 25, cam_dist = 8; 6.23 +static bool bnstate[8]; 6.24 +static int prev_x, prev_y; 6.25 + 6.26 +static unsigned int modkeys; 6.27 + 6.28 + 6.29 +bool game_init() 6.30 +{ 6.31 + if(init_opengl() == -1) { 6.32 + return false; 6.33 + } 6.34 + 6.35 + glEnable(GL_DEPTH_TEST); 6.36 + glEnable(GL_CULL_FACE); 6.37 + glEnable(GL_NORMALIZE); 6.38 + glEnable(GL_LIGHTING); 6.39 + glEnable(GL_LIGHT0); 6.40 + 6.41 + float amb[] = {0.3, 0.3, 0.3, 1.0}; 6.42 + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb); 6.43 + 6.44 + if(glcaps.sep_spec) { 6.45 + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); 6.46 + } 6.47 + glEnable(GL_MULTISAMPLE); 6.48 + 6.49 + if(!init_shadow(4096)) { 6.50 + fprintf(stderr, "failed to initialize shadowmaps\n"); 6.51 + return false; 6.52 + } 6.53 + if(!(sdr_shadow = create_program_load("sdr/shadow.v.glsl", "sdr/shadow.p.glsl"))) { 6.54 + return false; 6.55 + } 6.56 + set_uniform_int(sdr_shadow, "tex", 0); 6.57 + set_uniform_int(sdr_shadow, "shadowmap", 1); 6.58 + 6.59 + if(!(sdr_shadow_notex = create_program_load("sdr/shadow.v.glsl", "sdr/shadow-notex.p.glsl"))) { 6.60 + return false; 6.61 + } 6.62 + set_uniform_int(sdr_shadow_notex, "shadowmap", 1); 6.63 + 6.64 + 6.65 + assert(glGetError() == GL_NO_ERROR); 6.66 + return true; 6.67 +} 6.68 + 6.69 +void game_cleanup() 6.70 +{ 6.71 +} 6.72 + 6.73 +void game_update(unsigned long time_msec) 6.74 +{ 6.75 + cur_time = time_msec; 6.76 +} 6.77 + 6.78 +void game_display() 6.79 +{ 6.80 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 6.81 + 6.82 + glMatrixMode(GL_MODELVIEW); 6.83 + glLoadIdentity(); 6.84 + glTranslatef(0, 0.1, -cam_dist); 6.85 + glRotatef(cam_phi, 1, 0, 0); 6.86 + glRotatef(cam_theta, 0, 1, 0); 6.87 + 6.88 + float lpos[] = {-10, 20, 10, 1}; 6.89 + glLightfv(GL_LIGHT0, GL_POSITION, lpos); 6.90 + 6.91 + if(opt.shadows && sdr_shadow) { 6.92 + begin_shadow_pass(Vector3(lpos[0], lpos[1], lpos[2]), Vector3(0, 0, 0), 5); 6.93 + draw_scene(); 6.94 + end_shadow_pass(); 6.95 + 6.96 + glActiveTexture(GL_TEXTURE1); 6.97 + glBindTexture(GL_TEXTURE_2D, get_shadow_tex()); 6.98 + 6.99 + glMatrixMode(GL_TEXTURE); 6.100 + Matrix4x4 shadow_matrix = get_shadow_matrix(); 6.101 + glLoadTransposeMatrixf(shadow_matrix[0]); 6.102 + 6.103 + glActiveTexture(GL_TEXTURE0); 6.104 + glMatrixMode(GL_MODELVIEW); 6.105 + 6.106 + set_shader(sdr_shadow_notex); 6.107 + 6.108 + draw_scene(); 6.109 + 6.110 + glActiveTexture(GL_TEXTURE1); 6.111 + glBindTexture(GL_TEXTURE_2D, 0); 6.112 + glActiveTexture(GL_TEXTURE0); 6.113 + glBindTexture(GL_TEXTURE_2D, 0); 6.114 + } else { 6.115 + draw_scene(); 6.116 + } 6.117 +} 6.118 + 6.119 +static void glmaterial(float r, float g, float b, float spec, float shin) 6.120 +{ 6.121 + float color[] = {r, g, b, 1}; 6.122 + float scolor[] = {spec, spec, spec, 1}; 6.123 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); 6.124 + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, scolor); 6.125 + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shin); 6.126 +} 6.127 + 6.128 +static void draw_scene() 6.129 +{ 6.130 + glPushMatrix(); 6.131 + glTranslatef(0, -1, 0); 6.132 + 6.133 + glmaterial(0.5, 0.5, 0.5, 0.8, 40.0); 6.134 + 6.135 + glBegin(GL_QUADS); 6.136 + glNormal3f(0, 1, 0); 6.137 + glVertex3f(-10, 0, 10); 6.138 + glVertex3f(10, 0, 10); 6.139 + glVertex3f(10, 0, -10); 6.140 + glVertex3f(-10, 0, -10); 6.141 + glEnd(); 6.142 + 6.143 + glPopMatrix(); 6.144 + 6.145 + glmaterial(0.2, 0.3, 1.0, 0.8, 60.0); 6.146 + draw_teapot(); 6.147 +} 6.148 + 6.149 + 6.150 +void game_reshape(int x, int y) 6.151 +{ 6.152 + glMatrixMode(GL_PROJECTION); 6.153 + glLoadIdentity(); 6.154 + gluPerspective(45, (float)x / (float)y, 0.2, 200.0); 6.155 + 6.156 + glViewport(0, 0, x, y); 6.157 +} 6.158 + 6.159 +void game_keyboard(int bn, bool press) 6.160 +{ 6.161 + if(press) { 6.162 + switch(bn) { 6.163 + case 27: 6.164 + quit(); 6.165 + 6.166 + case 'w': 6.167 + dbg_wireframe = !dbg_wireframe; 6.168 + redisplay(); 6.169 + break; 6.170 + 6.171 + case 's': 6.172 + opt.shadows = !opt.shadows; 6.173 + redisplay(); 6.174 + break; 6.175 + } 6.176 + } 6.177 +} 6.178 + 6.179 +void game_modifier_key(int key, bool press) 6.180 +{ 6.181 + if(press) { 6.182 + modkeys |= (1 << key); 6.183 + } else { 6.184 + modkeys &= ~(1 << key); 6.185 + } 6.186 +} 6.187 + 6.188 +void game_mbutton(int bn, bool press, int x, int y) 6.189 +{ 6.190 + bnstate[bn] = press; 6.191 + prev_x = x; 6.192 + prev_y = y; 6.193 + 6.194 + if(modkeys) { 6.195 + return; 6.196 + } 6.197 + 6.198 + if(bn == 0) { 6.199 + } 6.200 +} 6.201 + 6.202 +void game_mmotion(int x, int y) 6.203 +{ 6.204 + int dx = x - prev_x; 6.205 + int dy = y - prev_y; 6.206 + prev_x = x; 6.207 + prev_y = y; 6.208 + 6.209 + if(modkeys) { 6.210 + if(bnstate[0]) { 6.211 + cam_theta += dx * 0.5; 6.212 + cam_phi += dy * 0.5; 6.213 + 6.214 + if(cam_phi < -90) cam_phi = -90; 6.215 + if(cam_phi > 90) cam_phi = 90; 6.216 + } 6.217 + if(bnstate[2]) { 6.218 + cam_dist += dy * 0.1; 6.219 + if(cam_dist < 0.0) cam_dist = 0.0; 6.220 + } 6.221 + } 6.222 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/game.h Sat Aug 22 07:15:00 2015 +0300 7.3 @@ -0,0 +1,30 @@ 7.4 +#ifndef GAME_H_ 7.5 +#define GAME_H_ 7.6 + 7.7 +#include "vmath/vmath.h" 7.8 + 7.9 +extern int win_width, win_height; 7.10 +extern unsigned long cur_time; 7.11 + 7.12 +extern bool dbg_wireframe; 7.13 +extern int dbg_int; 7.14 + 7.15 +enum { MOD_ALT, MOD_CTL, MOD_SHIFT }; 7.16 + 7.17 +bool game_init(); 7.18 +void game_cleanup(); 7.19 +void game_update(unsigned long time_msec); 7.20 +void game_display(); 7.21 +void game_reshape(int x, int y); 7.22 +void game_keyboard(int key, bool press); 7.23 +void game_modifier_key(int key, bool press); 7.24 +void game_mbutton(int bn, bool press, int x, int y); 7.25 +void game_mmotion(int x, int y); 7.26 + 7.27 +void set_fullscreen(bool fs); 7.28 +void redisplay(); 7.29 +void quit(); 7.30 + 7.31 +void draw_teapot(); 7.32 + 7.33 +#endif /* GAME_H_ */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/geom.cc Sat Aug 22 07:15:00 2015 +0300 8.3 @@ -0,0 +1,251 @@ 8.4 +#include <algorithm> 8.5 +#include <float.h> 8.6 +#include "geom.h" 8.7 + 8.8 +GeomObject::~GeomObject() 8.9 +{ 8.10 +} 8.11 + 8.12 + 8.13 +Sphere::Sphere() 8.14 +{ 8.15 + radius = 1.0; 8.16 +} 8.17 + 8.18 +Sphere::Sphere(const Vector3 ¢, float radius) 8.19 + : center(cent) 8.20 +{ 8.21 + this->radius = radius; 8.22 +} 8.23 + 8.24 +void Sphere::set_union(const GeomObject *obj1, const GeomObject *obj2) 8.25 +{ 8.26 + const Sphere *sph1 = dynamic_cast<const Sphere*>(obj1); 8.27 + const Sphere *sph2 = dynamic_cast<const Sphere*>(obj2); 8.28 + 8.29 + if(!sph1 || !sph2) { 8.30 + fprintf(stderr, "Sphere::set_union: arguments must be spheres"); 8.31 + return; 8.32 + } 8.33 + 8.34 + float dist = (sph1->center - sph2->center).length(); 8.35 + float surf_dist = dist - (sph1->radius + sph2->radius); 8.36 + float d1 = sph1->radius + surf_dist / 2.0; 8.37 + float d2 = sph2->radius + surf_dist / 2.0; 8.38 + float t = d1 / (d1 + d2); 8.39 + 8.40 + if(t < 0.0) t = 0.0; 8.41 + if(t > 1.0) t = 1.0; 8.42 + 8.43 + center = sph1->center * t + sph2->center * (1.0 - t); 8.44 + radius = std::max(dist * t + sph2->radius, dist * (1.0f - t) + sph1->radius); 8.45 +} 8.46 + 8.47 +void Sphere::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 8.48 +{ 8.49 + fprintf(stderr, "Sphere::intersection undefined\n"); 8.50 +} 8.51 + 8.52 +bool Sphere::intersect(const Ray &ray, HitPoint *hit) const 8.53 +{ 8.54 + float a = dot_product(ray.dir, ray.dir); 8.55 + float b = 2.0 * ray.dir.x * (ray.origin.x - center.x) + 8.56 + 2.0 * ray.dir.y * (ray.origin.y - center.y) + 8.57 + 2.0 * ray.dir.z * (ray.origin.z - center.z); 8.58 + float c = dot_product(ray.origin, ray.origin) + dot_product(center, center) - 8.59 + 2.0 * dot_product(ray.origin, center) - radius * radius; 8.60 + 8.61 + float discr = b * b - 4.0 * a * c; 8.62 + if(discr < 1e-4) { 8.63 + return false; 8.64 + } 8.65 + 8.66 + float sqrt_discr = sqrt(discr); 8.67 + float t0 = (-b + sqrt_discr) / (2.0 * a); 8.68 + float t1 = (-b - sqrt_discr) / (2.0 * a); 8.69 + 8.70 + if(t0 < 1e-4) 8.71 + t0 = t1; 8.72 + if(t1 < 1e-4) 8.73 + t1 = t0; 8.74 + 8.75 + float t = t0 < t1 ? t0 : t1; 8.76 + if(t < 1e-4) { 8.77 + return false; 8.78 + } 8.79 + 8.80 + // fill the HitPoint structure 8.81 + if(hit) { 8.82 + hit->obj = this; 8.83 + hit->dist = t; 8.84 + hit->pos = ray.origin + ray.dir * t; 8.85 + hit->normal = (hit->pos - center) / radius; 8.86 + } 8.87 + return true; 8.88 +} 8.89 + 8.90 + 8.91 +AABox::AABox() 8.92 +{ 8.93 +} 8.94 + 8.95 +AABox::AABox(const Vector3 &vmin, const Vector3 &vmax) 8.96 + : min(vmin), max(vmax) 8.97 +{ 8.98 +} 8.99 + 8.100 +void AABox::set_union(const GeomObject *obj1, const GeomObject *obj2) 8.101 +{ 8.102 + const AABox *box1 = dynamic_cast<const AABox*>(obj1); 8.103 + const AABox *box2 = dynamic_cast<const AABox*>(obj2); 8.104 + 8.105 + if(!box1 || !box2) { 8.106 + fprintf(stderr, "AABox::set_union: arguments must be AABoxes too\n"); 8.107 + return; 8.108 + } 8.109 + 8.110 + min.x = std::min(box1->min.x, box2->min.x); 8.111 + min.y = std::min(box1->min.y, box2->min.y); 8.112 + min.z = std::min(box1->min.z, box2->min.z); 8.113 + 8.114 + max.x = std::max(box1->max.x, box2->max.x); 8.115 + max.y = std::max(box1->max.y, box2->max.y); 8.116 + max.z = std::max(box1->max.z, box2->max.z); 8.117 +} 8.118 + 8.119 +void AABox::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 8.120 +{ 8.121 + const AABox *box1 = dynamic_cast<const AABox*>(obj1); 8.122 + const AABox *box2 = dynamic_cast<const AABox*>(obj2); 8.123 + 8.124 + if(!box1 || !box2) { 8.125 + fprintf(stderr, "AABox::set_intersection: arguments must be AABoxes too\n"); 8.126 + return; 8.127 + } 8.128 + 8.129 + for(int i=0; i<3; i++) { 8.130 + min[i] = std::max(box1->min[i], box2->min[i]); 8.131 + max[i] = std::min(box1->max[i], box2->max[i]); 8.132 + 8.133 + if(max[i] < min[i]) { 8.134 + max[i] = min[i]; 8.135 + } 8.136 + } 8.137 +} 8.138 + 8.139 +bool AABox::intersect(const Ray &ray, HitPoint *hit) const 8.140 +{ 8.141 + Vector3 param[2] = {min, max}; 8.142 + Vector3 inv_dir(1.0 / ray.dir.x, 1.0 / ray.dir.y, 1.0 / ray.dir.z); 8.143 + int sign[3] = {inv_dir.x < 0, inv_dir.y < 0, inv_dir.z < 0}; 8.144 + 8.145 + float tmin = (param[sign[0]].x - ray.origin.x) * inv_dir.x; 8.146 + float tmax = (param[1 - sign[0]].x - ray.origin.x) * inv_dir.x; 8.147 + float tymin = (param[sign[1]].y - ray.origin.y) * inv_dir.y; 8.148 + float tymax = (param[1 - sign[1]].y - ray.origin.y) * inv_dir.y; 8.149 + 8.150 + if(tmin > tymax || tymin > tmax) { 8.151 + return false; 8.152 + } 8.153 + if(tymin > tmin) { 8.154 + tmin = tymin; 8.155 + } 8.156 + if(tymax < tmax) { 8.157 + tmax = tymax; 8.158 + } 8.159 + 8.160 + float tzmin = (param[sign[2]].z - ray.origin.z) * inv_dir.z; 8.161 + float tzmax = (param[1 - sign[2]].z - ray.origin.z) * inv_dir.z; 8.162 + 8.163 + if(tmin > tzmax || tzmin > tmax) { 8.164 + return false; 8.165 + } 8.166 + if(tzmin > tmin) { 8.167 + tmin = tzmin; 8.168 + } 8.169 + if(tzmax < tmax) { 8.170 + tmax = tzmax; 8.171 + } 8.172 + 8.173 + float t = tmin < 1e-4 ? tmax : tmin; 8.174 + if(t >= 1e-4) { 8.175 + 8.176 + if(hit) { 8.177 + hit->obj = this; 8.178 + hit->dist = t; 8.179 + hit->pos = ray.origin + ray.dir * t; 8.180 + 8.181 + float min_dist = FLT_MAX; 8.182 + Vector3 offs = min + (max - min) / 2.0; 8.183 + Vector3 local_hit = hit->pos - offs; 8.184 + 8.185 + static const Vector3 axis[] = { 8.186 + Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1) 8.187 + }; 8.188 + //int tcidx[][2] = {{2, 1}, {0, 2}, {0, 1}}; 8.189 + 8.190 + for(int i=0; i<3; i++) { 8.191 + float dist = fabs((max[i] - offs[i]) - fabs(local_hit[i])); 8.192 + if(dist < min_dist) { 8.193 + min_dist = dist; 8.194 + hit->normal = axis[i] * (local_hit[i] < 0.0 ? 1.0 : -1.0); 8.195 + //hit->texcoord = Vector2(hit->pos[tcidx[i][0]], hit->pos[tcidx[i][1]]); 8.196 + } 8.197 + } 8.198 + } 8.199 + return true; 8.200 + } 8.201 + return false; 8.202 + 8.203 +} 8.204 + 8.205 +Plane::Plane() 8.206 + : normal(0.0, 1.0, 0.0) 8.207 +{ 8.208 +} 8.209 + 8.210 +Plane::Plane(const Vector3 &p, const Vector3 &norm) 8.211 + : pt(p) 8.212 +{ 8.213 + normal = norm.normalized(); 8.214 +} 8.215 + 8.216 +Plane::Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3) 8.217 + : pt(p1) 8.218 +{ 8.219 + normal = cross_product(p2 - p1, p3 - p1).normalized(); 8.220 +} 8.221 + 8.222 +Plane::Plane(const Vector3 &normal, float dist) 8.223 +{ 8.224 + this->normal = normal.normalized(); 8.225 + pt = this->normal * dist; 8.226 +} 8.227 + 8.228 +void Plane::set_union(const GeomObject *obj1, const GeomObject *obj2) 8.229 +{ 8.230 + fprintf(stderr, "Plane::set_union undefined\n"); 8.231 +} 8.232 + 8.233 +void Plane::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 8.234 +{ 8.235 + fprintf(stderr, "Plane::set_intersection undefined\n"); 8.236 +} 8.237 + 8.238 +bool Plane::intersect(const Ray &ray, HitPoint *hit) const 8.239 +{ 8.240 + float ndotdir = dot_product(normal, ray.dir); 8.241 + if(fabs(ndotdir) < 1e-4) { 8.242 + return false; 8.243 + } 8.244 + 8.245 + if(hit) { 8.246 + Vector3 ptdir = pt - ray.origin; 8.247 + float t = dot_product(normal, ptdir) / ndotdir; 8.248 + 8.249 + hit->pos = ray.origin + ray.dir * t; 8.250 + hit->normal = normal; 8.251 + hit->obj = this; 8.252 + } 8.253 + return true; 8.254 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/geom.h Sat Aug 22 07:15:00 2015 +0300 9.3 @@ -0,0 +1,70 @@ 9.4 +#ifndef GEOMOBJ_H_ 9.5 +#define GEOMOBJ_H_ 9.6 + 9.7 +#include "vmath/vmath.h" 9.8 + 9.9 +class GeomObject; 9.10 +class SceneNode; 9.11 + 9.12 +struct HitPoint { 9.13 + float dist; //< parametric distance along the ray 9.14 + Vector3 pos; //< position of intersection (orig + dir * dist) 9.15 + Vector3 normal; //< normal at the point of intersection 9.16 + const void *obj; //< pointer to the intersected object 9.17 + const SceneNode *node; 9.18 + Ray ray; 9.19 +}; 9.20 + 9.21 +class GeomObject { 9.22 +public: 9.23 + virtual ~GeomObject(); 9.24 + 9.25 + virtual void set_union(const GeomObject *obj1, const GeomObject *obj2) = 0; 9.26 + virtual void set_intersection(const GeomObject *obj1, const GeomObject *obj2) = 0; 9.27 + 9.28 + virtual bool intersect(const Ray &ray, HitPoint *hit = 0) const = 0; 9.29 +}; 9.30 + 9.31 +class Sphere : public GeomObject { 9.32 +public: 9.33 + Vector3 center; 9.34 + float radius; 9.35 + 9.36 + Sphere(); 9.37 + Sphere(const Vector3 ¢er, float radius); 9.38 + 9.39 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 9.40 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 9.41 + 9.42 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 9.43 +}; 9.44 + 9.45 +class AABox : public GeomObject { 9.46 +public: 9.47 + Vector3 min, max; 9.48 + 9.49 + AABox(); 9.50 + AABox(const Vector3 &min, const Vector3 &max); 9.51 + 9.52 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 9.53 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 9.54 + 9.55 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 9.56 +}; 9.57 + 9.58 +class Plane : public GeomObject { 9.59 +public: 9.60 + Vector3 pt, normal; 9.61 + 9.62 + Plane(); 9.63 + Plane(const Vector3 &pt, const Vector3 &normal); 9.64 + Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3); 9.65 + Plane(const Vector3 &normal, float dist); 9.66 + 9.67 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 9.68 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 9.69 + 9.70 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 9.71 +}; 9.72 + 9.73 +#endif // GEOMOBJ_H_
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/light.cc Sat Aug 22 07:15:00 2015 +0300 10.3 @@ -0,0 +1,17 @@ 10.4 +#include "light.h" 10.5 +#include "opengl.h" 10.6 + 10.7 +Light::Light() 10.8 + : color(1, 1, 1) 10.9 +{ 10.10 +} 10.11 + 10.12 +void Light::setup(int idx) const 10.13 +{ 10.14 + float lpos[] = {pos.x, pos.y, pos.z, 1.0}; 10.15 + float col[] = {color.x, color.y, color.z, 1.0}; 10.16 + 10.17 + glLightfv(GL_LIGHT0 + idx, GL_POSITION, lpos); 10.18 + glLightfv(GL_LIGHT0 + idx, GL_DIFFUSE, col); 10.19 + glLightfv(GL_LIGHT0 + idx, GL_SPECULAR, col); 10.20 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/light.h Sat Aug 22 07:15:00 2015 +0300 11.3 @@ -0,0 +1,16 @@ 11.4 +#ifndef LIGHT_H_ 11.5 +#define LIGHT_H_ 11.6 + 11.7 +#include "vmath/vmath.h" 11.8 + 11.9 +class Light { 11.10 +public: 11.11 + Vector3 pos; 11.12 + Vector3 color; 11.13 + 11.14 + Light(); 11.15 + 11.16 + void setup(int idx = 0) const; 11.17 +}; 11.18 + 11.19 +#endif // LIGHT_H_
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/main.cc Sat Aug 22 07:15:00 2015 +0300 12.3 @@ -0,0 +1,148 @@ 12.4 +#include <stdio.h> 12.5 +#include <stdlib.h> 12.6 +#include <assert.h> 12.7 +#ifdef __APPLE__ 12.8 +#include <GLUT/glut.h> 12.9 +#else 12.10 +#include <GL/glut.h> 12.11 +#endif 12.12 +#include "game.h" 12.13 +#include "opt.h" 12.14 + 12.15 +static void display(); 12.16 +static void idle(); 12.17 +static void reshape(int x, int y); 12.18 +static void keydown(unsigned char key, int x, int y); 12.19 +static void keyup(unsigned char key, int x, int y); 12.20 +static void mouse(int bn, int st, int x, int y); 12.21 +static void motion(int x, int y); 12.22 +static void update_modifiers(); 12.23 + 12.24 +static unsigned int start_time; 12.25 + 12.26 +int main(int argc, char **argv) 12.27 +{ 12.28 + glutInit(&argc, argv); 12.29 + if(!init_options(argc, argv)) { 12.30 + return 1; 12.31 + } 12.32 + glutInitWindowSize(opt.xres, opt.yres); 12.33 + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE); 12.34 + glutCreateWindow("umonster"); 12.35 + 12.36 + if(opt.fullscreen) { 12.37 + set_fullscreen(true); 12.38 + } 12.39 + 12.40 + glutDisplayFunc(display); 12.41 + glutIdleFunc(idle); 12.42 + glutReshapeFunc(reshape); 12.43 + glutKeyboardFunc(keydown); 12.44 + glutKeyboardUpFunc(keyup); 12.45 + glutMouseFunc(mouse); 12.46 + glutMotionFunc(motion); 12.47 + glutPassiveMotionFunc(motion); 12.48 + 12.49 + if(!game_init()) { 12.50 + return 1; 12.51 + } 12.52 + atexit(game_cleanup); 12.53 + 12.54 + start_time = glutGet(GLUT_ELAPSED_TIME); 12.55 + glutMainLoop(); 12.56 + return 0; 12.57 +} 12.58 + 12.59 +void set_fullscreen(bool fs) 12.60 +{ 12.61 + if(fs) { 12.62 + glutFullScreen(); 12.63 + } else { 12.64 + glutReshapeWindow(opt.xres, opt.yres); 12.65 + } 12.66 +} 12.67 + 12.68 +void redisplay() 12.69 +{ 12.70 + glutPostRedisplay(); 12.71 +} 12.72 + 12.73 +void quit() 12.74 +{ 12.75 + exit(0); 12.76 +} 12.77 + 12.78 +void draw_teapot() 12.79 +{ 12.80 + glFrontFace(GL_CW); 12.81 + glutSolidTeapot(1.0); 12.82 + glFrontFace(GL_CCW); 12.83 +} 12.84 + 12.85 +static void display() 12.86 +{ 12.87 + unsigned int msec = glutGet(GLUT_ELAPSED_TIME) - start_time; 12.88 + game_update(msec); 12.89 + 12.90 + game_display(); 12.91 + 12.92 + glutSwapBuffers(); 12.93 + assert(glGetError() == GL_NO_ERROR); 12.94 +} 12.95 + 12.96 +static void idle() 12.97 +{ 12.98 + glutPostRedisplay(); 12.99 +} 12.100 + 12.101 +static void reshape(int x, int y) 12.102 +{ 12.103 + win_width = x; 12.104 + win_height = y; 12.105 + game_reshape(x, y); 12.106 +} 12.107 + 12.108 +static void keydown(unsigned char key, int x, int y) 12.109 +{ 12.110 + update_modifiers(); 12.111 + game_keyboard(key, true); 12.112 +} 12.113 + 12.114 +static void keyup(unsigned char key, int x, int y) 12.115 +{ 12.116 + update_modifiers(); 12.117 + game_keyboard(key, false); 12.118 +} 12.119 + 12.120 +static void mouse(int bn, int st, int x, int y) 12.121 +{ 12.122 + update_modifiers(); 12.123 + game_mbutton(bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y); 12.124 +} 12.125 + 12.126 +static void motion(int x, int y) 12.127 +{ 12.128 + game_mmotion(x, y); 12.129 +} 12.130 + 12.131 +static void update_modifiers() 12.132 +{ 12.133 + static unsigned int prev_mod; 12.134 + unsigned int mod = glutGetModifiers(); 12.135 + unsigned int delta = mod ^ prev_mod; 12.136 + 12.137 + if(delta & GLUT_ACTIVE_SHIFT) { 12.138 + bool press = (mod & GLUT_ACTIVE_SHIFT) != 0; 12.139 + game_modifier_key(MOD_SHIFT, press); 12.140 + } 12.141 + if(delta & GLUT_ACTIVE_CTRL) { 12.142 + bool press = (mod & GLUT_ACTIVE_CTRL) != 0; 12.143 + game_modifier_key(MOD_CTL, press); 12.144 + } 12.145 + if(delta & GLUT_ACTIVE_ALT) { 12.146 + bool press = (mod & GLUT_ACTIVE_ALT) != 0; 12.147 + game_modifier_key(MOD_ALT, press); 12.148 + } 12.149 + 12.150 + prev_mod = mod; 12.151 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/mesh.cc Sat Aug 22 07:15:00 2015 +0300 13.3 @@ -0,0 +1,1237 @@ 13.4 +#include <stdio.h> 13.5 +#include <stdlib.h> 13.6 +#include <float.h> 13.7 +#include <assert.h> 13.8 +#include "opengl.h" 13.9 +#include "mesh.h" 13.10 +//#include "xform_node.h" 13.11 + 13.12 +#define USE_OLDGL 13.13 + 13.14 +bool Mesh::use_custom_sdr_attr = true; 13.15 +int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 0, 1, 2, 3, 4, 5, 6 }; 13.16 +/* 13.17 + (int)SDR_ATTR_VERTEX, 13.18 + (int)SDR_ATTR_NORMAL, 13.19 + (int)SDR_ATTR_TANGENT, 13.20 + (int)SDR_ATTR_TEXCOORD, 13.21 + (int)SDR_ATTR_COLOR, 13.22 + -1, -1}; 13.23 +*/ 13.24 +unsigned int Mesh::intersect_mode = ISECT_DEFAULT; 13.25 +float Mesh::vertex_sel_dist = 0.01; 13.26 +float Mesh::vis_vecsize = 1.0; 13.27 + 13.28 +Mesh::Mesh() 13.29 +{ 13.30 + clear(); 13.31 + 13.32 + glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects); 13.33 + 13.34 + for(int i=0; i<NUM_MESH_ATTR; i++) { 13.35 + vattr[i].vbo = buffer_objects[i]; 13.36 + } 13.37 + ibo = buffer_objects[NUM_MESH_ATTR]; 13.38 + wire_ibo = 0; 13.39 +} 13.40 + 13.41 +Mesh::~Mesh() 13.42 +{ 13.43 + glDeleteBuffers(NUM_MESH_ATTR + 1, buffer_objects); 13.44 + 13.45 + if(wire_ibo) { 13.46 + glDeleteBuffers(1, &wire_ibo); 13.47 + } 13.48 +} 13.49 + 13.50 +Mesh::Mesh(const Mesh &rhs) 13.51 +{ 13.52 + clear(); 13.53 + 13.54 + glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects); 13.55 + 13.56 + for(int i=0; i<NUM_MESH_ATTR; i++) { 13.57 + vattr[i].vbo = buffer_objects[i]; 13.58 + } 13.59 + ibo = buffer_objects[NUM_MESH_ATTR]; 13.60 + wire_ibo = 0; 13.61 + 13.62 + clone(rhs); 13.63 +} 13.64 + 13.65 +Mesh &Mesh::operator =(const Mesh &rhs) 13.66 +{ 13.67 + if(&rhs != this) { 13.68 + clone(rhs); 13.69 + } 13.70 + return *this; 13.71 +} 13.72 + 13.73 +bool Mesh::clone(const Mesh &m) 13.74 +{ 13.75 + clear(); 13.76 + 13.77 + for(int i=0; i<NUM_MESH_ATTR; i++) { 13.78 + if(m.has_attrib(i)) { 13.79 + m.get_attrib_data(i); // force validation of the actual data on the source mesh 13.80 + 13.81 + vattr[i].nelem = m.vattr[i].nelem; 13.82 + vattr[i].data = m.vattr[i].data; // copy the actual data 13.83 + vattr[i].data_valid = true; 13.84 + } 13.85 + } 13.86 + 13.87 + if(m.is_indexed()) { 13.88 + m.get_index_data(); // again, force validation 13.89 + 13.90 + // copy the index data 13.91 + idata = m.idata; 13.92 + idata_valid = true; 13.93 + } 13.94 + 13.95 + name = m.name; 13.96 + nverts = m.nverts; 13.97 + nfaces = m.nfaces; 13.98 + 13.99 + //bones = m.bones; 13.100 + 13.101 + memcpy(cur_val, m.cur_val, sizeof cur_val); 13.102 + 13.103 + aabb = m.aabb; 13.104 + aabb_valid = m.aabb_valid; 13.105 + bsph = m.bsph; 13.106 + bsph_valid = m.bsph_valid; 13.107 + 13.108 + hitface = m.hitface; 13.109 + hitvert = m.hitvert; 13.110 + 13.111 + intersect_mode = m.intersect_mode; 13.112 + vertex_sel_dist = m.vertex_sel_dist; 13.113 + vis_vecsize = m.vis_vecsize; 13.114 + 13.115 + return true; 13.116 +} 13.117 + 13.118 +void Mesh::set_name(const char *name) 13.119 +{ 13.120 + this->name = name; 13.121 +} 13.122 + 13.123 +const char *Mesh::get_name() const 13.124 +{ 13.125 + return name.c_str(); 13.126 +} 13.127 + 13.128 +bool Mesh::has_attrib(int attr) const 13.129 +{ 13.130 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 13.131 + return false; 13.132 + } 13.133 + 13.134 + // if neither of these is valid, then nobody has set this attribute 13.135 + return vattr[attr].vbo_valid || vattr[attr].data_valid; 13.136 +} 13.137 + 13.138 +bool Mesh::is_indexed() const 13.139 +{ 13.140 + return ibo_valid || idata_valid; 13.141 +} 13.142 + 13.143 +void Mesh::clear() 13.144 +{ 13.145 + //bones.clear(); 13.146 + 13.147 + for(int i=0; i<NUM_MESH_ATTR; i++) { 13.148 + vattr[i].nelem = 0; 13.149 + vattr[i].vbo_valid = false; 13.150 + vattr[i].data_valid = false; 13.151 + //vattr[i].sdr_loc = -1; 13.152 + vattr[i].data.clear(); 13.153 + } 13.154 + ibo_valid = idata_valid = false; 13.155 + idata.clear(); 13.156 + 13.157 + wire_ibo_valid = false; 13.158 + 13.159 + nverts = nfaces = 0; 13.160 + 13.161 + bsph_valid = false; 13.162 + aabb_valid = false; 13.163 +} 13.164 + 13.165 +float *Mesh::set_attrib_data(int attrib, int nelem, unsigned int num, const float *data) 13.166 +{ 13.167 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 13.168 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 13.169 + return 0; 13.170 + } 13.171 + 13.172 + if(nverts && num != nverts) { 13.173 + fprintf(stderr, "%s: attribute count missmatch (%d instead of %d)\n", __FUNCTION__, num, nverts); 13.174 + return 0; 13.175 + } 13.176 + nverts = num; 13.177 + 13.178 + vattr[attrib].data.clear(); 13.179 + vattr[attrib].nelem = nelem; 13.180 + vattr[attrib].data.resize(num * nelem); 13.181 + 13.182 + if(data) { 13.183 + memcpy(&vattr[attrib].data[0], data, num * nelem * sizeof *data); 13.184 + } 13.185 + 13.186 + vattr[attrib].data_valid = true; 13.187 + vattr[attrib].vbo_valid = false; 13.188 + return &vattr[attrib].data[0]; 13.189 +} 13.190 + 13.191 +float *Mesh::get_attrib_data(int attrib) 13.192 +{ 13.193 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 13.194 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 13.195 + return 0; 13.196 + } 13.197 + 13.198 + vattr[attrib].vbo_valid = false; 13.199 + return (float*)((const Mesh*)this)->get_attrib_data(attrib); 13.200 +} 13.201 + 13.202 +const float *Mesh::get_attrib_data(int attrib) const 13.203 +{ 13.204 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 13.205 + fprintf(stderr, "%s: invalid attrib: %d\n", __FUNCTION__, attrib); 13.206 + return 0; 13.207 + } 13.208 + 13.209 + if(!vattr[attrib].data_valid) { 13.210 +#if GL_ES_VERSION_2_0 13.211 + fprintf(stderr, "%s: can't read back attrib data on CrippledGL ES\n", __FUNCTION__); 13.212 + return 0; 13.213 +#else 13.214 + if(!vattr[attrib].vbo_valid) { 13.215 + fprintf(stderr, "%s: unavailable attrib: %d\n", __FUNCTION__, attrib); 13.216 + return 0; 13.217 + } 13.218 + 13.219 + // local data copy is unavailable, grab the data from the vbo 13.220 + Mesh *m = (Mesh*)this; 13.221 + m->vattr[attrib].data.resize(nverts * vattr[attrib].nelem); 13.222 + 13.223 + glBindBuffer(GL_ARRAY_BUFFER, vattr[attrib].vbo); 13.224 + void *data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); 13.225 + memcpy(&m->vattr[attrib].data[0], data, nverts * vattr[attrib].nelem * sizeof(float)); 13.226 + glUnmapBuffer(GL_ARRAY_BUFFER); 13.227 + 13.228 + vattr[attrib].data_valid = true; 13.229 +#endif 13.230 + } 13.231 + 13.232 + return &vattr[attrib].data[0]; 13.233 +} 13.234 + 13.235 +void Mesh::set_attrib(int attrib, int idx, const Vector4 &v) 13.236 +{ 13.237 + float *data = get_attrib_data(attrib); 13.238 + if(data) { 13.239 + data += idx * vattr[attrib].nelem; 13.240 + for(int i=0; i<vattr[attrib].nelem; i++) { 13.241 + data[i] = v[i]; 13.242 + } 13.243 + } 13.244 +} 13.245 + 13.246 +Vector4 Mesh::get_attrib(int attrib, int idx) const 13.247 +{ 13.248 + Vector4 v(0.0, 0.0, 0.0, 1.0); 13.249 + const float *data = get_attrib_data(attrib); 13.250 + if(data) { 13.251 + data += idx * vattr[attrib].nelem; 13.252 + for(int i=0; i<vattr[attrib].nelem; i++) { 13.253 + v[i] = data[i]; 13.254 + } 13.255 + } 13.256 + return v; 13.257 +} 13.258 + 13.259 +int Mesh::get_attrib_count(int attrib) const 13.260 +{ 13.261 + return has_attrib(attrib) ? nverts : 0; 13.262 +} 13.263 + 13.264 + 13.265 +unsigned int *Mesh::set_index_data(int num, const unsigned int *indices) 13.266 +{ 13.267 + int nidx = nfaces * 3; 13.268 + if(nidx && num != nidx) { 13.269 + fprintf(stderr, "%s: index count missmatch (%d instead of %d)\n", __FUNCTION__, num, nidx); 13.270 + return 0; 13.271 + } 13.272 + nfaces = num / 3; 13.273 + 13.274 + idata.clear(); 13.275 + idata.resize(num); 13.276 + 13.277 + if(indices) { 13.278 + memcpy(&idata[0], indices, num * sizeof *indices); 13.279 + } 13.280 + 13.281 + idata_valid = true; 13.282 + ibo_valid = false; 13.283 + 13.284 + return &idata[0]; 13.285 +} 13.286 + 13.287 +unsigned int *Mesh::get_index_data() 13.288 +{ 13.289 + ibo_valid = false; 13.290 + return (unsigned int*)((const Mesh*)this)->get_index_data(); 13.291 +} 13.292 + 13.293 +const unsigned int *Mesh::get_index_data() const 13.294 +{ 13.295 + if(!idata_valid) { 13.296 +#if GL_ES_VERSION_2_0 13.297 + fprintf(stderr, "%s: can't read back index data in CrippledGL ES\n", __FUNCTION__); 13.298 + return 0; 13.299 +#else 13.300 + if(!ibo_valid) { 13.301 + fprintf(stderr, "%s: indices unavailable\n", __FUNCTION__); 13.302 + return 0; 13.303 + } 13.304 + 13.305 + // local data copy is unavailable, gram the data from the ibo 13.306 + Mesh *m = (Mesh*)this; 13.307 + int nidx = nfaces * 3; 13.308 + m->idata.resize(nidx); 13.309 + 13.310 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 13.311 + void *data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); 13.312 + memcpy(&m->idata[0], data, nidx * sizeof(unsigned int)); 13.313 + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); 13.314 + 13.315 + idata_valid = true; 13.316 +#endif 13.317 + } 13.318 + 13.319 + return &idata[0]; 13.320 +} 13.321 + 13.322 +int Mesh::get_index_count() const 13.323 +{ 13.324 + return nfaces * 3; 13.325 +} 13.326 + 13.327 +void Mesh::append(const Mesh &mesh) 13.328 +{ 13.329 + unsigned int idxoffs = nverts; 13.330 + 13.331 + if(!nverts) { 13.332 + clone(mesh); 13.333 + return; 13.334 + } 13.335 + 13.336 + nverts += mesh.nverts; 13.337 + nfaces += mesh.nfaces; 13.338 + 13.339 + for(int i=0; i<NUM_MESH_ATTR; i++) { 13.340 + if(has_attrib(i) && mesh.has_attrib(i)) { 13.341 + // force validating the data arrays 13.342 + get_attrib_data(i); 13.343 + mesh.get_attrib_data(i); 13.344 + 13.345 + // append the mesh data 13.346 + vattr[i].data.insert(vattr[i].data.end(), mesh.vattr[i].data.begin(), mesh.vattr[i].data.end()); 13.347 + } 13.348 + } 13.349 + 13.350 + if(ibo_valid || idata_valid) { 13.351 + // make index arrays valid 13.352 + get_index_data(); 13.353 + mesh.get_index_data(); 13.354 + 13.355 + size_t orig_sz = idata.size(); 13.356 + 13.357 + idata.insert(idata.end(), mesh.idata.begin(), mesh.idata.end()); 13.358 + 13.359 + // fixup all the new indices 13.360 + for(size_t i=orig_sz; i<idata.size(); i++) { 13.361 + idata[i] += idxoffs; 13.362 + } 13.363 + } 13.364 + 13.365 + // fuck everything 13.366 + wire_ibo_valid = false; 13.367 + aabb_valid = false; 13.368 + bsph_valid = false; 13.369 +} 13.370 + 13.371 +// assemble a complete vertex by adding all the useful attributes 13.372 +void Mesh::vertex(float x, float y, float z) 13.373 +{ 13.374 + cur_val[MESH_ATTR_VERTEX] = Vector4(x, y, z, 1.0f); 13.375 + vattr[MESH_ATTR_VERTEX].data_valid = true; 13.376 + vattr[MESH_ATTR_VERTEX].nelem = 3; 13.377 + 13.378 + for(int i=0; i<NUM_MESH_ATTR; i++) { 13.379 + if(vattr[i].data_valid) { 13.380 + for(int j=0; j<vattr[MESH_ATTR_VERTEX].nelem; j++) { 13.381 + vattr[i].data.push_back(cur_val[i][j]); 13.382 + } 13.383 + } 13.384 + vattr[i].vbo_valid = false; 13.385 + } 13.386 + 13.387 + if(idata_valid) { 13.388 + idata.clear(); 13.389 + } 13.390 + ibo_valid = idata_valid = false; 13.391 +} 13.392 + 13.393 +void Mesh::normal(float nx, float ny, float nz) 13.394 +{ 13.395 + cur_val[MESH_ATTR_NORMAL] = Vector4(nx, ny, nz, 1.0f); 13.396 + vattr[MESH_ATTR_NORMAL].data_valid = true; 13.397 + vattr[MESH_ATTR_NORMAL].nelem = 3; 13.398 +} 13.399 + 13.400 +void Mesh::tangent(float tx, float ty, float tz) 13.401 +{ 13.402 + cur_val[MESH_ATTR_TANGENT] = Vector4(tx, ty, tz, 1.0f); 13.403 + vattr[MESH_ATTR_TANGENT].data_valid = true; 13.404 + vattr[MESH_ATTR_TANGENT].nelem = 3; 13.405 +} 13.406 + 13.407 +void Mesh::texcoord(float u, float v, float w) 13.408 +{ 13.409 + cur_val[MESH_ATTR_TEXCOORD] = Vector4(u, v, w, 1.0f); 13.410 + vattr[MESH_ATTR_TEXCOORD].data_valid = true; 13.411 + vattr[MESH_ATTR_TEXCOORD].nelem = 3; 13.412 +} 13.413 + 13.414 +void Mesh::boneweights(float w1, float w2, float w3, float w4) 13.415 +{ 13.416 + cur_val[MESH_ATTR_BONEWEIGHTS] = Vector4(w1, w2, w3, w4); 13.417 + vattr[MESH_ATTR_BONEWEIGHTS].data_valid = true; 13.418 + vattr[MESH_ATTR_BONEWEIGHTS].nelem = 4; 13.419 +} 13.420 + 13.421 +void Mesh::boneidx(int idx1, int idx2, int idx3, int idx4) 13.422 +{ 13.423 + cur_val[MESH_ATTR_BONEIDX] = Vector4(idx1, idx2, idx3, idx4); 13.424 + vattr[MESH_ATTR_BONEIDX].data_valid = true; 13.425 + vattr[MESH_ATTR_BONEIDX].nelem = 4; 13.426 +} 13.427 + 13.428 +int Mesh::get_poly_count() const 13.429 +{ 13.430 + if(nfaces) { 13.431 + return nfaces; 13.432 + } 13.433 + if(nverts) { 13.434 + return nverts / 3; 13.435 + } 13.436 + return 0; 13.437 +} 13.438 + 13.439 +/// static function 13.440 +void Mesh::set_attrib_location(int attr, int loc) 13.441 +{ 13.442 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 13.443 + return; 13.444 + } 13.445 + Mesh::global_sdr_loc[attr] = loc; 13.446 +} 13.447 + 13.448 +/// static function 13.449 +int Mesh::get_attrib_location(int attr) 13.450 +{ 13.451 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 13.452 + return -1; 13.453 + } 13.454 + return Mesh::global_sdr_loc[attr]; 13.455 +} 13.456 + 13.457 +/// static function 13.458 +void Mesh::clear_attrib_locations() 13.459 +{ 13.460 + for(int i=0; i<NUM_MESH_ATTR; i++) { 13.461 + Mesh::global_sdr_loc[i] = -1; 13.462 + } 13.463 +} 13.464 + 13.465 +/// static function 13.466 +void Mesh::set_vis_vecsize(float sz) 13.467 +{ 13.468 + Mesh::vis_vecsize = sz; 13.469 +} 13.470 + 13.471 +float Mesh::get_vis_vecsize() 13.472 +{ 13.473 + return Mesh::vis_vecsize; 13.474 +} 13.475 + 13.476 +void Mesh::apply_xform(const Matrix4x4 &xform) 13.477 +{ 13.478 + Matrix4x4 dir_xform = xform; 13.479 + dir_xform[0][3] = dir_xform[1][3] = dir_xform[2][3] = 0.0f; 13.480 + dir_xform[3][0] = dir_xform[3][1] = dir_xform[3][2] = 0.0f; 13.481 + dir_xform[3][3] = 1.0f; 13.482 + 13.483 + apply_xform(xform, dir_xform); 13.484 +} 13.485 + 13.486 +void Mesh::apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform) 13.487 +{ 13.488 + for(unsigned int i=0; i<nverts; i++) { 13.489 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 13.490 + set_attrib(MESH_ATTR_VERTEX, i, v.transformed(xform)); 13.491 + 13.492 + if(has_attrib(MESH_ATTR_NORMAL)) { 13.493 + Vector3 n = get_attrib(MESH_ATTR_NORMAL, i); 13.494 + set_attrib(MESH_ATTR_NORMAL, i, n.transformed(dir_xform)); 13.495 + } 13.496 + if(has_attrib(MESH_ATTR_TANGENT)) { 13.497 + Vector3 t = get_attrib(MESH_ATTR_TANGENT, i); 13.498 + set_attrib(MESH_ATTR_TANGENT, i, t.transformed(dir_xform)); 13.499 + } 13.500 + } 13.501 +} 13.502 + 13.503 +void Mesh::flip() 13.504 +{ 13.505 + flip_faces(); 13.506 + flip_normals(); 13.507 +} 13.508 + 13.509 +void Mesh::flip_faces() 13.510 +{ 13.511 + if(is_indexed()) { 13.512 + unsigned int *indices = get_index_data(); 13.513 + if(!indices) return; 13.514 + 13.515 + int idxnum = get_index_count(); 13.516 + for(int i=0; i<idxnum; i+=3) { 13.517 + unsigned int tmp = indices[i + 2]; 13.518 + indices[i + 2] = indices[i + 1]; 13.519 + indices[i + 1] = tmp; 13.520 + } 13.521 + 13.522 + } else { 13.523 + Vector3 *verts = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 13.524 + if(!verts) return; 13.525 + 13.526 + int vnum = get_attrib_count(MESH_ATTR_VERTEX); 13.527 + for(int i=0; i<vnum; i+=3) { 13.528 + Vector3 tmp = verts[i + 2]; 13.529 + verts[i + 2] = verts[i + 1]; 13.530 + verts[i + 1] = tmp; 13.531 + } 13.532 + } 13.533 +} 13.534 + 13.535 +void Mesh::flip_normals() 13.536 +{ 13.537 + Vector3 *normals = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 13.538 + if(!normals) return; 13.539 + 13.540 + int num = get_attrib_count(MESH_ATTR_NORMAL); 13.541 + for(int i=0; i<num; i++) { 13.542 + normals[i] = -normals[i]; 13.543 + } 13.544 +} 13.545 + 13.546 +/* 13.547 +int Mesh::add_bone(XFormNode *bone) 13.548 +{ 13.549 + int idx = bones.size(); 13.550 + bones.push_back(bone); 13.551 + return idx; 13.552 +} 13.553 + 13.554 +const XFormNode *Mesh::get_bone(int idx) const 13.555 +{ 13.556 + if(idx < 0 || idx >= (int)bones.size()) { 13.557 + return 0; 13.558 + } 13.559 + return bones[idx]; 13.560 +} 13.561 + 13.562 +int Mesh::get_bones_count() const 13.563 +{ 13.564 + return (int)bones.size(); 13.565 +} 13.566 +*/ 13.567 + 13.568 +bool Mesh::pre_draw() const 13.569 +{ 13.570 + cur_sdr = 0; 13.571 + if(glcaps.shaders) { 13.572 + glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr); 13.573 + } 13.574 + 13.575 + ((Mesh*)this)->update_buffers(); 13.576 + 13.577 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 13.578 + fprintf(stderr, "%s: invalid vertex buffer\n", __FUNCTION__); 13.579 + return false; 13.580 + } 13.581 + 13.582 + if(cur_sdr && use_custom_sdr_attr) { 13.583 + // rendering with shaders 13.584 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 13.585 + fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__); 13.586 + return false; 13.587 + } 13.588 + 13.589 + for(int i=0; i<NUM_MESH_ATTR; i++) { 13.590 + int loc = global_sdr_loc[i]; 13.591 + if(loc >= 0 && vattr[i].vbo_valid) { 13.592 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 13.593 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 13.594 + glEnableVertexAttribArray(loc); 13.595 + } 13.596 + } 13.597 + } else { 13.598 +#ifndef GL_ES_VERSION_2_0 13.599 + // rendering with fixed-function (not available in GLES2) 13.600 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_VERTEX].vbo); 13.601 + glVertexPointer(vattr[MESH_ATTR_VERTEX].nelem, GL_FLOAT, 0, 0); 13.602 + glEnableClientState(GL_VERTEX_ARRAY); 13.603 + 13.604 + if(vattr[MESH_ATTR_NORMAL].vbo_valid) { 13.605 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_NORMAL].vbo); 13.606 + glNormalPointer(GL_FLOAT, 0, 0); 13.607 + glEnableClientState(GL_NORMAL_ARRAY); 13.608 + } 13.609 + if(vattr[MESH_ATTR_TEXCOORD].vbo_valid) { 13.610 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_TEXCOORD].vbo); 13.611 + glTexCoordPointer(vattr[MESH_ATTR_TEXCOORD].nelem, GL_FLOAT, 0, 0); 13.612 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 13.613 + } 13.614 + if(vattr[MESH_ATTR_COLOR].vbo_valid) { 13.615 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_COLOR].vbo); 13.616 + glColorPointer(vattr[MESH_ATTR_COLOR].nelem, GL_FLOAT, 0, 0); 13.617 + glEnableClientState(GL_COLOR_ARRAY); 13.618 + } 13.619 +#endif 13.620 + } 13.621 + glBindBuffer(GL_ARRAY_BUFFER, 0); 13.622 + 13.623 + return true; 13.624 +} 13.625 + 13.626 +void Mesh::draw() const 13.627 +{ 13.628 + if(!pre_draw()) return; 13.629 + 13.630 + if(ibo_valid) { 13.631 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 13.632 + glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0); 13.633 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 13.634 + } else { 13.635 + glDrawArrays(GL_TRIANGLES, 0, nverts); 13.636 + } 13.637 + 13.638 + post_draw(); 13.639 +} 13.640 + 13.641 +void Mesh::post_draw() const 13.642 +{ 13.643 + if(cur_sdr && use_custom_sdr_attr) { 13.644 + // rendered with shaders 13.645 + for(int i=0; i<NUM_MESH_ATTR; i++) { 13.646 + int loc = global_sdr_loc[i]; 13.647 + if(loc >= 0 && vattr[i].vbo_valid) { 13.648 + glDisableVertexAttribArray(loc); 13.649 + } 13.650 + } 13.651 + } else { 13.652 +#ifndef GL_ES_VERSION_2_0 13.653 + // rendered with fixed-function 13.654 + glDisableClientState(GL_VERTEX_ARRAY); 13.655 + if(vattr[MESH_ATTR_NORMAL].vbo_valid) { 13.656 + glDisableClientState(GL_NORMAL_ARRAY); 13.657 + } 13.658 + if(vattr[MESH_ATTR_TEXCOORD].vbo_valid) { 13.659 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 13.660 + } 13.661 + if(vattr[MESH_ATTR_COLOR].vbo_valid) { 13.662 + glDisableClientState(GL_COLOR_ARRAY); 13.663 + } 13.664 +#endif 13.665 + } 13.666 +} 13.667 + 13.668 +void Mesh::draw_wire() const 13.669 +{ 13.670 + if(!pre_draw()) return; 13.671 + 13.672 + ((Mesh*)this)->update_wire_ibo(); 13.673 + 13.674 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 13.675 + glDrawElements(GL_LINES, nfaces * 6, GL_UNSIGNED_INT, 0); 13.676 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 13.677 + 13.678 + post_draw(); 13.679 +} 13.680 + 13.681 +void Mesh::draw_vertices() const 13.682 +{ 13.683 + if(!pre_draw()) return; 13.684 + 13.685 + glDrawArrays(GL_POINTS, 0, nverts); 13.686 + 13.687 + post_draw(); 13.688 +} 13.689 + 13.690 +void Mesh::draw_normals() const 13.691 +{ 13.692 +#ifdef USE_OLDGL 13.693 + int cur_sdr = 0; 13.694 + if(glcaps.shaders) { 13.695 + glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr); 13.696 + } 13.697 + 13.698 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 13.699 + Vector3 *norm = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 13.700 + if(!varr || !norm) { 13.701 + return; 13.702 + } 13.703 + 13.704 + glBegin(GL_LINES); 13.705 + if(cur_sdr && use_custom_sdr_attr) { 13.706 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 13.707 + if(vert_loc < 0) { 13.708 + glEnd(); 13.709 + return; 13.710 + } 13.711 + 13.712 + for(size_t i=0; i<nverts; i++) { 13.713 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 13.714 + Vector3 end = varr[i] + norm[i] * vis_vecsize; 13.715 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 13.716 + } 13.717 + } else { 13.718 + for(size_t i=0; i<nverts; i++) { 13.719 + glVertex3f(varr[i].x, varr[i].y, varr[i].z); 13.720 + Vector3 end = varr[i] + norm[i] * vis_vecsize; 13.721 + glVertex3f(end.x, end.y, end.z); 13.722 + } 13.723 + } 13.724 + glEnd(); 13.725 +#endif // USE_OLDGL 13.726 +} 13.727 + 13.728 +void Mesh::draw_tangents() const 13.729 +{ 13.730 +#ifdef USE_OLDGL 13.731 + int cur_sdr = 0; 13.732 + if(glcaps.shaders) { 13.733 + glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr); 13.734 + } 13.735 + 13.736 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 13.737 + Vector3 *tang = (Vector3*)get_attrib_data(MESH_ATTR_TANGENT); 13.738 + if(!varr || !tang) { 13.739 + return; 13.740 + } 13.741 + 13.742 + glBegin(GL_LINES); 13.743 + if(cur_sdr && use_custom_sdr_attr) { 13.744 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 13.745 + if(vert_loc < 0) { 13.746 + glEnd(); 13.747 + return; 13.748 + } 13.749 + 13.750 + for(size_t i=0; i<nverts; i++) { 13.751 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 13.752 + Vector3 end = varr[i] + tang[i] * vis_vecsize; 13.753 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 13.754 + } 13.755 + } else { 13.756 + for(size_t i=0; i<nverts; i++) { 13.757 + glVertex3f(varr[i].x, varr[i].y, varr[i].z); 13.758 + Vector3 end = varr[i] + tang[i] * vis_vecsize; 13.759 + glVertex3f(end.x, end.y, end.z); 13.760 + } 13.761 + } 13.762 + glEnd(); 13.763 +#endif // USE_OLDGL 13.764 +} 13.765 + 13.766 +void Mesh::get_aabbox(Vector3 *vmin, Vector3 *vmax) const 13.767 +{ 13.768 + if(!aabb_valid) { 13.769 + ((Mesh*)this)->calc_aabb(); 13.770 + } 13.771 + *vmin = aabb.min; 13.772 + *vmax = aabb.max; 13.773 +} 13.774 + 13.775 +const AABox &Mesh::get_aabbox() const 13.776 +{ 13.777 + if(!aabb_valid) { 13.778 + ((Mesh*)this)->calc_aabb(); 13.779 + } 13.780 + return aabb; 13.781 +} 13.782 + 13.783 +float Mesh::get_bsphere(Vector3 *center, float *rad) const 13.784 +{ 13.785 + if(!bsph_valid) { 13.786 + ((Mesh*)this)->calc_bsph(); 13.787 + } 13.788 + *center = bsph.center; 13.789 + *rad = bsph.radius; 13.790 + return bsph.radius; 13.791 +} 13.792 + 13.793 +const Sphere &Mesh::get_bsphere() const 13.794 +{ 13.795 + if(!bsph_valid) { 13.796 + ((Mesh*)this)->calc_bsph(); 13.797 + } 13.798 + return bsph; 13.799 +} 13.800 + 13.801 +/// static function 13.802 +void Mesh::set_intersect_mode(unsigned int mode) 13.803 +{ 13.804 + Mesh::intersect_mode = mode; 13.805 +} 13.806 + 13.807 +/// static function 13.808 +unsigned int Mesh::get_intersect_mode() 13.809 +{ 13.810 + return Mesh::intersect_mode; 13.811 +} 13.812 + 13.813 +/// static function 13.814 +void Mesh::set_vertex_select_distance(float dist) 13.815 +{ 13.816 + Mesh::vertex_sel_dist = dist; 13.817 +} 13.818 + 13.819 +/// static function 13.820 +float Mesh::get_vertex_select_distance() 13.821 +{ 13.822 + return Mesh::vertex_sel_dist; 13.823 +} 13.824 + 13.825 +bool Mesh::intersect(const Ray &ray, HitPoint *hit) const 13.826 +{ 13.827 + assert((Mesh::intersect_mode & (ISECT_VERTICES | ISECT_FACE)) != (ISECT_VERTICES | ISECT_FACE)); 13.828 + 13.829 + const Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 13.830 + const Vector3 *narr = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 13.831 + if(!varr) { 13.832 + return false; 13.833 + } 13.834 + const unsigned int *idxarr = get_index_data(); 13.835 + 13.836 + // first test with the bounding box 13.837 + AABox box; 13.838 + get_aabbox(&box.min, &box.max); 13.839 + if(!box.intersect(ray)) { 13.840 + return false; 13.841 + } 13.842 + 13.843 + HitPoint nearest_hit; 13.844 + nearest_hit.dist = FLT_MAX; 13.845 + nearest_hit.obj = 0; 13.846 + 13.847 + if(Mesh::intersect_mode & ISECT_VERTICES) { 13.848 + // we asked for "intersections" with the vertices of the mesh 13.849 + long nearest_vidx = -1; 13.850 + float thres_sq = Mesh::vertex_sel_dist * Mesh::vertex_sel_dist; 13.851 + 13.852 + for(unsigned int i=0; i<nverts; i++) { 13.853 + 13.854 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(narr[i], ray.dir) > 0) { 13.855 + continue; 13.856 + } 13.857 + 13.858 + // project the vertex onto the ray line 13.859 + float t = dot_product(varr[i] - ray.origin, ray.dir); 13.860 + Vector3 vproj = ray.origin + ray.dir * t; 13.861 + 13.862 + float dist_sq = (vproj - varr[i]).length_sq(); 13.863 + if(dist_sq < thres_sq) { 13.864 + if(!hit) { 13.865 + return true; 13.866 + } 13.867 + if(t < nearest_hit.dist) { 13.868 + nearest_hit.dist = t; 13.869 + nearest_vidx = i; 13.870 + } 13.871 + } 13.872 + } 13.873 + 13.874 + if(nearest_vidx != -1) { 13.875 + hitvert = varr[nearest_vidx]; 13.876 + nearest_hit.obj = &hitvert; 13.877 + } 13.878 + 13.879 + } else { 13.880 + // regular intersection test with polygons 13.881 + 13.882 + for(unsigned int i=0; i<nfaces; i++) { 13.883 + Triangle face(i, varr, idxarr); 13.884 + 13.885 + // ignore back-facing polygons if the mode flags include ISECT_FRONT 13.886 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(face.get_normal(), ray.dir) > 0) { 13.887 + continue; 13.888 + } 13.889 + 13.890 + HitPoint fhit; 13.891 + if(face.intersect(ray, hit ? &fhit : 0)) { 13.892 + if(!hit) { 13.893 + return true; 13.894 + } 13.895 + if(fhit.dist < nearest_hit.dist) { 13.896 + nearest_hit = fhit; 13.897 + hitface = face; 13.898 + } 13.899 + } 13.900 + } 13.901 + } 13.902 + 13.903 + if(nearest_hit.obj) { 13.904 + if(hit) { 13.905 + *hit = nearest_hit; 13.906 + 13.907 + // if we are interested in the mesh and not the faces set obj to this 13.908 + if(Mesh::intersect_mode & ISECT_FACE) { 13.909 + hit->obj = &hitface; 13.910 + } else if(Mesh::intersect_mode & ISECT_VERTICES) { 13.911 + hit->obj = &hitvert; 13.912 + } else { 13.913 + hit->obj = this; 13.914 + } 13.915 + } 13.916 + return true; 13.917 + } 13.918 + return false; 13.919 +} 13.920 + 13.921 + 13.922 +// texture coordinate manipulation 13.923 +void Mesh::texcoord_apply_xform(const Matrix4x4 &xform) 13.924 +{ 13.925 + if(!has_attrib(MESH_ATTR_TEXCOORD)) { 13.926 + return; 13.927 + } 13.928 + 13.929 + for(unsigned int i=0; i<nverts; i++) { 13.930 + Vector4 tc = get_attrib(MESH_ATTR_TEXCOORD, i); 13.931 + set_attrib(MESH_ATTR_TEXCOORD, i, tc.transformed(xform)); 13.932 + } 13.933 +} 13.934 + 13.935 +void Mesh::texcoord_gen_plane(const Vector3 &norm, const Vector3 &tang) 13.936 +{ 13.937 + if(!nverts) return; 13.938 + 13.939 + if(!has_attrib(MESH_ATTR_TEXCOORD)) { 13.940 + // allocate texture coordinate attribute array 13.941 + set_attrib_data(MESH_ATTR_TEXCOORD, 2, nverts); 13.942 + } 13.943 + 13.944 + Vector3 n = norm.normalized(); 13.945 + Vector3 b = cross_product(n, tang).normalized(); 13.946 + Vector3 t = cross_product(b, n); 13.947 + 13.948 + for(unsigned int i=0; i<nverts; i++) { 13.949 + Vector3 pos = get_attrib(MESH_ATTR_VERTEX, i); 13.950 + 13.951 + // distance along the tangent direction 13.952 + float u = dot_product(pos, t); 13.953 + // distance along the bitangent direction 13.954 + float v = dot_product(pos, b); 13.955 + 13.956 + set_attrib(MESH_ATTR_TEXCOORD, i, Vector4(u, v, 0, 1)); 13.957 + } 13.958 +} 13.959 + 13.960 +void Mesh::texcoord_gen_box() 13.961 +{ 13.962 + if(!nverts || !has_attrib(MESH_ATTR_NORMAL)) return; 13.963 + 13.964 + if(!has_attrib(MESH_ATTR_TEXCOORD)) { 13.965 + // allocate texture coordinate attribute array 13.966 + set_attrib_data(MESH_ATTR_TEXCOORD, 2, nverts); 13.967 + } 13.968 + 13.969 + for(unsigned int i=0; i<nverts; i++) { 13.970 + Vector3 pos = Vector3(get_attrib(MESH_ATTR_VERTEX, i)) * 0.5 + Vector3(0.5, 0.5, 0.5); 13.971 + Vector3 norm = get_attrib(MESH_ATTR_NORMAL, i); 13.972 + 13.973 + float abs_nx = fabs(norm.x); 13.974 + float abs_ny = fabs(norm.y); 13.975 + float abs_nz = fabs(norm.z); 13.976 + int dom = abs_nx > abs_ny && abs_nx > abs_nz ? 0 : (abs_ny > abs_nz ? 1 : 2); 13.977 + 13.978 + float uv[2], *uvptr = uv; 13.979 + for(int j=0; j<3; j++) { 13.980 + if(j == dom) continue; // skip dominant axis 13.981 + 13.982 + *uvptr++ = pos[j]; 13.983 + } 13.984 + set_attrib(MESH_ATTR_TEXCOORD, i, Vector4(uv[0], uv[1], 0, 1)); 13.985 + } 13.986 +} 13.987 + 13.988 +// ------ private member functions ------ 13.989 + 13.990 +void Mesh::calc_aabb() 13.991 +{ 13.992 + // the cast is to force calling the const version which doesn't invalidate 13.993 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 13.994 + return; 13.995 + } 13.996 + 13.997 + aabb.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX); 13.998 + aabb.max = -aabb.min; 13.999 + 13.1000 + for(unsigned int i=0; i<nverts; i++) { 13.1001 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 13.1002 + for(int j=0; j<3; j++) { 13.1003 + if(v[j] < aabb.min[j]) { 13.1004 + aabb.min[j] = v[j]; 13.1005 + } 13.1006 + if(v[j] > aabb.max[j]) { 13.1007 + aabb.max[j] = v[j]; 13.1008 + } 13.1009 + } 13.1010 + } 13.1011 + aabb_valid = true; 13.1012 +} 13.1013 + 13.1014 +void Mesh::calc_bsph() 13.1015 +{ 13.1016 + // the cast is to force calling the const version which doesn't invalidate 13.1017 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 13.1018 + return; 13.1019 + } 13.1020 + 13.1021 + Vector3 v; 13.1022 + bsph.center = Vector3(0, 0, 0); 13.1023 + 13.1024 + // first find the center 13.1025 + for(unsigned int i=0; i<nverts; i++) { 13.1026 + v = get_attrib(MESH_ATTR_VERTEX, i); 13.1027 + bsph.center += v; 13.1028 + } 13.1029 + bsph.center /= (float)nverts; 13.1030 + 13.1031 + bsph.radius = 0.0f; 13.1032 + for(unsigned int i=0; i<nverts; i++) { 13.1033 + v = get_attrib(MESH_ATTR_VERTEX, i); 13.1034 + float dist_sq = (v - bsph.center).length_sq(); 13.1035 + if(dist_sq > bsph.radius) { 13.1036 + bsph.radius = dist_sq; 13.1037 + } 13.1038 + } 13.1039 + bsph.radius = sqrt(bsph.radius); 13.1040 + 13.1041 + bsph_valid = true; 13.1042 +} 13.1043 + 13.1044 +void Mesh::update_buffers() 13.1045 +{ 13.1046 + for(int i=0; i<NUM_MESH_ATTR; i++) { 13.1047 + if(has_attrib(i) && !vattr[i].vbo_valid) { 13.1048 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 13.1049 + glBufferData(GL_ARRAY_BUFFER, nverts * vattr[i].nelem * sizeof(float), &vattr[i].data[0], GL_STATIC_DRAW); 13.1050 + vattr[i].vbo_valid = true; 13.1051 + } 13.1052 + } 13.1053 + glBindBuffer(GL_ARRAY_BUFFER, 0); 13.1054 + 13.1055 + if(idata_valid && !ibo_valid) { 13.1056 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 13.1057 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), &idata[0], GL_STATIC_DRAW); 13.1058 + ibo_valid = true; 13.1059 + } 13.1060 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 13.1061 +} 13.1062 + 13.1063 +void Mesh::update_wire_ibo() 13.1064 +{ 13.1065 + update_buffers(); 13.1066 + 13.1067 + if(wire_ibo_valid) { 13.1068 + return; 13.1069 + } 13.1070 + 13.1071 + if(!wire_ibo) { 13.1072 + glGenBuffers(1, &wire_ibo); 13.1073 + } 13.1074 + 13.1075 + unsigned int *wire_idxarr = new unsigned int[nfaces * 6]; 13.1076 + unsigned int *dest = wire_idxarr; 13.1077 + 13.1078 + if(ibo_valid) { 13.1079 + // we're dealing with an indexed mesh 13.1080 + const unsigned int *idxarr = ((const Mesh*)this)->get_index_data(); 13.1081 + 13.1082 + for(unsigned int i=0; i<nfaces; i++) { 13.1083 + *dest++ = idxarr[0]; 13.1084 + *dest++ = idxarr[1]; 13.1085 + *dest++ = idxarr[1]; 13.1086 + *dest++ = idxarr[2]; 13.1087 + *dest++ = idxarr[2]; 13.1088 + *dest++ = idxarr[0]; 13.1089 + idxarr += 3; 13.1090 + } 13.1091 + } else { 13.1092 + // not an indexed mesh ... 13.1093 + for(unsigned int i=0; i<nfaces; i++) { 13.1094 + int vidx = i * 3; 13.1095 + *dest++ = vidx; 13.1096 + *dest++ = vidx + 1; 13.1097 + *dest++ = vidx + 1; 13.1098 + *dest++ = vidx + 2; 13.1099 + *dest++ = vidx + 2; 13.1100 + *dest++ = vidx; 13.1101 + } 13.1102 + } 13.1103 + 13.1104 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 13.1105 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 6 * sizeof(unsigned int), wire_idxarr, GL_STATIC_DRAW); 13.1106 + delete [] wire_idxarr; 13.1107 + wire_ibo_valid = true; 13.1108 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 13.1109 +} 13.1110 + 13.1111 + 13.1112 +// ------ class Triangle ------ 13.1113 +Triangle::Triangle() 13.1114 +{ 13.1115 + normal_valid = false; 13.1116 + id = -1; 13.1117 +} 13.1118 + 13.1119 +Triangle::Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2) 13.1120 +{ 13.1121 + v[0] = v0; 13.1122 + v[1] = v1; 13.1123 + v[2] = v2; 13.1124 + normal_valid = false; 13.1125 + id = -1; 13.1126 +} 13.1127 + 13.1128 +Triangle::Triangle(int n, const Vector3 *varr, const unsigned int *idxarr) 13.1129 +{ 13.1130 + if(idxarr) { 13.1131 + v[0] = varr[idxarr[n * 3]]; 13.1132 + v[1] = varr[idxarr[n * 3 + 1]]; 13.1133 + v[2] = varr[idxarr[n * 3 + 2]]; 13.1134 + } else { 13.1135 + v[0] = varr[n * 3]; 13.1136 + v[1] = varr[n * 3 + 1]; 13.1137 + v[2] = varr[n * 3 + 2]; 13.1138 + } 13.1139 + normal_valid = false; 13.1140 + id = n; 13.1141 +} 13.1142 + 13.1143 +void Triangle::calc_normal() 13.1144 +{ 13.1145 + normal = cross_product(v[1] - v[0], v[2] - v[0]).normalized(); 13.1146 + normal_valid = true; 13.1147 +} 13.1148 + 13.1149 +const Vector3 &Triangle::get_normal() const 13.1150 +{ 13.1151 + if(!normal_valid) { 13.1152 + ((Triangle*)this)->calc_normal(); 13.1153 + } 13.1154 + return normal; 13.1155 +} 13.1156 + 13.1157 +void Triangle::transform(const Matrix4x4 &xform) 13.1158 +{ 13.1159 + v[0].transform(xform); 13.1160 + v[1].transform(xform); 13.1161 + v[2].transform(xform); 13.1162 + normal_valid = false; 13.1163 +} 13.1164 + 13.1165 +void Triangle::draw() const 13.1166 +{ 13.1167 + Vector3 n[3]; 13.1168 + n[0] = get_normal(); 13.1169 + n[1] = get_normal(); 13.1170 + n[2] = get_normal(); 13.1171 + 13.1172 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 13.1173 + int nloc = Mesh::get_attrib_location(MESH_ATTR_NORMAL); 13.1174 + 13.1175 + glEnableVertexAttribArray(vloc); 13.1176 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 13.1177 + glVertexAttribPointer(nloc, 3, GL_FLOAT, GL_FALSE, 0, &n[0].x); 13.1178 + 13.1179 + glDrawArrays(GL_TRIANGLES, 0, 3); 13.1180 + 13.1181 + glDisableVertexAttribArray(vloc); 13.1182 + glDisableVertexAttribArray(nloc); 13.1183 +} 13.1184 + 13.1185 +void Triangle::draw_wire() const 13.1186 +{ 13.1187 + static const int idxarr[] = {0, 1, 1, 2, 2, 0}; 13.1188 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 13.1189 + 13.1190 + glEnableVertexAttribArray(vloc); 13.1191 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 13.1192 + 13.1193 + glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, idxarr); 13.1194 + 13.1195 + glDisableVertexAttribArray(vloc); 13.1196 +} 13.1197 + 13.1198 +Vector3 Triangle::calc_barycentric(const Vector3 &pos) const 13.1199 +{ 13.1200 + Vector3 norm = get_normal(); 13.1201 + 13.1202 + float area_sq = fabs(dot_product(cross_product(v[1] - v[0], v[2] - v[0]), norm)); 13.1203 + if(area_sq < 1e-5) { 13.1204 + return Vector3(0, 0, 0); 13.1205 + } 13.1206 + 13.1207 + float asq0 = fabs(dot_product(cross_product(v[1] - pos, v[2] - pos), norm)); 13.1208 + float asq1 = fabs(dot_product(cross_product(v[2] - pos, v[0] - pos), norm)); 13.1209 + float asq2 = fabs(dot_product(cross_product(v[0] - pos, v[1] - pos), norm)); 13.1210 + 13.1211 + return Vector3(asq0 / area_sq, asq1 / area_sq, asq2 / area_sq); 13.1212 +} 13.1213 + 13.1214 +bool Triangle::intersect(const Ray &ray, HitPoint *hit) const 13.1215 +{ 13.1216 + Vector3 normal = get_normal(); 13.1217 + 13.1218 + float ndotdir = dot_product(ray.dir, normal); 13.1219 + if(fabs(ndotdir) < 1e-4) { 13.1220 + return false; 13.1221 + } 13.1222 + 13.1223 + Vector3 vertdir = v[0] - ray.origin; 13.1224 + float t = dot_product(normal, vertdir) / ndotdir; 13.1225 + 13.1226 + Vector3 pos = ray.origin + ray.dir * t; 13.1227 + Vector3 bary = calc_barycentric(pos); 13.1228 + 13.1229 + if(bary.x + bary.y + bary.z > 1.00001) { 13.1230 + return false; 13.1231 + } 13.1232 + 13.1233 + if(hit) { 13.1234 + hit->dist = t; 13.1235 + hit->pos = ray.origin + ray.dir * t; 13.1236 + hit->normal = normal; 13.1237 + hit->obj = this; 13.1238 + } 13.1239 + return true; 13.1240 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/mesh.h Sat Aug 22 07:15:00 2015 +0300 14.3 @@ -0,0 +1,236 @@ 14.4 +#ifndef MESH_H_ 14.5 +#define MESH_H_ 14.6 + 14.7 +#include <string> 14.8 +#include <vector> 14.9 +#include "vmath/vmath.h" 14.10 +#include "geom.h" 14.11 + 14.12 +enum { 14.13 + MESH_ATTR_VERTEX, 14.14 + MESH_ATTR_NORMAL, 14.15 + MESH_ATTR_TANGENT, 14.16 + MESH_ATTR_TEXCOORD, 14.17 + MESH_ATTR_COLOR, 14.18 + MESH_ATTR_BONEWEIGHTS, 14.19 + MESH_ATTR_BONEIDX, 14.20 + 14.21 + NUM_MESH_ATTR 14.22 +}; 14.23 + 14.24 +// intersection mode flags 14.25 +enum { 14.26 + ISECT_DEFAULT = 0, // default (whole mesh, all intersections) 14.27 + ISECT_FRONT = 1, // front-faces only 14.28 + ISECT_FACE = 2, // return intersected face pointer instead of mesh 14.29 + ISECT_VERTICES = 4 // return (?) TODO 14.30 +}; 14.31 + 14.32 +//class XFormNode; 14.33 + 14.34 + 14.35 +class Triangle { 14.36 +public: 14.37 + Vector3 v[3]; 14.38 + Vector3 normal; 14.39 + bool normal_valid; 14.40 + int id; 14.41 + 14.42 + Triangle(); 14.43 + Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2); 14.44 + Triangle(int n, const Vector3 *varr, const unsigned int *idxarr = 0); 14.45 + 14.46 + /// calculate normal (quite expensive) 14.47 + void calc_normal(); 14.48 + const Vector3 &get_normal() const; 14.49 + 14.50 + void transform(const Matrix4x4 &xform); 14.51 + 14.52 + void draw() const; 14.53 + void draw_wire() const; 14.54 + 14.55 + /// calculate barycentric coordinates of a point 14.56 + Vector3 calc_barycentric(const Vector3 &pos) const; 14.57 + 14.58 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 14.59 +}; 14.60 + 14.61 + 14.62 +class Mesh { 14.63 +private: 14.64 + std::string name; 14.65 + unsigned int nverts, nfaces; 14.66 + 14.67 + // current value for each attribute for the immedate mode 14.68 + // interface. 14.69 + Vector4 cur_val[NUM_MESH_ATTR]; 14.70 + 14.71 + unsigned int buffer_objects[NUM_MESH_ATTR + 1]; 14.72 + 14.73 + // vertex attribute data and buffer objects 14.74 + struct { 14.75 + int nelem; // number of elements per attribute range: [1, 4] 14.76 + std::vector<float> data; 14.77 + unsigned int vbo; 14.78 + mutable bool vbo_valid; // if this is false, the vbo needs updating from the data 14.79 + mutable bool data_valid; // if this is false, the data needs to be pulled from the vbo 14.80 + //int sdr_loc; 14.81 + } vattr[NUM_MESH_ATTR]; 14.82 + 14.83 + static int global_sdr_loc[NUM_MESH_ATTR]; 14.84 + 14.85 + //std::vector<XFormNode*> bones; // bones affecting this mesh 14.86 + 14.87 + // index data and buffer object 14.88 + std::vector<unsigned int> idata; 14.89 + unsigned int ibo; 14.90 + mutable bool ibo_valid; 14.91 + mutable bool idata_valid; 14.92 + 14.93 + // index buffer object for wireframe rendering (constructed on demand) 14.94 + unsigned int wire_ibo; 14.95 + mutable bool wire_ibo_valid; 14.96 + 14.97 + // axis-aligned bounding box 14.98 + mutable AABox aabb; 14.99 + mutable bool aabb_valid; 14.100 + 14.101 + // bounding sphere 14.102 + mutable Sphere bsph; 14.103 + mutable bool bsph_valid; 14.104 + 14.105 + // keeps the last intersected face 14.106 + mutable Triangle hitface; 14.107 + // keeps the last intersected vertex position 14.108 + mutable Vector3 hitvert; 14.109 + 14.110 + void calc_aabb(); 14.111 + void calc_bsph(); 14.112 + 14.113 + static unsigned int intersect_mode; 14.114 + static float vertex_sel_dist; 14.115 + 14.116 + static float vis_vecsize; 14.117 + 14.118 + /// update the VBOs after data has changed (invalid vbo/ibo) 14.119 + void update_buffers(); 14.120 + /// construct/update the wireframe index buffer (called from draw_wire). 14.121 + void update_wire_ibo(); 14.122 + 14.123 + mutable int cur_sdr; 14.124 + bool pre_draw() const; 14.125 + void post_draw() const; 14.126 + 14.127 + 14.128 +public: 14.129 + static bool use_custom_sdr_attr; 14.130 + 14.131 + Mesh(); 14.132 + ~Mesh(); 14.133 + 14.134 + Mesh(const Mesh &rhs); 14.135 + Mesh &operator =(const Mesh &rhs); 14.136 + bool clone(const Mesh &m); 14.137 + 14.138 + void set_name(const char *name); 14.139 + const char *get_name() const; 14.140 + 14.141 + bool has_attrib(int attr) const; 14.142 + bool is_indexed() const; 14.143 + 14.144 + // clears everything about this mesh, and returns to the newly constructed state 14.145 + void clear(); 14.146 + 14.147 + // access the vertex attribute data 14.148 + // if vdata == 0, space is just allocated 14.149 + float *set_attrib_data(int attrib, int nelem, unsigned int num, const float *vdata = 0); // invalidates vbo 14.150 + float *get_attrib_data(int attrib); // invalidates vbo 14.151 + const float *get_attrib_data(int attrib) const; 14.152 + 14.153 + // simple access to any particular attribute 14.154 + void set_attrib(int attrib, int idx, const Vector4 &v); // invalidates vbo 14.155 + Vector4 get_attrib(int attrib, int idx) const; 14.156 + 14.157 + int get_attrib_count(int attrib) const; 14.158 + 14.159 + // ... same for index data 14.160 + unsigned int *set_index_data(int num, const unsigned int *indices = 0); // invalidates ibo 14.161 + unsigned int *get_index_data(); // invalidates ibo 14.162 + const unsigned int *get_index_data() const; 14.163 + 14.164 + int get_index_count() const; 14.165 + 14.166 + void append(const Mesh &mesh); 14.167 + 14.168 + // immediate-mode style mesh construction interface 14.169 + void vertex(float x, float y, float z); 14.170 + void normal(float nx, float ny, float nz); 14.171 + void tangent(float tx, float ty, float tz); 14.172 + void texcoord(float u, float v, float w); 14.173 + void boneweights(float w1, float w2, float w3, float w4); 14.174 + void boneidx(int idx1, int idx2, int idx3, int idx4); 14.175 + 14.176 + int get_poly_count() const; 14.177 + 14.178 + /* apply a transformation to the vertices and its inverse-transpose 14.179 + * to the normals and tangents. 14.180 + */ 14.181 + void apply_xform(const Matrix4x4 &xform); 14.182 + void apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform); 14.183 + 14.184 + void flip(); // both faces and normals 14.185 + void flip_faces(); 14.186 + void flip_normals(); 14.187 + 14.188 + // adds a bone and returns its index 14.189 + /*int add_bone(XFormNode *bone); 14.190 + const XFormNode *get_bone(int idx) const; 14.191 + int get_bones_count() const;*/ 14.192 + 14.193 + // access the shader attribute locations 14.194 + static void set_attrib_location(int attr, int loc); 14.195 + static int get_attrib_location(int attr); 14.196 + static void clear_attrib_locations(); 14.197 + 14.198 + static void set_vis_vecsize(float sz); 14.199 + static float get_vis_vecsize(); 14.200 + 14.201 + void draw() const; 14.202 + void draw_wire() const; 14.203 + void draw_vertices() const; 14.204 + void draw_normals() const; 14.205 + void draw_tangents() const; 14.206 + 14.207 + /** get the bounding box in local space. The result will be cached, and subsequent 14.208 + * calls will return the same box. The cache gets invalidated by any functions that can affect 14.209 + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). 14.210 + * @{ */ 14.211 + void get_aabbox(Vector3 *vmin, Vector3 *vmax) const; 14.212 + const AABox &get_aabbox() const; 14.213 + /// @} 14.214 + 14.215 + /** get the bounding sphere in local space. The result will be cached, and subsequent 14.216 + * calls will return the same box. The cache gets invalidated by any functions that can affect 14.217 + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). 14.218 + * @{ */ 14.219 + float get_bsphere(Vector3 *center, float *rad) const; 14.220 + const Sphere &get_bsphere() const; 14.221 + 14.222 + static void set_intersect_mode(unsigned int mode); 14.223 + static unsigned int get_intersect_mode(); 14.224 + static void set_vertex_select_distance(float dist); 14.225 + static float get_vertex_select_distance(); 14.226 + 14.227 + /** Find the intersection between the mesh and a ray. 14.228 + * XXX Brute force at the moment, not intended to be used for anything other than picking in tools. 14.229 + * If you intend to use it in a speed-critical part of the code, you'll *have* to optimize it! 14.230 + */ 14.231 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 14.232 + 14.233 + // texture coordinate manipulation 14.234 + void texcoord_apply_xform(const Matrix4x4 &xform); 14.235 + void texcoord_gen_plane(const Vector3 &norm, const Vector3 &tang); 14.236 + void texcoord_gen_box(); 14.237 +}; 14.238 + 14.239 +#endif // MESH_H_
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/src/meshgen.cc Sat Aug 22 07:15:00 2015 +0300 15.3 @@ -0,0 +1,581 @@ 15.4 +#include <stdio.h> 15.5 +#include "meshgen.h" 15.6 +#include "mesh.h" 15.7 + 15.8 +// -------- sphere -------- 15.9 + 15.10 +#define SURAD(u) ((u) * 2.0 * M_PI) 15.11 +#define SVRAD(v) ((v) * M_PI) 15.12 + 15.13 +static Vector3 sphvec(float theta, float phi) 15.14 +{ 15.15 + return Vector3(sin(theta) * sin(phi), 15.16 + cos(phi), 15.17 + cos(theta) * sin(phi)); 15.18 +} 15.19 + 15.20 +void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange) 15.21 +{ 15.22 + if(usub < 4) usub = 4; 15.23 + if(vsub < 2) vsub = 2; 15.24 + 15.25 + int uverts = usub + 1; 15.26 + int vverts = vsub + 1; 15.27 + 15.28 + int num_verts = uverts * vverts; 15.29 + int num_quads = usub * vsub; 15.30 + int num_tri = num_quads * 2; 15.31 + 15.32 + mesh->clear(); 15.33 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 15.34 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 15.35 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 15.36 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 15.37 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 15.38 + 15.39 + float du = urange / (float)(uverts - 1); 15.40 + float dv = vrange / (float)(vverts - 1); 15.41 + 15.42 + float u = 0.0; 15.43 + for(int i=0; i<uverts; i++) { 15.44 + float theta = SURAD(u * urange); 15.45 + 15.46 + float v = 0.0; 15.47 + for(int j=0; j<vverts; j++) { 15.48 + float phi = SVRAD(v * vrange); 15.49 + 15.50 + Vector3 pos = sphvec(theta, phi); 15.51 + 15.52 + *varr++ = pos * rad; 15.53 + *narr++ = pos; 15.54 + *tarr++ = (sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f)).normalized(); 15.55 + *uvarr++ = Vector2(u * urange, v * vrange); 15.56 + 15.57 + if(i < usub && j < vsub) { 15.58 + int idx = i * vverts + j; 15.59 + *idxarr++ = idx; 15.60 + *idxarr++ = idx + 1; 15.61 + *idxarr++ = idx + vverts + 1; 15.62 + 15.63 + *idxarr++ = idx; 15.64 + *idxarr++ = idx + vverts + 1; 15.65 + *idxarr++ = idx + vverts; 15.66 + } 15.67 + 15.68 + v += dv; 15.69 + } 15.70 + u += du; 15.71 + } 15.72 +} 15.73 + 15.74 + 15.75 +// -------- cylinder -------- 15.76 + 15.77 +static Vector3 cylvec(float theta, float height) 15.78 +{ 15.79 + return Vector3(sin(theta), height, cos(theta)); 15.80 +} 15.81 + 15.82 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 15.83 +{ 15.84 + if(usub < 4) usub = 4; 15.85 + if(vsub < 1) vsub = 1; 15.86 + 15.87 + int uverts = usub + 1; 15.88 + int vverts = vsub + 1; 15.89 + 15.90 + int num_body_verts = uverts * vverts; 15.91 + int num_body_quads = usub * vsub; 15.92 + int num_body_tri = num_body_quads * 2; 15.93 + 15.94 + int capvverts = capsub ? capsub + 1 : 0; 15.95 + int num_cap_verts = uverts * capvverts; 15.96 + int num_cap_quads = usub * capsub; 15.97 + int num_cap_tri = num_cap_quads * 2; 15.98 + 15.99 + int num_verts = num_body_verts + num_cap_verts * 2; 15.100 + int num_tri = num_body_tri + num_cap_tri * 2; 15.101 + 15.102 + mesh->clear(); 15.103 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 15.104 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 15.105 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 15.106 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 15.107 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 15.108 + 15.109 + float du = urange / (float)(uverts - 1); 15.110 + float dv = vrange / (float)(vverts - 1); 15.111 + 15.112 + float u = 0.0; 15.113 + for(int i=0; i<uverts; i++) { 15.114 + float theta = SURAD(u); 15.115 + 15.116 + float v = 0.0; 15.117 + for(int j=0; j<vverts; j++) { 15.118 + float y = (v - 0.5) * height; 15.119 + Vector3 pos = cylvec(theta, y); 15.120 + 15.121 + *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad); 15.122 + *narr++ = Vector3(pos.x, 0.0, pos.z); 15.123 + *tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 15.124 + *uvarr++ = Vector2(u * urange, v * vrange); 15.125 + 15.126 + if(i < usub && j < vsub) { 15.127 + int idx = i * vverts + j; 15.128 + 15.129 + *idxarr++ = idx; 15.130 + *idxarr++ = idx + vverts + 1; 15.131 + *idxarr++ = idx + 1; 15.132 + 15.133 + *idxarr++ = idx; 15.134 + *idxarr++ = idx + vverts; 15.135 + *idxarr++ = idx + vverts + 1; 15.136 + } 15.137 + 15.138 + v += dv; 15.139 + } 15.140 + u += du; 15.141 + } 15.142 + 15.143 + 15.144 + // now the cap! 15.145 + if(!capsub) { 15.146 + return; 15.147 + } 15.148 + 15.149 + dv = 1.0 / (float)(capvverts - 1); 15.150 + 15.151 + u = 0.0; 15.152 + for(int i=0; i<uverts; i++) { 15.153 + float theta = SURAD(u); 15.154 + 15.155 + float v = 0.0; 15.156 + for(int j=0; j<capvverts; j++) { 15.157 + float r = v * rad; 15.158 + 15.159 + Vector3 pos = cylvec(theta, height / 2.0) * r; 15.160 + pos.y = height / 2.0; 15.161 + Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 15.162 + 15.163 + *varr++ = pos; 15.164 + *narr++ = Vector3(0, 1, 0); 15.165 + *tarr++ = tang; 15.166 + *uvarr++ = Vector2(u * urange, v); 15.167 + 15.168 + pos.y = -height / 2.0; 15.169 + *varr++ = pos; 15.170 + *narr++ = Vector3(0, -1, 0); 15.171 + *tarr++ = -tang; 15.172 + *uvarr++ = Vector2(u * urange, v); 15.173 + 15.174 + if(i < usub && j < capsub) { 15.175 + unsigned int idx = num_body_verts + (i * capvverts + j) * 2; 15.176 + 15.177 + unsigned int vidx[4] = { 15.178 + idx, 15.179 + idx + capvverts * 2, 15.180 + idx + (capvverts + 1) * 2, 15.181 + idx + 2 15.182 + }; 15.183 + 15.184 + *idxarr++ = vidx[0]; 15.185 + *idxarr++ = vidx[2]; 15.186 + *idxarr++ = vidx[1]; 15.187 + *idxarr++ = vidx[0]; 15.188 + *idxarr++ = vidx[3]; 15.189 + *idxarr++ = vidx[2]; 15.190 + 15.191 + *idxarr++ = vidx[0] + 1; 15.192 + *idxarr++ = vidx[1] + 1; 15.193 + *idxarr++ = vidx[2] + 1; 15.194 + *idxarr++ = vidx[0] + 1; 15.195 + *idxarr++ = vidx[2] + 1; 15.196 + *idxarr++ = vidx[3] + 1; 15.197 + } 15.198 + 15.199 + v += dv; 15.200 + } 15.201 + u += du; 15.202 + } 15.203 +} 15.204 + 15.205 +// -------- cone -------- 15.206 + 15.207 +static Vector3 conevec(float theta, float y, float height) 15.208 +{ 15.209 + float scale = 1.0 - y / height; 15.210 + return Vector3(sin(theta) * scale, y, cos(theta) * scale); 15.211 +} 15.212 + 15.213 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 15.214 +{ 15.215 + if(usub < 4) usub = 4; 15.216 + if(vsub < 1) vsub = 1; 15.217 + 15.218 + int uverts = usub + 1; 15.219 + int vverts = vsub + 1; 15.220 + 15.221 + int num_body_verts = uverts * vverts; 15.222 + int num_body_quads = usub * vsub; 15.223 + int num_body_tri = num_body_quads * 2; 15.224 + 15.225 + int capvverts = capsub ? capsub + 1 : 0; 15.226 + int num_cap_verts = uverts * capvverts; 15.227 + int num_cap_quads = usub * capsub; 15.228 + int num_cap_tri = num_cap_quads * 2; 15.229 + 15.230 + int num_verts = num_body_verts + num_cap_verts; 15.231 + int num_tri = num_body_tri + num_cap_tri; 15.232 + 15.233 + mesh->clear(); 15.234 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 15.235 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 15.236 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 15.237 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 15.238 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 15.239 + 15.240 + float du = urange / (float)(uverts - 1); 15.241 + float dv = vrange / (float)(vverts - 1); 15.242 + 15.243 + float u = 0.0; 15.244 + for(int i=0; i<uverts; i++) { 15.245 + float theta = SURAD(u); 15.246 + 15.247 + float v = 0.0; 15.248 + for(int j=0; j<vverts; j++) { 15.249 + float y = v * height; 15.250 + Vector3 pos = conevec(theta, y, height); 15.251 + 15.252 + Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized(); 15.253 + Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized(); 15.254 + 15.255 + *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad); 15.256 + *narr++ = cross_product(tang, bitang); 15.257 + *tarr++ = tang; 15.258 + *uvarr++ = Vector2(u * urange, v * vrange); 15.259 + 15.260 + if(i < usub && j < vsub) { 15.261 + int idx = i * vverts + j; 15.262 + 15.263 + *idxarr++ = idx; 15.264 + *idxarr++ = idx + vverts + 1; 15.265 + *idxarr++ = idx + 1; 15.266 + 15.267 + *idxarr++ = idx; 15.268 + *idxarr++ = idx + vverts; 15.269 + *idxarr++ = idx + vverts + 1; 15.270 + } 15.271 + 15.272 + v += dv; 15.273 + } 15.274 + u += du; 15.275 + } 15.276 + 15.277 + 15.278 + // now the bottom cap! 15.279 + if(!capsub) { 15.280 + return; 15.281 + } 15.282 + 15.283 + dv = 1.0 / (float)(capvverts - 1); 15.284 + 15.285 + u = 0.0; 15.286 + for(int i=0; i<uverts; i++) { 15.287 + float theta = SURAD(u); 15.288 + 15.289 + float v = 0.0; 15.290 + for(int j=0; j<capvverts; j++) { 15.291 + float r = v * rad; 15.292 + 15.293 + Vector3 pos = conevec(theta, 0.0, height) * r; 15.294 + Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 15.295 + 15.296 + *varr++ = pos; 15.297 + *narr++ = Vector3(0, -1, 0); 15.298 + *tarr++ = tang; 15.299 + *uvarr++ = Vector2(u * urange, v); 15.300 + 15.301 + if(i < usub && j < capsub) { 15.302 + unsigned int idx = num_body_verts + i * capvverts + j; 15.303 + 15.304 + unsigned int vidx[4] = { 15.305 + idx, 15.306 + idx + capvverts, 15.307 + idx + (capvverts + 1), 15.308 + idx + 1 15.309 + }; 15.310 + 15.311 + *idxarr++ = vidx[0]; 15.312 + *idxarr++ = vidx[1]; 15.313 + *idxarr++ = vidx[2]; 15.314 + *idxarr++ = vidx[0]; 15.315 + *idxarr++ = vidx[2]; 15.316 + *idxarr++ = vidx[3]; 15.317 + } 15.318 + 15.319 + v += dv; 15.320 + } 15.321 + u += du; 15.322 + } 15.323 +} 15.324 + 15.325 + 15.326 +// -------- plane -------- 15.327 + 15.328 +void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub) 15.329 +{ 15.330 + gen_heightmap(mesh, width, height, usub, vsub, 0); 15.331 +} 15.332 + 15.333 + 15.334 +// ----- heightmap ------ 15.335 + 15.336 +void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata) 15.337 +{ 15.338 + if(usub < 1) usub = 1; 15.339 + if(vsub < 1) vsub = 1; 15.340 + 15.341 + mesh->clear(); 15.342 + 15.343 + int uverts = usub + 1; 15.344 + int vverts = vsub + 1; 15.345 + int num_verts = uverts * vverts; 15.346 + 15.347 + int num_quads = usub * vsub; 15.348 + int num_tri = num_quads * 2; 15.349 + 15.350 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 15.351 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 15.352 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 15.353 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 15.354 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 15.355 + 15.356 + float du = 1.0 / (float)usub; 15.357 + float dv = 1.0 / (float)vsub; 15.358 + 15.359 + float u = 0.0; 15.360 + for(int i=0; i<uverts; i++) { 15.361 + float v = 0.0; 15.362 + for(int j=0; j<vverts; j++) { 15.363 + float x = (u - 0.5) * width; 15.364 + float y = (v - 0.5) * height; 15.365 + float z = hf ? hf(u, v, hfdata) : 0.0; 15.366 + 15.367 + Vector3 normal = Vector3(0, 0, 1); 15.368 + if(hf) { 15.369 + float u1z = hf(u + du, v, hfdata); 15.370 + float v1z = hf(u, v + dv, hfdata); 15.371 + 15.372 + Vector3 tang = Vector3(du * width, 0, u1z - z); 15.373 + Vector3 bitan = Vector3(0, dv * height, v1z - z); 15.374 + normal = cross_product(tang, bitan).normalized(); 15.375 + } 15.376 + 15.377 + *varr++ = Vector3(x, y, z); 15.378 + *narr++ = normal; 15.379 + *tarr++ = Vector3(1, 0, 0); 15.380 + *uvarr++ = Vector2(u, v); 15.381 + 15.382 + if(i < usub && j < vsub) { 15.383 + int idx = i * vverts + j; 15.384 + 15.385 + *idxarr++ = idx; 15.386 + *idxarr++ = idx + vverts + 1; 15.387 + *idxarr++ = idx + 1; 15.388 + 15.389 + *idxarr++ = idx; 15.390 + *idxarr++ = idx + vverts; 15.391 + *idxarr++ = idx + vverts + 1; 15.392 + } 15.393 + 15.394 + v += dv; 15.395 + } 15.396 + u += du; 15.397 + } 15.398 +} 15.399 + 15.400 +// ----- heightmap ------ 15.401 + 15.402 +void gen_box(Mesh *mesh, float xsz, float ysz, float zsz) 15.403 +{ 15.404 + mesh->clear(); 15.405 + 15.406 + const int num_faces = 6; 15.407 + int num_verts = num_faces * 4; 15.408 + int num_tri = num_faces * 2; 15.409 + 15.410 + float x = xsz / 2.0; 15.411 + float y = ysz / 2.0; 15.412 + float z = zsz / 2.0; 15.413 + 15.414 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 15.415 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 15.416 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 15.417 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 15.418 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 15.419 + 15.420 + static const Vector2 uv[] = { Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(0, 1) }; 15.421 + 15.422 + // front 15.423 + for(int i=0; i<4; i++) { 15.424 + *narr++ = Vector3(0, 0, 1); 15.425 + *tarr++ = Vector3(1, 0, 0); 15.426 + *uvarr++ = uv[i]; 15.427 + } 15.428 + *varr++ = Vector3(-x, -y, z); 15.429 + *varr++ = Vector3(x, -y, z); 15.430 + *varr++ = Vector3(x, y, z); 15.431 + *varr++ = Vector3(-x, y, z); 15.432 + // right 15.433 + for(int i=0; i<4; i++) { 15.434 + *narr++ = Vector3(1, 0, 0); 15.435 + *tarr++ = Vector3(0, 0, -1); 15.436 + *uvarr++ = uv[i]; 15.437 + } 15.438 + *varr++ = Vector3(x, -y, z); 15.439 + *varr++ = Vector3(x, -y, -z); 15.440 + *varr++ = Vector3(x, y, -z); 15.441 + *varr++ = Vector3(x, y, z); 15.442 + // back 15.443 + for(int i=0; i<4; i++) { 15.444 + *narr++ = Vector3(0, 0, -1); 15.445 + *tarr++ = Vector3(-1, 0, 0); 15.446 + *uvarr++ = uv[i]; 15.447 + } 15.448 + *varr++ = Vector3(x, -y, -z); 15.449 + *varr++ = Vector3(-x, -y, -z); 15.450 + *varr++ = Vector3(-x, y, -z); 15.451 + *varr++ = Vector3(x, y, -z); 15.452 + // left 15.453 + for(int i=0; i<4; i++) { 15.454 + *narr++ = Vector3(-1, 0, 0); 15.455 + *tarr++ = Vector3(0, 0, 1); 15.456 + *uvarr++ = uv[i]; 15.457 + } 15.458 + *varr++ = Vector3(-x, -y, -z); 15.459 + *varr++ = Vector3(-x, -y, z); 15.460 + *varr++ = Vector3(-x, y, z); 15.461 + *varr++ = Vector3(-x, y, -z); 15.462 + // top 15.463 + for(int i=0; i<4; i++) { 15.464 + *narr++ = Vector3(0, 1, 0); 15.465 + *tarr++ = Vector3(1, 0, 0); 15.466 + *uvarr++ = uv[i]; 15.467 + } 15.468 + *varr++ = Vector3(-x, y, z); 15.469 + *varr++ = Vector3(x, y, z); 15.470 + *varr++ = Vector3(x, y, -z); 15.471 + *varr++ = Vector3(-x, y, -z); 15.472 + // bottom 15.473 + for(int i=0; i<4; i++) { 15.474 + *narr++ = Vector3(0, -1, 0); 15.475 + *tarr++ = Vector3(1, 0, 0); 15.476 + *uvarr++ = uv[i]; 15.477 + } 15.478 + *varr++ = Vector3(-x, -y, -z); 15.479 + *varr++ = Vector3(x, -y, -z); 15.480 + *varr++ = Vector3(x, -y, z); 15.481 + *varr++ = Vector3(-x, -y, z); 15.482 + 15.483 + // index array 15.484 + static const int faceidx[] = {0, 1, 2, 0, 2, 3}; 15.485 + for(int i=0; i<num_faces; i++) { 15.486 + for(int j=0; j<6; j++) { 15.487 + *idxarr++ = faceidx[j] + i * 4; 15.488 + } 15.489 + } 15.490 +} 15.491 + 15.492 +static inline Vector3 rev_vert(float u, float v, Vector2 (*rf)(float, float, void*), void *cls) 15.493 +{ 15.494 + Vector2 pos = rf(u, v, cls); 15.495 + 15.496 + float angle = u * 2.0 * M_PI; 15.497 + float x = pos.x * cos(angle); 15.498 + float y = pos.y; 15.499 + float z = pos.x * sin(angle); 15.500 + 15.501 + return Vector3(x, y, z); 15.502 +} 15.503 + 15.504 +// ------ surface of revolution ------- 15.505 +void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), void *cls) 15.506 +{ 15.507 + gen_revol(mesh, usub, vsub, rfunc, 0, cls); 15.508 +} 15.509 + 15.510 +void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), 15.511 + Vector2 (*nfunc)(float, float, void*), void *cls) 15.512 +{ 15.513 + if(!rfunc) return; 15.514 + if(usub < 3) usub = 3; 15.515 + if(vsub < 1) vsub = 1; 15.516 + 15.517 + mesh->clear(); 15.518 + 15.519 + int uverts = usub + 1; 15.520 + int vverts = vsub + 1; 15.521 + int num_verts = uverts * vverts; 15.522 + 15.523 + int num_quads = usub * vsub; 15.524 + int num_tri = num_quads * 2; 15.525 + 15.526 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 15.527 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 15.528 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 15.529 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 15.530 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 15.531 + 15.532 + float du = 1.0 / (float)(uverts - 1); 15.533 + float dv = 1.0 / (float)(vverts - 1); 15.534 + 15.535 + float u = 0.0; 15.536 + for(int i=0; i<uverts; i++) { 15.537 + float v = 0.0; 15.538 + for(int j=0; j<vverts; j++) { 15.539 + Vector3 pos = rev_vert(u, v, rfunc, cls); 15.540 + 15.541 + Vector3 nextu = rev_vert(fmod(u + du, 1.0), v, rfunc, cls); 15.542 + Vector3 tang = nextu - pos; 15.543 + if(tang.length_sq() < 1e-6) { 15.544 + float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25; 15.545 + nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls); 15.546 + tang = nextu - pos; 15.547 + } 15.548 + 15.549 + Vector3 normal; 15.550 + if(nfunc) { 15.551 + normal = rev_vert(u, v, nfunc, cls); 15.552 + } else { 15.553 + Vector3 nextv = rev_vert(u, v + dv, rfunc, cls); 15.554 + Vector3 bitan = nextv - pos; 15.555 + if(bitan.length_sq() < 1e-6) { 15.556 + nextv = rev_vert(u, v - dv, rfunc, cls); 15.557 + bitan = pos - nextv; 15.558 + } 15.559 + 15.560 + normal = cross_product(tang, bitan); 15.561 + } 15.562 + 15.563 + *varr++ = pos; 15.564 + *narr++ = normal.normalized(); 15.565 + *tarr++ = tang.normalized(); 15.566 + *uvarr++ = Vector2(u, v); 15.567 + 15.568 + if(i < usub && j < vsub) { 15.569 + int idx = i * vverts + j; 15.570 + 15.571 + *idxarr++ = idx; 15.572 + *idxarr++ = idx + vverts + 1; 15.573 + *idxarr++ = idx + 1; 15.574 + 15.575 + *idxarr++ = idx; 15.576 + *idxarr++ = idx + vverts; 15.577 + *idxarr++ = idx + vverts + 1; 15.578 + } 15.579 + 15.580 + v += dv; 15.581 + } 15.582 + u += du; 15.583 + } 15.584 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/src/meshgen.h Sat Aug 22 07:15:00 2015 +0300 16.3 @@ -0,0 +1,18 @@ 16.4 +#ifndef MESHGEN_H_ 16.5 +#define MESHGEN_H_ 16.6 + 16.7 +#include "vmath/vmath.h" 16.8 + 16.9 +class Mesh; 16.10 + 16.11 +void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange = 1.0, float vrange = 1.0); 16.12 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub = 0, float urange = 1.0, float vrange = 1.0); 16.13 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub = 0, float urange = 1.0, float vrange = 1.0); 16.14 +void gen_plane(Mesh *mesh, float width, float height, int usub = 1, int vsub = 1); 16.15 +void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata = 0); 16.16 +void gen_box(Mesh *mesh, float xsz, float ysz, float zsz); 16.17 + 16.18 +void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), void *cls = 0); 16.19 +void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), Vector2 (*nfunc)(float, float, void*), void *cls); 16.20 + 16.21 +#endif // MESHGEN_H_
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/src/object.cc Sat Aug 22 07:15:00 2015 +0300 17.3 @@ -0,0 +1,225 @@ 17.4 +#include "object.h" 17.5 +#include "opengl.h" 17.6 +#include "shadow.h" 17.7 + 17.8 +Material::Material() 17.9 + : diffuse(1, 1, 1), specular(0, 0, 0) 17.10 +{ 17.11 + shininess = 60.0; 17.12 + alpha = 1.0; 17.13 +} 17.14 + 17.15 +RenderOps::RenderOps() 17.16 +{ 17.17 + zwrite = true; 17.18 + cast_shadows = true; 17.19 + transparent = false; 17.20 +} 17.21 + 17.22 +void RenderOps::setup() const 17.23 +{ 17.24 + if(!zwrite) { 17.25 + glDepthMask(0); 17.26 + } 17.27 + if(transparent) { 17.28 + glEnable(GL_BLEND); 17.29 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 17.30 + } else { 17.31 + glDisable(GL_BLEND); 17.32 + } 17.33 +} 17.34 + 17.35 +Object::Object() 17.36 +{ 17.37 + mesh = 0; 17.38 + tex = 0; 17.39 + sdr = 0; 17.40 +} 17.41 + 17.42 +Object::~Object() 17.43 +{ 17.44 + delete mesh; 17.45 +} 17.46 + 17.47 +Matrix4x4 &Object::xform() 17.48 +{ 17.49 + return matrix; 17.50 +} 17.51 + 17.52 +const Matrix4x4 &Object::xform() const 17.53 +{ 17.54 + return matrix; 17.55 +} 17.56 + 17.57 +Matrix4x4 &Object::tex_xform() 17.58 +{ 17.59 + return tex_matrix; 17.60 +} 17.61 + 17.62 +const Matrix4x4 &Object::tex_xform() const 17.63 +{ 17.64 + return tex_matrix; 17.65 +} 17.66 + 17.67 +void Object::set_mesh(Mesh *m) 17.68 +{ 17.69 + this->mesh = m; 17.70 +} 17.71 + 17.72 +Mesh *Object::get_mesh() const 17.73 +{ 17.74 + return mesh; 17.75 +} 17.76 + 17.77 +void Object::set_texture(unsigned int tex) 17.78 +{ 17.79 + this->tex = tex; 17.80 +} 17.81 + 17.82 +void Object::set_shader(unsigned int sdr) 17.83 +{ 17.84 + if(GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader) { 17.85 + this->sdr = sdr; 17.86 + } 17.87 +} 17.88 + 17.89 +unsigned int Object::get_shader() const 17.90 +{ 17.91 + return sdr; 17.92 +} 17.93 + 17.94 +void Object::draw() const 17.95 +{ 17.96 + if(!mesh) return; 17.97 + 17.98 + if(shadow_pass && !rop.cast_shadows) { 17.99 + return; 17.100 + } 17.101 + 17.102 + glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT); 17.103 + rop.setup(); 17.104 + 17.105 + if(glcaps.shaders) { 17.106 + if(sdr) { 17.107 + if(!shadow_pass) { 17.108 + glUseProgram(sdr); 17.109 + } 17.110 + } else { 17.111 + glUseProgram(0); 17.112 + } 17.113 + } 17.114 + 17.115 + if(tex) { 17.116 + glBindTexture(GL_TEXTURE_2D, tex); 17.117 + glEnable(GL_TEXTURE_2D); 17.118 + 17.119 + glMatrixMode(GL_TEXTURE); 17.120 + glPushMatrix(); 17.121 + glLoadTransposeMatrixf(tex_matrix[0]); 17.122 + } else { 17.123 + glDisable(GL_TEXTURE_2D); 17.124 + } 17.125 + 17.126 + glMatrixMode(GL_MODELVIEW); 17.127 + glPushMatrix(); 17.128 + glMultTransposeMatrixf(matrix[0]); 17.129 + 17.130 + float dcol[] = {mtl.diffuse.x, mtl.diffuse.y, mtl.diffuse.z, mtl.alpha}; 17.131 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dcol); 17.132 + float scol[] = {mtl.specular.x, mtl.specular.y, mtl.specular.z, 1.0f}; 17.133 + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, scol); 17.134 + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mtl.shininess); 17.135 + 17.136 + mesh->draw(); 17.137 + 17.138 + if(tex) { 17.139 + glDisable(GL_TEXTURE_2D); 17.140 + 17.141 + glMatrixMode(GL_TEXTURE); 17.142 + glPopMatrix(); 17.143 + } 17.144 + 17.145 + if(sdr) { 17.146 + glUseProgram(0); 17.147 + } 17.148 + 17.149 + glMatrixMode(GL_MODELVIEW); 17.150 + glPopMatrix(); 17.151 + 17.152 + glPopAttrib(); 17.153 +} 17.154 + 17.155 +void Object::draw_wire(const Vector4 &col) const 17.156 +{ 17.157 + if(shadow_pass) return; 17.158 + 17.159 + glPushAttrib(GL_ENABLE_BIT); 17.160 + glDisable(GL_LIGHTING); 17.161 + glUseProgram(0); 17.162 + 17.163 + glMatrixMode(GL_MODELVIEW); 17.164 + glPushMatrix(); 17.165 + glMultTransposeMatrixf(matrix[0]); 17.166 + 17.167 + glColor4f(col.x, col.y, col.z, col.w); 17.168 + mesh->draw_wire(); 17.169 + 17.170 + glPopMatrix(); 17.171 + glPopAttrib(); 17.172 +} 17.173 + 17.174 +void Object::draw_vertices(const Vector4 &col) const 17.175 +{ 17.176 + glPushAttrib(GL_ENABLE_BIT); 17.177 + glDisable(GL_LIGHTING); 17.178 + glUseProgram(0); 17.179 + 17.180 + glMatrixMode(GL_MODELVIEW); 17.181 + glPushMatrix(); 17.182 + glMultTransposeMatrixf(matrix[0]); 17.183 + 17.184 + glColor4f(col.x, col.y, col.z, col.w); 17.185 + mesh->draw_vertices(); 17.186 + 17.187 + glPopMatrix(); 17.188 + glPopAttrib(); 17.189 +} 17.190 + 17.191 +void Object::draw_normals(float len, const Vector4 &col) const 17.192 +{ 17.193 + glPushAttrib(GL_ENABLE_BIT); 17.194 + glDisable(GL_LIGHTING); 17.195 + 17.196 + glMatrixMode(GL_MODELVIEW); 17.197 + glPushMatrix(); 17.198 + glMultTransposeMatrixf(matrix[0]); 17.199 + 17.200 + glColor4f(col.x, col.y, col.z, col.w); 17.201 + mesh->set_vis_vecsize(len); 17.202 + mesh->draw_normals(); 17.203 + 17.204 + glPopMatrix(); 17.205 + glPopAttrib(); 17.206 +} 17.207 + 17.208 +void Object::draw_tangents(float len, const Vector4 &col) const 17.209 +{ 17.210 + glPushAttrib(GL_ENABLE_BIT); 17.211 + glDisable(GL_LIGHTING); 17.212 + 17.213 + glMatrixMode(GL_MODELVIEW); 17.214 + glPushMatrix(); 17.215 + glMultTransposeMatrixf(matrix[0]); 17.216 + 17.217 + glColor4f(col.x, col.y, col.z, col.w); 17.218 + mesh->set_vis_vecsize(len); 17.219 + mesh->draw_tangents(); 17.220 + 17.221 + glPopMatrix(); 17.222 + glPopAttrib(); 17.223 +} 17.224 + 17.225 +bool Object::intersect(const Ray &ray, HitPoint *hit) const 17.226 +{ 17.227 + return false; // TODO 17.228 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/src/object.h Sat Aug 22 07:15:00 2015 +0300 18.3 @@ -0,0 +1,63 @@ 18.4 +#ifndef OBJECT_H_ 18.5 +#define OBJECT_H_ 18.6 + 18.7 +#include "mesh.h" 18.8 +#include "geom.h" 18.9 +#include "vmath/vmath.h" 18.10 + 18.11 +struct Material { 18.12 + Vector3 diffuse; 18.13 + Vector3 specular; 18.14 + float shininess; 18.15 + float alpha; 18.16 + 18.17 + Material(); 18.18 +}; 18.19 + 18.20 +struct RenderOps { 18.21 + bool zwrite; 18.22 + bool cast_shadows; 18.23 + bool transparent; 18.24 + 18.25 + RenderOps(); 18.26 + void setup() const; 18.27 +}; 18.28 + 18.29 +class Object { 18.30 +private: 18.31 + Mesh *mesh; 18.32 + Matrix4x4 matrix; 18.33 + unsigned int tex; 18.34 + Matrix4x4 tex_matrix; 18.35 + unsigned int sdr; 18.36 + 18.37 +public: 18.38 + Material mtl; 18.39 + RenderOps rop; 18.40 + 18.41 + Object(); 18.42 + ~Object(); 18.43 + 18.44 + Matrix4x4 &xform(); 18.45 + const Matrix4x4 &xform() const; 18.46 + 18.47 + Matrix4x4 &tex_xform(); 18.48 + const Matrix4x4 &tex_xform() const; 18.49 + 18.50 + void set_mesh(Mesh *m); 18.51 + Mesh *get_mesh() const; 18.52 + 18.53 + void set_texture(unsigned int tex); 18.54 + void set_shader(unsigned int sdr); 18.55 + unsigned int get_shader() const; 18.56 + 18.57 + void draw() const; 18.58 + void draw_wire(const Vector4 &col = Vector4(1, 1, 1, 1)) const; 18.59 + void draw_vertices(const Vector4 &col = Vector4(1, 0.3, 0.2, 1)) const; 18.60 + void draw_normals(float len = 1.0, const Vector4 &col = Vector4(0.1, 0.2, 1.0, 1)) const; 18.61 + void draw_tangents(float len = 1.0, const Vector4 &col = Vector4(0.1, 1.0, 0.2, 1)) const; 18.62 + 18.63 + bool intersect(const Ray &ray, HitPoint *hit) const; 18.64 +}; 18.65 + 18.66 +#endif // OBJECT_H_
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/src/opengl.c Sat Aug 22 07:15:00 2015 +0300 19.3 @@ -0,0 +1,16 @@ 19.4 +#include "opengl.h" 19.5 + 19.6 +struct GLCaps glcaps; 19.7 + 19.8 +int init_opengl() 19.9 +{ 19.10 + glewInit(); 19.11 + 19.12 + glcaps.shaders = GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader; 19.13 + glcaps.fsaa = GLEW_ARB_multisample; 19.14 + glcaps.sep_spec = GLEW_EXT_separate_specular_color; 19.15 + glcaps.fbo = GLEW_ARB_framebuffer_object; 19.16 + glcaps.shadow = GLEW_ARB_shadow | GLEW_SGIX_shadow; 19.17 + 19.18 + return 0; 19.19 +}
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/src/opengl.h Sat Aug 22 07:15:00 2015 +0300 20.3 @@ -0,0 +1,25 @@ 20.4 +#ifndef OPENGL_H_ 20.5 +#define OPENGL_H_ 20.6 + 20.7 +#include <GL/glew.h> 20.8 + 20.9 +struct GLCaps { 20.10 + int shaders; 20.11 + int fsaa; 20.12 + int sep_spec; 20.13 + int fbo; 20.14 + int shadow; 20.15 +}; 20.16 +extern struct GLCaps glcaps; 20.17 + 20.18 +#ifdef __cplusplus 20.19 +extern "C" { 20.20 +#endif 20.21 + 20.22 +int init_opengl(); 20.23 + 20.24 +#ifdef __cplusplus 20.25 +} 20.26 +#endif 20.27 + 20.28 +#endif /* OPENGL_H_ */
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/src/opt.cc Sat Aug 22 07:15:00 2015 +0300 21.3 @@ -0,0 +1,17 @@ 21.4 +#include <stdio.h> 21.5 +#include "opt.h" 21.6 + 21.7 +Options opt; 21.8 + 21.9 +bool init_options(int argc, char **argv) 21.10 +{ 21.11 + // TODO read config files, parse args, etc... 21.12 + 21.13 + opt.xres = 1280; 21.14 + opt.yres = 800; 21.15 + opt.fullscreen = false; 21.16 + opt.shadows = true; 21.17 + opt.reflections = true; 21.18 + 21.19 + return true; 21.20 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/src/opt.h Sat Aug 22 07:15:00 2015 +0300 22.3 @@ -0,0 +1,16 @@ 22.4 +#ifndef OPT_H_ 22.5 +#define OPT_H_ 22.6 + 22.7 +#include "vmath/vmath.h" 22.8 + 22.9 +struct Options { 22.10 + int xres, yres; 22.11 + bool fullscreen; 22.12 + bool shadows, reflections; 22.13 +}; 22.14 + 22.15 +extern Options opt; 22.16 + 22.17 +bool init_options(int argc, char **argv); 22.18 + 22.19 +#endif /* OPT_H_ */
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/src/pnoise.cc Sat Aug 22 07:15:00 2015 +0300 23.3 @@ -0,0 +1,149 @@ 23.4 +#include <stdlib.h> 23.5 +#include "pnoise.h" 23.6 +#include "vmath/vmath.h" 23.7 + 23.8 +#define B 0x100 23.9 +#define BM 0xff 23.10 +#define N 0x1000 23.11 +#define NP 12 23.12 +#define NM 0xfff 23.13 + 23.14 +#define s_curve(t) ((t) * (t) * (3.0f - 2.0f * (t))) 23.15 +#define setup(elem, b0, b1, r0, r1) \ 23.16 + do { \ 23.17 + float t = elem + N; \ 23.18 + b0 = ((int)t) & BM; \ 23.19 + b1 = (b0 + 1) & BM; \ 23.20 + r0 = t - (int)t; \ 23.21 + r1 = r0 - 1.0f; \ 23.22 + } while(0) 23.23 + 23.24 +#define setup_p(elem, b0, b1, r0, r1, p) \ 23.25 + do { \ 23.26 + float t = elem + N; \ 23.27 + b0 = (((int)t) & BM) % p; \ 23.28 + b1 = ((b0 + 1) & BM) % p; \ 23.29 + r0 = t - (int)t; \ 23.30 + r1 = r0 - 1.0f; \ 23.31 + } while(0) 23.32 + 23.33 +static int perm[B + B + 2]; 23.34 +static vec2_t grad2[B + B + 2]; 23.35 +static bool tables_valid; 23.36 + 23.37 +static void init_noise() 23.38 +{ 23.39 + for(int i=0; i<B; i++) { 23.40 + perm[i] = i; 23.41 + 23.42 + grad2[i].x = (float)((rand() % (B + B)) - B) / B; 23.43 + grad2[i].y = (float)((rand() % (B + B)) - B) / B; 23.44 + grad2[i] = v2_normalize(grad2[i]); 23.45 + } 23.46 + 23.47 + for(int i=0; i<B; i++) { 23.48 + int rand_idx = rand() % B; 23.49 + 23.50 + int tmp = perm[i]; 23.51 + perm[i] = perm[rand_idx]; 23.52 + perm[rand_idx] = tmp; 23.53 + } 23.54 + 23.55 + for(int i=0; i<B+2; i++) { 23.56 + perm[B + i] = perm[i]; 23.57 + grad2[B + i] = grad2[i]; 23.58 + } 23.59 +} 23.60 + 23.61 +#define lerp(a, b, t) ((a) + ((b) - (a)) * t) 23.62 + 23.63 +float dbg_noise2(float x, float y) 23.64 +{ 23.65 + if(!tables_valid) { 23.66 + init_noise(); 23.67 + tables_valid = true; 23.68 + } 23.69 + 23.70 + int bx0, bx1, by0, by1; 23.71 + float rx0, rx1, ry0, ry1; 23.72 + setup(x, bx0, bx1, rx0, rx1); 23.73 + setup(y, by0, by1, ry0, ry1); 23.74 + 23.75 + int i = perm[bx0]; 23.76 + int j = perm[bx1]; 23.77 + 23.78 + int b00 = perm[i + by0]; 23.79 + int b10 = perm[j + by0]; 23.80 + int b01 = perm[i + by1]; 23.81 + int b11 = perm[j + by1]; 23.82 + 23.83 + float sx = s_curve(rx0); 23.84 + float sy = s_curve(ry0); 23.85 + 23.86 + vec2_t g00 = grad2[b00]; 23.87 + vec2_t g10 = grad2[b10]; 23.88 + vec2_t g01 = grad2[b01]; 23.89 + vec2_t g11 = grad2[b11]; 23.90 + 23.91 + float u = g00.x * rx0 + g00.y * ry0; 23.92 + float v = g10.x * rx1 + g10.y * ry0; 23.93 + float a = lerp(u, v, sx); 23.94 + 23.95 + u = g01.x * rx0 + g01.y * ry1; 23.96 + v = g11.x * rx1 + g11.y * ry1; 23.97 + float b = lerp(u, v, sx); 23.98 + 23.99 + return lerp(a, b, sy); 23.100 +} 23.101 + 23.102 +float pnoise2(float x, float y, int periodx, int periody) 23.103 +{ 23.104 + if(!tables_valid) { 23.105 + init_noise(); 23.106 + tables_valid = true; 23.107 + } 23.108 + 23.109 + int bx0, bx1, by0, by1; 23.110 + float rx0, rx1, ry0, ry1; 23.111 + setup_p(x, bx0, bx1, rx0, rx1, periodx); 23.112 + setup_p(y, by0, by1, ry0, ry1, periody); 23.113 + 23.114 + int i = perm[bx0]; 23.115 + int j = perm[bx1]; 23.116 + 23.117 + int b00 = perm[i + by0]; 23.118 + int b10 = perm[j + by0]; 23.119 + int b01 = perm[i + by1]; 23.120 + int b11 = perm[j + by1]; 23.121 + 23.122 + float sx = s_curve(rx0); 23.123 + float sy = s_curve(ry0); 23.124 + 23.125 + vec2_t g00 = grad2[b00]; 23.126 + vec2_t g10 = grad2[b10]; 23.127 + vec2_t g01 = grad2[b01]; 23.128 + vec2_t g11 = grad2[b11]; 23.129 + 23.130 + float u = g00.x * rx0 + g00.y * ry0; 23.131 + float v = g10.x * rx1 + g10.y * ry0; 23.132 + float a = lerp(u, v, sx); 23.133 + 23.134 + u = g01.x * rx0 + g01.y * ry1; 23.135 + v = g11.x * rx1 + g11.y * ry1; 23.136 + float b = lerp(u, v, sx); 23.137 + 23.138 + return lerp(a, b, sy); 23.139 +} 23.140 + 23.141 +float pturbulence2(float x, float y, int periodx, int periody, int octaves) 23.142 +{ 23.143 + int i; 23.144 + float res = 0.0f, freq = 1.0f; 23.145 + for(i=0; i<octaves; i++) { 23.146 + res += fabs(pnoise2(x * freq, y * freq, periodx, periody) / freq); 23.147 + freq *= 2.0f; 23.148 + periodx *= 2; 23.149 + periody *= 2; 23.150 + } 23.151 + return res; 23.152 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/src/pnoise.h Sat Aug 22 07:15:00 2015 +0300 24.3 @@ -0,0 +1,8 @@ 24.4 +#ifndef PNOISE_H_ 24.5 +#define PNOISE_H_ 24.6 + 24.7 +float dbg_noise2(float x, float y); 24.8 +float pnoise2(float x, float y, int periodx, int periody); 24.9 +float pturbulence2(float x, float y, int periodx, int periody, int octaves); 24.10 + 24.11 +#endif // PNOISE_H_
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/src/scene.cc Sat Aug 22 07:15:00 2015 +0300 25.3 @@ -0,0 +1,57 @@ 25.4 +#include "scene.h" 25.5 +#include "opengl.h" 25.6 +#include "opt.h" 25.7 +#include "game.h" 25.8 + 25.9 +static int max_lights = -1; 25.10 + 25.11 +Scene::~Scene() 25.12 +{ 25.13 + clear(); 25.14 +} 25.15 + 25.16 +void Scene::clear() 25.17 +{ 25.18 + for(size_t i=0; i<objects.size(); i++) { 25.19 + delete objects[i]; 25.20 + } 25.21 + objects.clear(); 25.22 + 25.23 + for(size_t i=0; i<lights.size(); i++) { 25.24 + delete lights[i]; 25.25 + } 25.26 + lights.clear(); 25.27 +} 25.28 + 25.29 +void Scene::add_object(Object *obj) 25.30 +{ 25.31 + objects.push_back(obj); 25.32 +} 25.33 + 25.34 +void Scene::add_lights(Light *lt) 25.35 +{ 25.36 + lights.push_back(lt); 25.37 +} 25.38 + 25.39 +void Scene::draw(unsigned int flags) const 25.40 +{ 25.41 + if(max_lights == -1) { 25.42 + glGetIntegerv(GL_MAX_LIGHTS, &max_lights); 25.43 + printf("max lights: %d\n", max_lights); 25.44 + } 25.45 + 25.46 + for(size_t i=0; i<lights.size(); i++) { 25.47 + lights[i]->setup(i); 25.48 + } 25.49 + 25.50 + for(size_t i=0; i<objects.size(); i++) { 25.51 + unsigned int mask = objects[i]->rop.transparent ? DRAW_TRANSPARENT : DRAW_SOLID; 25.52 + if(mask & flags) { 25.53 + if(dbg_wireframe) { 25.54 + objects[i]->draw_wire(); 25.55 + } else { 25.56 + objects[i]->draw(); 25.57 + } 25.58 + } 25.59 + } 25.60 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/src/scene.h Sat Aug 22 07:15:00 2015 +0300 26.3 @@ -0,0 +1,29 @@ 26.4 +#ifndef SCENE_H_ 26.5 +#define SCENE_H_ 26.6 + 26.7 +#include <vector> 26.8 +#include "object.h" 26.9 +#include "light.h" 26.10 + 26.11 +enum { 26.12 + DRAW_SOLID = 1, 26.13 + DRAW_TRANSPARENT = 2, 26.14 + DRAW_ALL = 0x7fffffff 26.15 +}; 26.16 + 26.17 +class Scene { 26.18 +public: 26.19 + std::vector<Object*> objects; 26.20 + std::vector<Light*> lights; 26.21 + 26.22 + ~Scene(); 26.23 + 26.24 + void clear(); 26.25 + 26.26 + void add_object(Object *obj); 26.27 + void add_lights(Light *lt); 26.28 + 26.29 + void draw(unsigned int flags = DRAW_ALL) const; 26.30 +}; 26.31 + 26.32 +#endif // SCENE_H_
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/src/sdr.c Sat Aug 22 07:15:00 2015 +0300 27.3 @@ -0,0 +1,407 @@ 27.4 +#include <stdio.h> 27.5 +#include <stdlib.h> 27.6 +#include <string.h> 27.7 +#include <errno.h> 27.8 +#include <stdarg.h> 27.9 +#include <assert.h> 27.10 +#include "opengl.h" 27.11 + 27.12 +#if defined(unix) || defined(__unix__) 27.13 +#include <unistd.h> 27.14 +#include <sys/stat.h> 27.15 +#endif /* unix */ 27.16 + 27.17 +#include "sdr.h" 27.18 + 27.19 +static const char *sdrtypestr(unsigned int sdrtype); 27.20 + 27.21 +unsigned int create_vertex_shader(const char *src) 27.22 +{ 27.23 + return create_shader(src, GL_VERTEX_SHADER); 27.24 +} 27.25 + 27.26 +unsigned int create_pixel_shader(const char *src) 27.27 +{ 27.28 + return create_shader(src, GL_FRAGMENT_SHADER); 27.29 +} 27.30 + 27.31 +unsigned int create_tessctl_shader(const char *src) 27.32 +{ 27.33 +#ifdef GL_TESS_CONTROL_SHADER 27.34 + return create_shader(src, GL_TESS_CONTROL_SHADER); 27.35 +#else 27.36 + return 0; 27.37 +#endif 27.38 +} 27.39 + 27.40 +unsigned int create_tesseval_shader(const char *src) 27.41 +{ 27.42 +#ifdef GL_TESS_EVALUATION_SHADER 27.43 + return create_shader(src, GL_TESS_EVALUATION_SHADER); 27.44 +#else 27.45 + return 0; 27.46 +#endif 27.47 +} 27.48 + 27.49 +unsigned int create_geometry_shader(const char *src) 27.50 +{ 27.51 +#ifdef GL_GEOMETRY_SHADER 27.52 + return create_shader(src, GL_GEOMETRY_SHADER); 27.53 +#else 27.54 + return 0; 27.55 +#endif 27.56 +} 27.57 + 27.58 +unsigned int create_shader(const char *src, unsigned int sdr_type) 27.59 +{ 27.60 + unsigned int sdr; 27.61 + int success, info_len; 27.62 + char *info_str = 0; 27.63 + GLenum err; 27.64 + 27.65 + sdr = glCreateShader(sdr_type); 27.66 + assert(glGetError() == GL_NO_ERROR); 27.67 + glShaderSource(sdr, 1, &src, 0); 27.68 + err = glGetError(); 27.69 + assert(err == GL_NO_ERROR); 27.70 + glCompileShader(sdr); 27.71 + assert(glGetError() == GL_NO_ERROR); 27.72 + 27.73 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); 27.74 + assert(glGetError() == GL_NO_ERROR); 27.75 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 27.76 + assert(glGetError() == GL_NO_ERROR); 27.77 + 27.78 + if(info_len) { 27.79 + if((info_str = malloc(info_len + 1))) { 27.80 + glGetShaderInfoLog(sdr, info_len, 0, info_str); 27.81 + assert(glGetError() == GL_NO_ERROR); 27.82 + info_str[info_len] = 0; 27.83 + } 27.84 + } 27.85 + 27.86 + if(success) { 27.87 + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); 27.88 + } else { 27.89 + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); 27.90 + glDeleteShader(sdr); 27.91 + sdr = 0; 27.92 + } 27.93 + 27.94 + free(info_str); 27.95 + return sdr; 27.96 +} 27.97 + 27.98 +void free_shader(unsigned int sdr) 27.99 +{ 27.100 + glDeleteShader(sdr); 27.101 +} 27.102 + 27.103 +unsigned int load_vertex_shader(const char *fname) 27.104 +{ 27.105 + return load_shader(fname, GL_VERTEX_SHADER); 27.106 +} 27.107 + 27.108 +unsigned int load_pixel_shader(const char *fname) 27.109 +{ 27.110 + return load_shader(fname, GL_FRAGMENT_SHADER); 27.111 +} 27.112 + 27.113 +unsigned int load_tessctl_shader(const char *fname) 27.114 +{ 27.115 +#ifdef GL_TESS_CONTROL_SHADER 27.116 + return load_shader(fname, GL_TESS_CONTROL_SHADER); 27.117 +#else 27.118 + return 0; 27.119 +#endif 27.120 +} 27.121 + 27.122 +unsigned int load_tesseval_shader(const char *fname) 27.123 +{ 27.124 +#ifdef GL_TESS_EVALUATION_SHADER 27.125 + return load_shader(fname, GL_TESS_EVALUATION_SHADER); 27.126 +#else 27.127 + return 0; 27.128 +#endif 27.129 +} 27.130 + 27.131 +unsigned int load_geometry_shader(const char *fname) 27.132 +{ 27.133 +#ifdef GL_GEOMETRY_SHADER 27.134 + return load_shader(fname, GL_GEOMETRY_SHADER); 27.135 +#else 27.136 + return 0; 27.137 +#endif 27.138 +} 27.139 + 27.140 +unsigned int load_shader(const char *fname, unsigned int sdr_type) 27.141 +{ 27.142 + unsigned int sdr; 27.143 + size_t filesize; 27.144 + FILE *fp; 27.145 + char *src; 27.146 + 27.147 + if(!(fp = fopen(fname, "rb"))) { 27.148 + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); 27.149 + return 0; 27.150 + } 27.151 + 27.152 + fseek(fp, 0, SEEK_END); 27.153 + filesize = ftell(fp); 27.154 + fseek(fp, 0, SEEK_SET); 27.155 + 27.156 + if(!(src = malloc(filesize + 1))) { 27.157 + fclose(fp); 27.158 + return 0; 27.159 + } 27.160 + fread(src, 1, filesize, fp); 27.161 + src[filesize] = 0; 27.162 + fclose(fp); 27.163 + 27.164 + fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname); 27.165 + sdr = create_shader(src, sdr_type); 27.166 + 27.167 + free(src); 27.168 + return sdr; 27.169 +} 27.170 + 27.171 + 27.172 +/* ---- gpu programs ---- */ 27.173 + 27.174 +unsigned int create_program(void) 27.175 +{ 27.176 + unsigned int prog = glCreateProgram(); 27.177 + assert(glGetError() == GL_NO_ERROR); 27.178 + return prog; 27.179 +} 27.180 + 27.181 +unsigned int create_program_link(unsigned int sdr0, ...) 27.182 +{ 27.183 + unsigned int prog, sdr; 27.184 + va_list ap; 27.185 + 27.186 + if(!(prog = create_program())) { 27.187 + return 0; 27.188 + } 27.189 + 27.190 + attach_shader(prog, sdr0); 27.191 + if(glGetError()) { 27.192 + return 0; 27.193 + } 27.194 + 27.195 + va_start(ap, sdr0); 27.196 + while((sdr = va_arg(ap, unsigned int))) { 27.197 + attach_shader(prog, sdr); 27.198 + if(glGetError()) { 27.199 + return 0; 27.200 + } 27.201 + } 27.202 + va_end(ap); 27.203 + 27.204 + if(link_program(prog) == -1) { 27.205 + free_program(prog); 27.206 + return 0; 27.207 + } 27.208 + return prog; 27.209 +} 27.210 + 27.211 +unsigned int create_program_load(const char *vfile, const char *pfile) 27.212 +{ 27.213 + unsigned int vs = 0, ps = 0; 27.214 + 27.215 + if(vfile && *vfile && !(vs = load_vertex_shader(vfile))) { 27.216 + return 0; 27.217 + } 27.218 + if(pfile && *pfile && !(ps = load_pixel_shader(pfile))) { 27.219 + return 0; 27.220 + } 27.221 + return create_program_link(vs, ps, 0); 27.222 +} 27.223 + 27.224 +void free_program(unsigned int sdr) 27.225 +{ 27.226 + glDeleteProgram(sdr); 27.227 +} 27.228 + 27.229 +void attach_shader(unsigned int prog, unsigned int sdr) 27.230 +{ 27.231 + int err; 27.232 + 27.233 + if(prog && sdr) { 27.234 + assert(glGetError() == GL_NO_ERROR); 27.235 + glAttachShader(prog, sdr); 27.236 + if((err = glGetError()) != GL_NO_ERROR) { 27.237 + fprintf(stderr, "failed to attach shader %u to program %u (err: 0x%x)\n", sdr, prog, err); 27.238 + abort(); 27.239 + } 27.240 + } 27.241 +} 27.242 + 27.243 +int link_program(unsigned int prog) 27.244 +{ 27.245 + int linked, info_len, retval = 0; 27.246 + char *info_str = 0; 27.247 + 27.248 + glLinkProgram(prog); 27.249 + assert(glGetError() == GL_NO_ERROR); 27.250 + glGetProgramiv(prog, GL_LINK_STATUS, &linked); 27.251 + assert(glGetError() == GL_NO_ERROR); 27.252 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 27.253 + assert(glGetError() == GL_NO_ERROR); 27.254 + 27.255 + if(info_len) { 27.256 + if((info_str = malloc(info_len + 1))) { 27.257 + glGetProgramInfoLog(prog, info_len, 0, info_str); 27.258 + assert(glGetError() == GL_NO_ERROR); 27.259 + info_str[info_len] = 0; 27.260 + } 27.261 + } 27.262 + 27.263 + if(linked) { 27.264 + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); 27.265 + } else { 27.266 + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); 27.267 + retval = -1; 27.268 + } 27.269 + 27.270 + free(info_str); 27.271 + return retval; 27.272 +} 27.273 + 27.274 +int bind_program(unsigned int prog) 27.275 +{ 27.276 + GLenum err; 27.277 + 27.278 + glUseProgram(prog); 27.279 + if(prog && (err = glGetError()) != GL_NO_ERROR) { 27.280 + /* maybe the program is not linked, try linking first */ 27.281 + if(err == GL_INVALID_OPERATION) { 27.282 + if(link_program(prog) == -1) { 27.283 + return -1; 27.284 + } 27.285 + glUseProgram(prog); 27.286 + return glGetError() == GL_NO_ERROR ? 0 : -1; 27.287 + } 27.288 + return -1; 27.289 + } 27.290 + return 0; 27.291 +} 27.292 + 27.293 +/* ugly but I'm not going to write the same bloody code over and over */ 27.294 +#define BEGIN_UNIFORM_CODE \ 27.295 + int loc, curr_prog; \ 27.296 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ 27.297 + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \ 27.298 + return -1; \ 27.299 + } \ 27.300 + if((loc = glGetUniformLocation(prog, name)) != -1) 27.301 + 27.302 +#define END_UNIFORM_CODE \ 27.303 + if((unsigned int)curr_prog != prog) { \ 27.304 + bind_program(curr_prog); \ 27.305 + } \ 27.306 + return loc == -1 ? -1 : 0 27.307 + 27.308 +int set_uniform_int(unsigned int prog, const char *name, int val) 27.309 +{ 27.310 + BEGIN_UNIFORM_CODE { 27.311 + glUniform1i(loc, val); 27.312 + } 27.313 + END_UNIFORM_CODE; 27.314 +} 27.315 + 27.316 +int set_uniform_float(unsigned int prog, const char *name, float val) 27.317 +{ 27.318 + BEGIN_UNIFORM_CODE { 27.319 + glUniform1f(loc, val); 27.320 + } 27.321 + END_UNIFORM_CODE; 27.322 +} 27.323 + 27.324 +int set_uniform_float2(unsigned int prog, const char *name, float x, float y) 27.325 +{ 27.326 + BEGIN_UNIFORM_CODE { 27.327 + glUniform2f(loc, x, y); 27.328 + } 27.329 + END_UNIFORM_CODE; 27.330 +} 27.331 + 27.332 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) 27.333 +{ 27.334 + BEGIN_UNIFORM_CODE { 27.335 + glUniform3f(loc, x, y, z); 27.336 + } 27.337 + END_UNIFORM_CODE; 27.338 +} 27.339 + 27.340 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) 27.341 +{ 27.342 + BEGIN_UNIFORM_CODE { 27.343 + glUniform4f(loc, x, y, z, w); 27.344 + } 27.345 + END_UNIFORM_CODE; 27.346 +} 27.347 + 27.348 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat) 27.349 +{ 27.350 + BEGIN_UNIFORM_CODE { 27.351 + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); 27.352 + } 27.353 + END_UNIFORM_CODE; 27.354 +} 27.355 + 27.356 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) 27.357 +{ 27.358 + BEGIN_UNIFORM_CODE { 27.359 + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); 27.360 + } 27.361 + END_UNIFORM_CODE; 27.362 +} 27.363 + 27.364 +int get_attrib_loc(unsigned int prog, const char *name) 27.365 +{ 27.366 + int loc, curr_prog; 27.367 + 27.368 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); 27.369 + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { 27.370 + return -1; 27.371 + } 27.372 + 27.373 + loc = glGetAttribLocation(prog, (char*)name); 27.374 + 27.375 + if((unsigned int)curr_prog != prog) { 27.376 + bind_program(curr_prog); 27.377 + } 27.378 + return loc; 27.379 +} 27.380 + 27.381 +void set_attrib_float3(int attr_loc, float x, float y, float z) 27.382 +{ 27.383 + glVertexAttrib3f(attr_loc, x, y, z); 27.384 +} 27.385 + 27.386 +static const char *sdrtypestr(unsigned int sdrtype) 27.387 +{ 27.388 + switch(sdrtype) { 27.389 + case GL_VERTEX_SHADER: 27.390 + return "vertex"; 27.391 + case GL_FRAGMENT_SHADER: 27.392 + return "pixel"; 27.393 +#ifdef GL_TESS_CONTROL_SHADER 27.394 + case GL_TESS_CONTROL_SHADER: 27.395 + return "tessellation control"; 27.396 +#endif 27.397 +#ifdef GL_TESS_EVALUATION_SHADER 27.398 + case GL_TESS_EVALUATION_SHADER: 27.399 + return "tessellation evaluation"; 27.400 +#endif 27.401 +#ifdef GL_GEOMETRY_SHADER 27.402 + case GL_GEOMETRY_SHADER: 27.403 + return "geometry"; 27.404 +#endif 27.405 + 27.406 + default: 27.407 + break; 27.408 + } 27.409 + return "<unknown>"; 27.410 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/src/sdr.h Sat Aug 22 07:15:00 2015 +0300 28.3 @@ -0,0 +1,52 @@ 28.4 +#ifndef SDR_H_ 28.5 +#define SDR_H_ 28.6 + 28.7 +#ifdef __cplusplus 28.8 +extern "C" { 28.9 +#endif /* __cplusplus */ 28.10 + 28.11 +/* ---- shaders ---- */ 28.12 +unsigned int create_vertex_shader(const char *src); 28.13 +unsigned int create_pixel_shader(const char *src); 28.14 +unsigned int create_tessctl_shader(const char *src); 28.15 +unsigned int create_tesseval_shader(const char *src); 28.16 +unsigned int create_geometry_shader(const char *src); 28.17 +unsigned int create_shader(const char *src, unsigned int sdr_type); 28.18 +void free_shader(unsigned int sdr); 28.19 + 28.20 +unsigned int load_vertex_shader(const char *fname); 28.21 +unsigned int load_pixel_shader(const char *fname); 28.22 +unsigned int load_tessctl_shader(const char *fname); 28.23 +unsigned int load_tesseval_shader(const char *fname); 28.24 +unsigned int load_geometry_shader(const char *fname); 28.25 +unsigned int load_shader(const char *src, unsigned int sdr_type); 28.26 + 28.27 +int add_shader(const char *fname, unsigned int sdr); 28.28 +int remove_shader(const char *fname); 28.29 + 28.30 +/* ---- gpu programs ---- */ 28.31 +unsigned int create_program(void); 28.32 +unsigned int create_program_link(unsigned int sdr0, ...); 28.33 +unsigned int create_program_load(const char *vfile, const char *pfile); 28.34 +void free_program(unsigned int sdr); 28.35 + 28.36 +void attach_shader(unsigned int prog, unsigned int sdr); 28.37 +int link_program(unsigned int prog); 28.38 +int bind_program(unsigned int prog); 28.39 + 28.40 +int set_uniform_int(unsigned int prog, const char *name, int val); 28.41 +int set_uniform_float(unsigned int prog, const char *name, float val); 28.42 +int set_uniform_float2(unsigned int prog, const char *name, float x, float y); 28.43 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z); 28.44 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w); 28.45 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat); 28.46 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat); 28.47 + 28.48 +int get_attrib_loc(unsigned int prog, const char *name); 28.49 +void set_attrib_float3(int attr_loc, float x, float y, float z); 28.50 + 28.51 +#ifdef __cplusplus 28.52 +} 28.53 +#endif /* __cplusplus */ 28.54 + 28.55 +#endif /* SDR_H_ */
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/src/shader.cc Sat Aug 22 07:15:00 2015 +0300 29.3 @@ -0,0 +1,28 @@ 29.4 +#include "shader.h" 29.5 +#include "sdr.h" 29.6 + 29.7 +static unsigned int cur_sdr; 29.8 +static unsigned int sover; 29.9 + 29.10 +void set_shader(unsigned int sdr) 29.11 +{ 29.12 + cur_sdr = sdr; 29.13 + if(!sover) { 29.14 + bind_program(sdr); 29.15 + } 29.16 +} 29.17 + 29.18 +unsigned int current_shader() 29.19 +{ 29.20 + return sover ? sover : cur_sdr; 29.21 +} 29.22 + 29.23 +void override_shader(unsigned int sdr) 29.24 +{ 29.25 + sover = sdr; 29.26 + if(sover) { 29.27 + bind_program(sdr); 29.28 + } else { 29.29 + bind_program(cur_sdr); 29.30 + } 29.31 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/src/shader.h Sat Aug 22 07:15:00 2015 +0300 30.3 @@ -0,0 +1,8 @@ 30.4 +#ifndef SHADER_H_ 30.5 +#define SHADER_H_ 30.6 + 30.7 +void set_shader(unsigned int sdr); 30.8 +unsigned int current_shader(); 30.9 +void override_shader(unsigned int sdr); 30.10 + 30.11 +#endif /* SHADER_H_ */
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/src/shadow.cc Sat Aug 22 07:15:00 2015 +0300 31.3 @@ -0,0 +1,141 @@ 31.4 +#include <assert.h> 31.5 +#include "opengl.h" 31.6 +#include "shadow.h" 31.7 +#include "vmath/vmath.h" 31.8 + 31.9 +bool shadow_pass; 31.10 + 31.11 +static int tex_sz, prev_vp[4]; 31.12 +static unsigned int fbo, depth_tex, rb_color; 31.13 +static Matrix4x4 shadow_mat; 31.14 + 31.15 +bool init_shadow(int sz) 31.16 +{ 31.17 + if(!glcaps.fbo || !glcaps.shadow) { 31.18 + return false; 31.19 + } 31.20 + 31.21 + tex_sz = sz; 31.22 + printf("initializing shadow buffer (%dx%d)\n", tex_sz, tex_sz); 31.23 + 31.24 + glGenFramebuffers(1, &fbo); 31.25 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 31.26 + 31.27 + glGenTextures(1, &depth_tex); 31.28 + glBindTexture(GL_TEXTURE_2D, depth_tex); 31.29 + float border[] = {1, 1, 1, 1}; 31.30 + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border); 31.31 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 31.32 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 31.33 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 31.34 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 31.35 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); 31.36 + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex_sz, tex_sz, 0, 31.37 + GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); 31.38 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_tex, 0); 31.39 + 31.40 + assert(glGetError() == GL_NO_ERROR); 31.41 + 31.42 + glDrawBuffer(GL_FALSE); 31.43 + glReadBuffer(GL_FALSE); 31.44 + 31.45 + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 31.46 + fprintf(stderr, "incomplete framebuffer\n"); 31.47 + return false; 31.48 + } 31.49 + 31.50 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 31.51 + glDrawBuffer(GL_BACK); 31.52 + glReadBuffer(GL_BACK); 31.53 + assert(glGetError() == GL_NO_ERROR); 31.54 + 31.55 + return true; 31.56 +} 31.57 + 31.58 +void destroy_shadow() 31.59 +{ 31.60 + glDeleteTextures(1, &depth_tex); 31.61 + glDeleteRenderbuffers(1, &rb_color); 31.62 + glDeleteFramebuffers(1, &fbo); 31.63 +} 31.64 + 31.65 +void begin_shadow_pass(const Vector3 &lpos, const Vector3 <arg, float lfov) 31.66 +{ 31.67 + shadow_pass = true; 31.68 + 31.69 + glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT); 31.70 + glDisable(GL_LIGHTING); 31.71 + glColorMask(0, 0, 0, 0); 31.72 + glDepthMask(1); 31.73 + 31.74 + Matrix4x4 viewmat; 31.75 + glGetFloatv(GL_MODELVIEW_MATRIX, viewmat[0]); 31.76 + viewmat.transpose(); 31.77 + 31.78 + Matrix4x4 lt_viewmat, lt_projmat; 31.79 + lt_projmat.set_perspective(DEG_TO_RAD(lfov) * 2.0, 1.0, 8.0, 50.0); 31.80 + lt_viewmat.set_lookat(lpos, ltarg, Vector3(0, 1, 0)); 31.81 + shadow_mat = lt_projmat * lt_viewmat * viewmat.inverse(); 31.82 + 31.83 + glMatrixMode(GL_PROJECTION); 31.84 + glPushMatrix(); 31.85 + glLoadTransposeMatrixf(lt_projmat[0]); 31.86 + 31.87 + glMatrixMode(GL_MODELVIEW); 31.88 + glPushMatrix(); 31.89 + glLoadTransposeMatrixf(lt_viewmat[0]); 31.90 + 31.91 + glGetIntegerv(GL_VIEWPORT, prev_vp); 31.92 + glViewport(0, 0, tex_sz, tex_sz); 31.93 + 31.94 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 31.95 + 31.96 + glPolygonOffset(2, 1); 31.97 + glEnable(GL_POLYGON_OFFSET_FILL); 31.98 + 31.99 + glClear(GL_DEPTH_BUFFER_BIT); 31.100 + glUseProgram(0); 31.101 +} 31.102 + 31.103 + 31.104 +void end_shadow_pass() 31.105 +{ 31.106 + shadow_pass = false; 31.107 + 31.108 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 31.109 + 31.110 + glViewport(prev_vp[0], prev_vp[1], prev_vp[2], prev_vp[3]); 31.111 + 31.112 + glMatrixMode(GL_PROJECTION); 31.113 + glPopMatrix(); 31.114 + glMatrixMode(GL_MODELVIEW); 31.115 + glPopMatrix(); 31.116 + 31.117 + glPopAttrib(); 31.118 +} 31.119 + 31.120 +Matrix4x4 get_shadow_matrix() 31.121 +{ 31.122 + return shadow_mat; 31.123 + 31.124 + /* 31.125 + glMatrixMode(GL_MODELVIEW); 31.126 + glPushMatrix(); 31.127 + glLoadIdentity(); 31.128 + gluPerspective(lfov * 2.0, 1.0, 0.5, 50.0); 31.129 + gluLookAt(lpos.x, lpos.y, lpos.z, ltarg.x, ltarg.y, ltarg.z, 0, 1, 0); 31.130 + 31.131 + float mat[16]; 31.132 + glGetFloatv(GL_MODELVIEW_MATRIX, mat); 31.133 + 31.134 + Matrix4x4 res; 31.135 + memcpy(res[0], mat, sizeof mat); 31.136 + res.transpose(); 31.137 + return res; 31.138 + */ 31.139 +} 31.140 + 31.141 +unsigned int get_shadow_tex() 31.142 +{ 31.143 + return depth_tex; 31.144 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/src/shadow.h Sat Aug 22 07:15:00 2015 +0300 32.3 @@ -0,0 +1,17 @@ 32.4 +#ifndef SHADOW_H_ 32.5 +#define SHADOW_H_ 32.6 + 32.7 +#include "vmath/vmath.h" 32.8 + 32.9 +extern bool shadow_pass; 32.10 + 32.11 +bool init_shadow(int sz); 32.12 +void destroy_shadow(); 32.13 + 32.14 +void begin_shadow_pass(const Vector3 &lpos, const Vector3 <arg, float lfov); 32.15 +void end_shadow_pass(); 32.16 + 32.17 +Matrix4x4 get_shadow_matrix(); 32.18 +unsigned int get_shadow_tex(); 32.19 + 32.20 +#endif // SHADOW_H_
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/src/snode.cc Sat Aug 22 07:15:00 2015 +0300 33.3 @@ -0,0 +1,188 @@ 33.4 +#include <float.h> 33.5 +#include <assert.h> 33.6 +#include <algorithm> 33.7 +#include "snode.h" 33.8 + 33.9 +SceneNode::SceneNode() 33.10 + : scale(1, 1, 1) 33.11 +{ 33.12 + parent = 0; 33.13 +} 33.14 + 33.15 +SceneNode::SceneNode(Object *obj) 33.16 + : scale(1, 1, 1) 33.17 +{ 33.18 + parent = 0; 33.19 + add_object(obj); 33.20 +} 33.21 + 33.22 +void SceneNode::add_child(SceneNode *node) 33.23 +{ 33.24 + if(node->parent) { 33.25 + if(node->parent == this) { 33.26 + return; 33.27 + } 33.28 + node->parent->remove_child(node); 33.29 + } 33.30 + 33.31 + children.push_back(node); 33.32 + node->parent = this; 33.33 +} 33.34 + 33.35 +bool SceneNode::remove_child(SceneNode *node) 33.36 +{ 33.37 + for(size_t i=0; i<children.size(); i++) { 33.38 + if(children[i] == node) { 33.39 + assert(node->parent == this); 33.40 + node->parent = 0; 33.41 + return true; 33.42 + } 33.43 + } 33.44 + return false; 33.45 +} 33.46 + 33.47 +int SceneNode::get_num_children() const 33.48 +{ 33.49 + return (int)children.size(); 33.50 +} 33.51 + 33.52 +SceneNode *SceneNode::get_child(int idx) const 33.53 +{ 33.54 + return children[idx]; 33.55 +} 33.56 + 33.57 +SceneNode *SceneNode::get_parent() const 33.58 +{ 33.59 + return parent; 33.60 +} 33.61 + 33.62 +void SceneNode::add_object(Object *obj) 33.63 +{ 33.64 + if(std::find(this->obj.begin(), this->obj.end(), obj) == this->obj.end()) { 33.65 + this->obj.push_back(obj); 33.66 + } 33.67 +} 33.68 + 33.69 +int SceneNode::get_num_objects() const 33.70 +{ 33.71 + return (int)obj.size(); 33.72 +} 33.73 + 33.74 +Object *SceneNode::get_object(int idx) const 33.75 +{ 33.76 + return obj[idx]; 33.77 +} 33.78 + 33.79 +void SceneNode::set_position(const Vector3 &pos) 33.80 +{ 33.81 + this->pos = pos; 33.82 +} 33.83 + 33.84 +void SceneNode::set_rotation(const Quaternion &rot) 33.85 +{ 33.86 + this->rot = rot; 33.87 +} 33.88 + 33.89 +void SceneNode::set_scaling(const Vector3 &scale) 33.90 +{ 33.91 + this->scale = scale; 33.92 +} 33.93 + 33.94 + 33.95 +const Vector3 &SceneNode::get_node_position() const 33.96 +{ 33.97 + return pos; 33.98 +} 33.99 + 33.100 +const Quaternion &SceneNode::get_node_rotation() const 33.101 +{ 33.102 + return rot; 33.103 +} 33.104 + 33.105 +const Vector3 &SceneNode::get_node_scaling() const 33.106 +{ 33.107 + return scale; 33.108 +} 33.109 + 33.110 + 33.111 +Vector3 SceneNode::get_position() const 33.112 +{ 33.113 + return Vector3(0, 0, 0).transformed(xform); 33.114 +} 33.115 + 33.116 +Quaternion SceneNode::get_rotation() const 33.117 +{ 33.118 + return rot; // TODO 33.119 +} 33.120 + 33.121 +Vector3 SceneNode::get_scaling() const 33.122 +{ 33.123 + return scale; // TODO 33.124 +} 33.125 + 33.126 +const Matrix4x4 &SceneNode::get_matrix() const 33.127 +{ 33.128 + return xform; 33.129 +} 33.130 + 33.131 +const Matrix4x4 &SceneNode::get_inv_matrix() const 33.132 +{ 33.133 + return inv_xform; 33.134 +} 33.135 + 33.136 + 33.137 +void SceneNode::update_node(long msec) 33.138 +{ 33.139 + xform.reset_identity(); 33.140 + xform.translate(pos); 33.141 + xform.rotate(rot); 33.142 + xform.scale(scale); 33.143 + 33.144 + if(parent) { 33.145 + xform = parent->xform * xform; 33.146 + } 33.147 + inv_xform = xform.inverse(); 33.148 +} 33.149 + 33.150 +void SceneNode::update(long msec) 33.151 +{ 33.152 + update_node(msec); 33.153 + 33.154 + for(size_t i=0; i<children.size(); i++) { 33.155 + children[i]->update(msec); 33.156 + } 33.157 +} 33.158 + 33.159 + 33.160 +bool SceneNode::intersect(const Ray &ray, HitPoint *hit) const 33.161 +{ 33.162 + Ray local_ray = ray.transformed(inv_xform); 33.163 + 33.164 + HitPoint nearest; 33.165 + nearest.dist = FLT_MAX; 33.166 + for(size_t i=0; i<obj.size(); i++) { 33.167 + if(obj[i]->intersect(local_ray, hit)) { 33.168 + if(!hit) return true; 33.169 + if(hit->dist < nearest.dist) { 33.170 + nearest = *hit; 33.171 + nearest.node = this; 33.172 + } 33.173 + } 33.174 + } 33.175 + 33.176 + for(size_t i=0; i<children.size(); i++) { 33.177 + if(children[i]->intersect(ray, hit)) { 33.178 + if(!hit) return true; 33.179 + if(hit->dist < nearest.dist) { 33.180 + nearest = *hit; 33.181 + } 33.182 + } 33.183 + } 33.184 + 33.185 + if(nearest.dist < FLT_MAX) { 33.186 + *hit = nearest; 33.187 + hit->ray = ray; 33.188 + return true; 33.189 + } 33.190 + return false; 33.191 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/src/snode.h Sat Aug 22 07:15:00 2015 +0300 34.3 @@ -0,0 +1,60 @@ 34.4 +#ifndef SNODE_H_ 34.5 +#define SNODE_H_ 34.6 + 34.7 +#include <vector> 34.8 +#include "object.h" 34.9 +#include "vmath/vmath.h" 34.10 +#include "geom.h" 34.11 + 34.12 +class SceneNode { 34.13 +private: 34.14 + Vector3 pos; 34.15 + Quaternion rot; 34.16 + Vector3 scale; 34.17 + 34.18 + std::vector<Object*> obj; 34.19 + 34.20 + SceneNode *parent; 34.21 + std::vector<SceneNode*> children; 34.22 + 34.23 + Matrix4x4 xform; 34.24 + Matrix4x4 inv_xform; 34.25 + 34.26 +public: 34.27 + SceneNode(); 34.28 + explicit SceneNode(Object *obj); 34.29 + 34.30 + void add_child(SceneNode *node); 34.31 + bool remove_child(SceneNode *node); 34.32 + 34.33 + int get_num_children() const; 34.34 + SceneNode *get_child(int idx) const; 34.35 + 34.36 + SceneNode *get_parent() const; 34.37 + 34.38 + void add_object(Object *obj); 34.39 + int get_num_objects() const; 34.40 + Object *get_object(int idx) const; 34.41 + 34.42 + void set_position(const Vector3 &pos); 34.43 + void set_rotation(const Quaternion &rot); 34.44 + void set_scaling(const Vector3 &scale); 34.45 + 34.46 + const Vector3 &get_node_position() const; 34.47 + const Quaternion &get_node_rotation() const; 34.48 + const Vector3 &get_node_scaling() const; 34.49 + 34.50 + Vector3 get_position() const; 34.51 + Quaternion get_rotation() const; 34.52 + Vector3 get_scaling() const; 34.53 + 34.54 + const Matrix4x4 &get_matrix() const; 34.55 + const Matrix4x4 &get_inv_matrix() const; 34.56 + 34.57 + void update_node(long msec = 0); 34.58 + void update(long msec = 0); 34.59 + 34.60 + bool intersect(const Ray &ray, HitPoint *hit) const; 34.61 +}; 34.62 + 34.63 +#endif // SNODE_H_