istereo2
diff src/istereo.c @ 2:81d35769f546
added the tunnel effect source
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 19 Sep 2015 05:51:51 +0300 |
parents | |
children | d4fed8aac9a6 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/istereo.c Sat Sep 19 05:51:51 2015 +0300 1.3 @@ -0,0 +1,399 @@ 1.4 +/* 1.5 +Stereoscopic tunnel for iOS. 1.6 +Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 1.7 + 1.8 +This program is free software: you can redistribute it and/or modify 1.9 +it under the terms of the GNU General Public License as published by 1.10 +the Free Software Foundation, either version 3 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU General Public License 1.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 1.20 +*/ 1.21 + 1.22 + 1.23 +#include <stdio.h> 1.24 +#include <math.h> 1.25 +#include <assert.h> 1.26 +#include <unistd.h> 1.27 +#include "opengl.h" 1.28 +#include "istereo.h" 1.29 +#include "sanegl.h" 1.30 +#include "sdr.h" 1.31 +#include "respath.h" 1.32 +#include "tex.h" 1.33 +#include "cam.h" 1.34 +#include "vmath.h" 1.35 +#include "config.h" 1.36 + 1.37 +static void render(float t); 1.38 +static void draw_tunnel(float t); 1.39 +static void tunnel_vertex(float u, float v, float du, float dv, int tang_loc, float t); 1.40 +static vec3_t calc_text_pos(float sec); 1.41 +static void draw_text(float idx, vec3_t tpos, float alpha); 1.42 +static void worm(float t, float z, float *tx, float *ty); 1.43 +static unsigned int get_shader_program(const char *vfile, const char *pfile); 1.44 +static float get_sec(void); 1.45 + 1.46 +unsigned int prog, prog_simple, prog_tunnel, prog_text; 1.47 +unsigned int tex, tex_stones, tex_normal, tex_text; 1.48 + 1.49 +int view_xsz, view_ysz; 1.50 + 1.51 +int stereo = 0; 1.52 +int use_bump = 0; 1.53 + 1.54 +/* construction parameters */ 1.55 +int sides = 24; 1.56 +int segm = 20; 1.57 +float tunnel_speed = 0.75; 1.58 +float ring_height = 0.5; 1.59 +float text_period = 13.0; 1.60 +float text_speed = 2.2; 1.61 + 1.62 +float split = 0.5275; 1.63 + 1.64 +int init(void) 1.65 +{ 1.66 + add_resource_path("sdr"); 1.67 + add_resource_path("data"); 1.68 + 1.69 + if(!(prog_simple = get_shader_program("test.v.glsl", "test.p.glsl"))) { 1.70 + return -1; 1.71 + } 1.72 + if(!(prog_tunnel = get_shader_program("tunnel.v.glsl", "tunnel.p.glsl"))) { 1.73 + return -1; 1.74 + } 1.75 + if(!(prog_text = get_shader_program("text.v.glsl", "text.p.glsl"))) { 1.76 + return -1; 1.77 + } 1.78 + 1.79 + if(!(tex = load_texture(find_resource("tiles.jpg", 0, 0)))) { 1.80 + return -1; 1.81 + } 1.82 + if(!(tex_stones = load_texture(find_resource("stonewall.jpg", 0, 0)))) { 1.83 + return -1; 1.84 + } 1.85 + if(!(tex_normal = load_texture(find_resource("stonewall_normal.jpg", 0, 0)))) { 1.86 + return -1; 1.87 + } 1.88 + if(!(tex_text = load_texture(find_resource("text.png", 0, 0)))) { 1.89 + return -1; 1.90 + } 1.91 + 1.92 + glEnable(GL_DEPTH_TEST); 1.93 + glEnable(GL_CULL_FACE); 1.94 + 1.95 + cam_fov(42.5); 1.96 + cam_clip(0.5, 250.0); 1.97 + 1.98 + return 0; 1.99 +} 1.100 + 1.101 +void cleanup(void) 1.102 +{ 1.103 + free_program(prog); 1.104 +} 1.105 + 1.106 +void redraw(void) 1.107 +{ 1.108 + float pan_x, pan_y, z; 1.109 + float tsec = get_sec(); 1.110 + 1.111 + z = ring_height * segm; 1.112 + worm(tsec, z, &pan_x, &pan_y); 1.113 + 1.114 + if(use_bump) { 1.115 + glClearColor(0.01, 0.01, 0.01, 1.0); 1.116 + tunnel_speed = 0.5; 1.117 + } else { 1.118 + glClearColor(0.6, 0.6, 0.6, 1.0); 1.119 + tunnel_speed = 0.75; 1.120 + } 1.121 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1.122 + 1.123 + if(stereo) { 1.124 + int split_pt = (int)((float)view_ysz * split); 1.125 + 1.126 + /* right eye */ 1.127 + glViewport(0, 0, view_xsz, split_pt); 1.128 + cam_aspect((float)split_pt / (float)view_xsz); 1.129 + 1.130 + gl_matrix_mode(GL_PROJECTION); 1.131 + gl_load_identity(); 1.132 + cam_stereo_proj_matrix(CAM_RIGHT); 1.133 + gl_rotatef(-90, 0, 0, 1); 1.134 + 1.135 + gl_matrix_mode(GL_MODELVIEW); 1.136 + gl_load_identity(); 1.137 + cam_stereo_view_matrix(CAM_RIGHT); 1.138 + gl_translatef(-pan_x, -pan_y, -1.1 * ring_height * segm); 1.139 + 1.140 + render(tsec); 1.141 + 1.142 + /* left eye */ 1.143 + glViewport(0, split_pt, view_xsz, view_ysz - split_pt); 1.144 + cam_aspect((float)(view_ysz - split_pt) / (float)view_xsz); 1.145 + 1.146 + gl_matrix_mode(GL_PROJECTION); 1.147 + gl_load_identity(); 1.148 + cam_stereo_proj_matrix(CAM_LEFT); 1.149 + gl_rotatef(-90, 0, 0, 1); 1.150 + 1.151 + gl_matrix_mode(GL_MODELVIEW); 1.152 + gl_load_identity(); 1.153 + cam_stereo_view_matrix(CAM_LEFT); 1.154 + gl_translatef(-pan_x, -pan_y, -1.1 * ring_height * segm); 1.155 + 1.156 + render(tsec); 1.157 + } else { 1.158 + glViewport(0, 0, view_xsz, view_ysz); 1.159 + cam_aspect((float)view_xsz / (float)view_ysz); 1.160 + 1.161 + gl_matrix_mode(GL_PROJECTION); 1.162 + gl_load_identity(); 1.163 + gl_rotatef(-90, 0, 0, 1); 1.164 + cam_proj_matrix(); 1.165 + 1.166 + gl_matrix_mode(GL_MODELVIEW); 1.167 + gl_load_identity(); 1.168 + cam_view_matrix(); 1.169 + gl_translatef(-pan_x, -pan_y, -1.1 * ring_height * segm); 1.170 + 1.171 + render(tsec); 1.172 + } 1.173 + 1.174 + assert(glGetError() == GL_NO_ERROR); 1.175 +} 1.176 + 1.177 +static void render(float t) 1.178 +{ 1.179 + int i; 1.180 + float text_line; 1.181 + 1.182 + draw_tunnel(t); 1.183 + 1.184 + if(use_bump) { 1.185 + glDepthMask(0); 1.186 + text_line = floor((text_speed * t) / text_period); 1.187 + for(i=0; i<8; i++) { 1.188 + vec3_t tpos = calc_text_pos(t - (float)i * 0.011); 1.189 + draw_text(text_line, tpos, 1.5 / (float)i); 1.190 + } 1.191 + glDepthMask(1); 1.192 + } 1.193 +} 1.194 + 1.195 +static void draw_tunnel(float t) 1.196 +{ 1.197 + static const float uoffs[] = {0.0, 0.0, 1.0, 1.0}; 1.198 + static const float voffs[] = {0.0, 1.0, 1.0, 0.0}; 1.199 + int i, j, k, tang_loc = -1; 1.200 + float du, dv; 1.201 + 1.202 + prog = use_bump ? prog_tunnel : prog_simple; 1.203 + 1.204 + bind_program(prog); 1.205 + set_uniform_float(prog, "t", t); 1.206 + 1.207 + if(use_bump) { 1.208 + vec3_t ltpos = calc_text_pos(t); 1.209 + 1.210 + bind_texture(tex_normal, 1); 1.211 + set_uniform_int(prog, "tex_norm", 1); 1.212 + bind_texture(tex_stones, 0); 1.213 + set_uniform_int(prog, "tex", 0); 1.214 + 1.215 + set_uniform_float4(prog, "light_pos", ltpos.x, ltpos.y, ltpos.z, 1.0); 1.216 + tang_loc = get_attrib_loc(prog, "attr_tangent"); 1.217 + } else { 1.218 + bind_texture(tex, 0); 1.219 + set_uniform_int(prog, "tex", 0); 1.220 + } 1.221 + 1.222 + gl_matrix_mode(GL_TEXTURE); 1.223 + gl_load_identity(); 1.224 + gl_translatef(0, -fmod(t * tunnel_speed, 1.0), 0); 1.225 + 1.226 + gl_begin(GL_QUADS); 1.227 + gl_color3f(1.0, 1.0, 1.0); 1.228 + 1.229 + du = 1.0 / sides; 1.230 + dv = 1.0 / segm; 1.231 + 1.232 + for(i=0; i<segm; i++) { 1.233 + float trans_zp[2], trans_z0[2], trans_z1[2]; 1.234 + 1.235 + float zp = ring_height * (i - 1); 1.236 + float z0 = ring_height * i; 1.237 + float z1 = ring_height * (i + 1); 1.238 + 1.239 + worm(t, zp, trans_zp, trans_zp + 1); 1.240 + worm(t, z0, trans_z0, trans_z0 + 1); 1.241 + worm(t, z1, trans_z1, trans_z1 + 1); 1.242 + 1.243 + for(j=0; j<sides; j++) { 1.244 + for(k=0; k<4; k++) { 1.245 + float u = (j + uoffs[k]) * du; 1.246 + float v = (i + voffs[k]) * dv; 1.247 + 1.248 + tunnel_vertex(u, v, du, dv, tang_loc, t); 1.249 + } 1.250 + } 1.251 + } 1.252 + gl_end(); 1.253 + 1.254 + bind_texture(0, 1); 1.255 + bind_texture(0, 0); 1.256 +} 1.257 + 1.258 +static void tunnel_vertex(float u, float v, float du, float dv, int tang_loc, float t) 1.259 +{ 1.260 + vec3_t pos, norm; 1.261 + vec3_t dfdu, dfdv, pos_du, pos_dv; 1.262 + 1.263 + float theta = 2.0 * M_PI * u; 1.264 + float theta1 = 2.0 * M_PI * (u + du); 1.265 + 1.266 + float x = cos(theta); 1.267 + float y = sin(theta); 1.268 + float x1 = cos(theta1); 1.269 + float y1 = sin(theta1); 1.270 + float z = v / dv * ring_height; 1.271 + float z1 = (v + dv) / dv * ring_height; 1.272 + 1.273 + float trans_z[2], trans_z1[2]; 1.274 + 1.275 + worm(t, z, trans_z, trans_z + 1); 1.276 + worm(t, z1, trans_z1, trans_z1 + 1); 1.277 + 1.278 + pos = v3_cons(x + trans_z[0], y + trans_z[1], z); 1.279 + pos_du = v3_cons(x1 + trans_z[0], y1 + trans_z[1], z); 1.280 + pos_dv = v3_cons(x + trans_z1[0], y + trans_z1[1], z1); 1.281 + 1.282 + dfdu = v3_sub(pos_du, pos); 1.283 + dfdv = v3_sub(pos_dv, pos); 1.284 + norm = v3_cross(dfdv, dfdu); 1.285 + 1.286 + gl_vertex_attrib3f(tang_loc, dfdu.x, dfdu.y, dfdu.z); 1.287 + gl_normal3f(norm.x, norm.y, norm.z); 1.288 + gl_texcoord2f(u * 2.0, v * 4.0); 1.289 + gl_vertex3f(pos.x, pos.y, pos.z); 1.290 +} 1.291 + 1.292 +static vec3_t calc_text_pos(float sec) 1.293 +{ 1.294 + float t = text_speed * sec; 1.295 + float z = fmod(t, text_period); 1.296 + float pan[2]; 1.297 + 1.298 + worm(sec, z, pan, pan + 1); 1.299 + return v3_cons(pan[0], pan[1], z + ring_height); 1.300 +} 1.301 + 1.302 +static void draw_text(float idx, vec3_t tpos, float alpha) 1.303 +{ 1.304 + gl_matrix_mode(GL_MODELVIEW); 1.305 + gl_push_matrix(); 1.306 + gl_translatef(tpos.x, tpos.y, tpos.z); 1.307 + 1.308 + glEnable(GL_BLEND); 1.309 + glBlendFunc(GL_SRC_ALPHA, GL_ONE); 1.310 + 1.311 + bind_program(prog_text); 1.312 + set_uniform_float(prog_text, "idx", idx); 1.313 + 1.314 + bind_texture(tex_text, 0); 1.315 + 1.316 + gl_begin(GL_QUADS); 1.317 + gl_color4f(1.0, 1.0, 1.0, alpha > 1.0 ? 1.0 : alpha); 1.318 + 1.319 + gl_texcoord2f(0, 1); 1.320 + gl_vertex3f(-1, -0.2, 0); 1.321 + 1.322 + gl_texcoord2f(1, 1); 1.323 + gl_vertex3f(1, -0.2, 0); 1.324 + 1.325 + gl_texcoord2f(1, 0); 1.326 + gl_vertex3f(1, 0.2, 0); 1.327 + 1.328 + gl_texcoord2f(0, 0); 1.329 + gl_vertex3f(-1, 0.2, 0); 1.330 + gl_end(); 1.331 + 1.332 + bind_texture(0, 0); 1.333 + glDisable(GL_BLEND); 1.334 + 1.335 + gl_pop_matrix(); 1.336 +} 1.337 + 1.338 + 1.339 +static void worm(float t, float z, float *tx, float *ty) 1.340 +{ 1.341 + float x, y; 1.342 + x = sin(t) + cos(t + z) + sin(t * 2.0 + z) / 2.0; 1.343 + y = cos(t) + sin(t + z) + cos(t * 2.0 + z) / 2.0; 1.344 + 1.345 + *tx = x * 0.5; 1.346 + *ty = y * 0.5; 1.347 +} 1.348 + 1.349 + 1.350 +void reshape(int x, int y) 1.351 +{ 1.352 + glViewport(0, 0, x, y); 1.353 + 1.354 + gl_matrix_mode(GL_PROJECTION); 1.355 + gl_load_identity(); 1.356 + glu_perspective(40.0, (float)x / (float)y, 0.5, 500.0); 1.357 + 1.358 + view_xsz = x; 1.359 + view_ysz = y; 1.360 +} 1.361 + 1.362 +static unsigned int get_shader_program(const char *vfile, const char *pfile) 1.363 +{ 1.364 + unsigned int prog, vs, ps; 1.365 + 1.366 + if(!(vs = get_vertex_shader(find_resource(vfile, 0, 0)))) { 1.367 + return 0; 1.368 + } 1.369 + if(!(ps = get_pixel_shader(find_resource(pfile, 0, 0)))) { 1.370 + return 0; 1.371 + } 1.372 + 1.373 + if(!(prog = create_program_link(vs, ps))) { 1.374 + return 0; 1.375 + } 1.376 + return prog; 1.377 +} 1.378 + 1.379 + 1.380 +#ifdef IPHONE 1.381 +#include <QuartzCore/QuartzCore.h> 1.382 + 1.383 +static float get_sec(void) 1.384 +{ 1.385 + static float first; 1.386 + static int init; 1.387 + 1.388 + if(!init) { 1.389 + init = 1; 1.390 + first = CACurrentMediaTime(); 1.391 + return 0.0f; 1.392 + } 1.393 + return CACurrentMediaTime() - first; 1.394 +} 1.395 + 1.396 +#else 1.397 + 1.398 +static float get_sec(void) 1.399 +{ 1.400 + return (float)glutGet(GLUT_ELAPSED_TIME) / 1000.0f; 1.401 +} 1.402 +#endif