vrshoot
diff src/unistate.cc @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/unistate.cc Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,678 @@ 1.4 +#include <map> 1.5 +#include <vector> 1.6 +#include "unistate.h" 1.7 +#include "shader.h" 1.8 +#include "logger.h" 1.9 + 1.10 +struct StateItem { 1.11 + StType type; 1.12 + 1.13 + union { 1.14 + int ival[4]; 1.15 + float fval[16]; 1.16 + }; 1.17 + int transpose; // for matrices 1.18 +}; 1.19 + 1.20 +static const char *typestr(StType type); 1.21 +static int type_nelem(StType type); 1.22 +static StType float_type(int elem); 1.23 +static StType int_type(int elem); 1.24 + 1.25 +std::vector<StateItem> state; 1.26 +std::map<std::string, int> stateidx; 1.27 + 1.28 + 1.29 +int add_unistate(const char *name, StType type) 1.30 +{ 1.31 + static const float ident3[] = {1, 0, 0, 0, 1, 0, 0, 0, 1}; 1.32 + static const float ident4[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 1.33 + 1.34 + if(stateidx.find(name) != stateidx.end()) { 1.35 + return stateidx[name]; 1.36 + } 1.37 + 1.38 + StateItem sitem; 1.39 + memset(&sitem, 0, sizeof sitem); 1.40 + sitem.type = type; 1.41 + 1.42 + // initialize to a reasonable default value 1.43 + switch(type) { 1.44 + case ST_MATRIX3: 1.45 + memcpy(sitem.fval, ident3, sizeof ident3); 1.46 + break; 1.47 + 1.48 + case ST_MATRIX4: 1.49 + memcpy(sitem.fval, ident4, sizeof ident4); 1.50 + break; 1.51 + 1.52 + default: 1.53 + break; // in all other cases leave it zero (see memset above) 1.54 + } 1.55 + 1.56 + int sidx = state.size(); 1.57 + state.push_back(sitem); 1.58 + stateidx[name] = sidx; 1.59 + 1.60 + debug_log("adding uniform state [%d]: %s %s\n", sidx, typestr(sitem.type), name); 1.61 + 1.62 + return sidx; 1.63 +} 1.64 + 1.65 +int get_unistate_index(const char *name) 1.66 +{ 1.67 + std::map<std::string, int>::const_iterator it = stateidx.find(name); 1.68 + if(it != stateidx.end()) { 1.69 + return it->second; 1.70 + } 1.71 + return -1; 1.72 +} 1.73 + 1.74 +#define CHECK_INDEX(i) \ 1.75 + if(i < 0 || i >= (int)state.size()) return 1.76 + 1.77 +#define CHECK_COUNT(count, type) \ 1.78 + do { \ 1.79 + int max_elem = type_nelem(type); \ 1.80 + if(!(count) || (count) > max_elem) { \ 1.81 + count = max_elem; \ 1.82 + } \ 1.83 + } while(0) 1.84 + 1.85 +void set_unistate(int sidx, const int *val, int count) 1.86 +{ 1.87 + CHECK_INDEX(sidx); 1.88 + CHECK_COUNT(count, state[sidx].type); 1.89 + 1.90 + memcpy(state[sidx].ival, val, count * sizeof *state[sidx].ival); 1.91 +} 1.92 + 1.93 +void set_unistate(int sidx, const float *val, int count) 1.94 +{ 1.95 + CHECK_INDEX(sidx); 1.96 + CHECK_COUNT(count, state[sidx].type); 1.97 + 1.98 + memcpy(state[sidx].fval, val, count * sizeof *state[sidx].fval); 1.99 + state[sidx].transpose = 0; 1.100 +} 1.101 + 1.102 +void get_unistate(int sidx, int *val, int count) 1.103 +{ 1.104 + CHECK_INDEX(sidx); 1.105 + CHECK_COUNT(count, state[sidx].type); 1.106 + 1.107 + memcpy(val, state[sidx].ival, count * sizeof *val); 1.108 +} 1.109 + 1.110 +void get_unistate(int sidx, float *val, int count) 1.111 +{ 1.112 + CHECK_INDEX(sidx); 1.113 + CHECK_COUNT(count, state[sidx].type); 1.114 + 1.115 + memcpy(val, state[sidx].fval, count * sizeof *val); 1.116 +} 1.117 + 1.118 +void set_unistate(int sidx, int val) 1.119 +{ 1.120 + set_unistate(sidx, &val, 1); 1.121 +} 1.122 + 1.123 +void set_unistate(int sidx, float val) 1.124 +{ 1.125 + set_unistate(sidx, &val, 1); 1.126 +} 1.127 + 1.128 +void set_unistate(int sidx, const Vector2 &vec) 1.129 +{ 1.130 + set_unistate(sidx, &vec.x, 2); 1.131 +} 1.132 + 1.133 +void set_unistate(int sidx, const Vector3 &vec) 1.134 +{ 1.135 + set_unistate(sidx, &vec.x, 3); 1.136 +} 1.137 + 1.138 +void set_unistate(int sidx, const Vector4 &vec) 1.139 +{ 1.140 + set_unistate(sidx, &vec.x, 4); 1.141 +} 1.142 + 1.143 +void set_unistate(int sidx, const Matrix3x3 &mat) 1.144 +{ 1.145 + set_unistate(sidx, mat[0], 9); 1.146 + state[sidx].transpose = 1; 1.147 +} 1.148 + 1.149 +void set_unistate(int sidx, const Matrix4x4 &mat) 1.150 +{ 1.151 + set_unistate(sidx, mat[0], 16); 1.152 + state[sidx].transpose = 1; 1.153 +} 1.154 + 1.155 + 1.156 +int set_unistate(const char *name, int *val, int count) 1.157 +{ 1.158 + int sidx = get_unistate_index(name); 1.159 + if(sidx < 0) { 1.160 + StType type = int_type(count); 1.161 + if(type == ST_UNKNOWN) { 1.162 + error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n", 1.163 + count, name); 1.164 + return -1; 1.165 + } 1.166 + 1.167 + sidx = add_unistate(name, type); 1.168 + } 1.169 + set_unistate(sidx, val); 1.170 + return sidx; 1.171 +} 1.172 + 1.173 +int set_unistate(const char *name, float *val, int count) 1.174 +{ 1.175 + int sidx = get_unistate_index(name); 1.176 + if(sidx < 0) { 1.177 + StType type = float_type(count); 1.178 + if(type == ST_UNKNOWN) { 1.179 + error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n", 1.180 + count, name); 1.181 + return -1; 1.182 + } 1.183 + 1.184 + sidx = add_unistate(name, type); 1.185 + } 1.186 + set_unistate(sidx, val); 1.187 + return sidx; 1.188 +} 1.189 + 1.190 +int set_unistate(const char *name, int val) 1.191 +{ 1.192 + int sidx = get_unistate_index(name); 1.193 + if(sidx < 0) { 1.194 + sidx = add_unistate(name, ST_INT); 1.195 + } 1.196 + set_unistate(sidx, val); 1.197 + return sidx; 1.198 +} 1.199 + 1.200 +int set_unistate(const char *name, float val) 1.201 +{ 1.202 + int sidx = get_unistate_index(name); 1.203 + if(sidx < 0) { 1.204 + sidx = add_unistate(name, ST_FLOAT); 1.205 + } 1.206 + set_unistate(sidx, val); 1.207 + return sidx; 1.208 +} 1.209 + 1.210 +int set_unistate(const char *name, const Vector2 &vec) 1.211 +{ 1.212 + int sidx = get_unistate_index(name); 1.213 + if(sidx < 0) { 1.214 + sidx = add_unistate(name, ST_FLOAT2); 1.215 + } 1.216 + set_unistate(sidx, vec); 1.217 + return sidx; 1.218 +} 1.219 + 1.220 +int set_unistate(const char *name, const Vector3 &vec) 1.221 +{ 1.222 + int sidx = get_unistate_index(name); 1.223 + if(sidx < 0) { 1.224 + sidx = add_unistate(name, ST_FLOAT3); 1.225 + } 1.226 + set_unistate(sidx, vec); 1.227 + return sidx; 1.228 +} 1.229 + 1.230 +int set_unistate(const char *name, const Vector4 &vec) 1.231 +{ 1.232 + int sidx = get_unistate_index(name); 1.233 + if(sidx < 0) { 1.234 + sidx = add_unistate(name, ST_FLOAT4); 1.235 + } 1.236 + set_unistate(sidx, vec); 1.237 + return sidx; 1.238 +} 1.239 + 1.240 +int set_unistate(const char *name, const Matrix3x3 &mat) 1.241 +{ 1.242 + int sidx = get_unistate_index(name); 1.243 + if(sidx < 0) { 1.244 + sidx = add_unistate(name, ST_MATRIX3); 1.245 + } 1.246 + set_unistate(sidx, mat); 1.247 + return sidx; 1.248 +} 1.249 + 1.250 +int set_unistate(const char *name, const Matrix4x4 &mat) 1.251 +{ 1.252 + int sidx = get_unistate_index(name); 1.253 + if(sidx < 0) { 1.254 + sidx = add_unistate(name, ST_MATRIX4); 1.255 + } 1.256 + set_unistate(sidx, mat); 1.257 + return sidx; 1.258 +} 1.259 + 1.260 + 1.261 +int get_unistate_int(int sidx) 1.262 +{ 1.263 + int val = 0; 1.264 + get_unistate(sidx, &val, 1); 1.265 + return val; 1.266 +} 1.267 + 1.268 +float get_unistate_float(int sidx) 1.269 +{ 1.270 + float val = 0.0f; 1.271 + get_unistate(sidx, &val, 1); 1.272 + return val; 1.273 +} 1.274 + 1.275 +Vector2 get_unistate_vec2(int sidx) 1.276 +{ 1.277 + float val[2] = {0.0f, 0.0f}; 1.278 + get_unistate(sidx, val, 2); 1.279 + return Vector2(val[0], val[1]); 1.280 +} 1.281 + 1.282 +Vector3 get_unistate_vec3(int sidx) 1.283 +{ 1.284 + float val[3] = {0.0f, 0.0f, 0.0f}; 1.285 + get_unistate(sidx, val, 3); 1.286 + return Vector3(val[0], val[1], val[2]); 1.287 +} 1.288 + 1.289 +Vector4 get_unistate_vec4(int sidx) 1.290 +{ 1.291 + float val[4] = {0.0f, 0.0f, 0.0f}; 1.292 + get_unistate(sidx, val, 4); 1.293 + return Vector4(val[0], val[1], val[2], val[3]); 1.294 +} 1.295 + 1.296 +Matrix3x3 get_unistate_mat3(int sidx) 1.297 +{ 1.298 + Matrix3x3 res; 1.299 + get_unistate(sidx, res.m[0], 9); 1.300 + return res; 1.301 +} 1.302 + 1.303 +Matrix4x4 get_unistate_mat4(int sidx) 1.304 +{ 1.305 + Matrix4x4 res; 1.306 + get_unistate(sidx, res.m[0], 16); 1.307 + return res; 1.308 +} 1.309 + 1.310 + 1.311 +int get_unistate_int(const char *name) 1.312 +{ 1.313 + int sidx = get_unistate_index(name); 1.314 + if(sidx == -1) { 1.315 + return 0; 1.316 + } 1.317 + return get_unistate_int(sidx); 1.318 +} 1.319 + 1.320 +float get_unistate_float(const char *name) 1.321 +{ 1.322 + int sidx = get_unistate_index(name); 1.323 + if(sidx == -1) { 1.324 + return 0.0f; 1.325 + } 1.326 + return get_unistate_float(sidx); 1.327 +} 1.328 + 1.329 +Vector2 get_unistate_vec2(const char *name) 1.330 +{ 1.331 + int sidx = get_unistate_index(name); 1.332 + if(sidx == -1) { 1.333 + return Vector2(); 1.334 + } 1.335 + return get_unistate_vec2(sidx); 1.336 +} 1.337 + 1.338 +Vector3 get_unistate_vec3(const char *name) 1.339 +{ 1.340 + int sidx = get_unistate_index(name); 1.341 + if(sidx == -1) { 1.342 + return Vector3(); 1.343 + } 1.344 + return get_unistate_vec3(sidx); 1.345 +} 1.346 + 1.347 +Vector4 get_unistate_vec4(const char *name) 1.348 +{ 1.349 + int sidx = get_unistate_index(name); 1.350 + if(sidx == -1) { 1.351 + return Vector4(); 1.352 + } 1.353 + return get_unistate_vec4(sidx); 1.354 +} 1.355 + 1.356 +Matrix3x3 get_unistate_mat3(const char *name) 1.357 +{ 1.358 + int sidx = get_unistate_index(name); 1.359 + if(sidx == -1) { 1.360 + return Matrix3x3(); 1.361 + } 1.362 + return get_unistate_mat3(sidx); 1.363 +} 1.364 + 1.365 +Matrix4x4 get_unistate_mat4(const char *name) 1.366 +{ 1.367 + int sidx = get_unistate_index(name); 1.368 + if(sidx == -1) { 1.369 + return Matrix4x4(); 1.370 + } 1.371 + return get_unistate_mat4(sidx); 1.372 +} 1.373 + 1.374 + 1.375 +void setup_unistate(const ShaderProg *sdr) 1.376 +{ 1.377 + if(!sdr) { 1.378 + if(!(sdr = ShaderProg::current)) { 1.379 + return; 1.380 + } 1.381 + } 1.382 + 1.383 + sdr->setup_state_uniforms(); 1.384 +} 1.385 + 1.386 +bool setup_unistate(int sidx, const ShaderProg *sdr, int loc) 1.387 +{ 1.388 + if(loc < 0 || sidx < 0 || sidx >= (int)state.size()) { 1.389 + return false; 1.390 + } 1.391 + 1.392 + CHECKGLERR; 1.393 + glUseProgram(sdr->get_id()); 1.394 + CHECKGLERR; 1.395 + 1.396 + switch(state[sidx].type) { 1.397 + case ST_INT: 1.398 + glUniform1iv(loc, 1, state[sidx].ival); 1.399 + break; 1.400 + case ST_INT2: 1.401 + glUniform2iv(loc, 1, state[sidx].ival); 1.402 + break; 1.403 + case ST_INT3: 1.404 + glUniform3iv(loc, 1, state[sidx].ival); 1.405 + break; 1.406 + case ST_INT4: 1.407 + glUniform4iv(loc, 1, state[sidx].ival); 1.408 + break; 1.409 + 1.410 + case ST_FLOAT: 1.411 + glUniform1fv(loc, 1, state[sidx].fval); 1.412 + break; 1.413 + case ST_FLOAT2: 1.414 + glUniform2fv(loc, 1, state[sidx].fval); 1.415 + break; 1.416 + case ST_FLOAT3: 1.417 + glUniform3fv(loc, 1, state[sidx].fval); 1.418 + break; 1.419 + case ST_FLOAT4: 1.420 + glUniform4fv(loc, 1, state[sidx].fval); 1.421 + break; 1.422 + 1.423 + case ST_MATRIX3: 1.424 +#ifdef GL_ES_VERSION_2_0 1.425 + { 1.426 + float tmat[9], *ptr = tmat; 1.427 + for(int i=0; i<3; i++) { 1.428 + for(int j=0; j<3; j++) { 1.429 + *ptr++ = state[sidx].fval[j * 3 + i]; 1.430 + } 1.431 + } 1.432 + glUniformMatrix3fv(loc, 1, GL_FALSE, tmat); 1.433 + } 1.434 +#else 1.435 + glUniformMatrix3fv(loc, 1, state[sidx].transpose, state[sidx].fval); 1.436 +#endif 1.437 + break; 1.438 + 1.439 + case ST_MATRIX4: 1.440 +#ifdef GL_ES_VERSION_2_0 1.441 + { 1.442 + float tmat[16], *ptr = tmat; 1.443 + for(int i=0; i<4; i++) { 1.444 + for(int j=0; j<4; j++) { 1.445 + *ptr++ = state[sidx].fval[j * 4 + i]; 1.446 + } 1.447 + } 1.448 + glUniformMatrix4fv(loc, 1, GL_FALSE, tmat); 1.449 + } 1.450 +#else 1.451 + glUniformMatrix4fv(loc, 1, state[sidx].transpose, state[sidx].fval); 1.452 +#endif 1.453 + break; 1.454 + 1.455 + default: 1.456 + return false; 1.457 + } 1.458 + 1.459 + CHECKGLERR; 1.460 + return true; 1.461 +} 1.462 + 1.463 +bool setup_unistate(const char *name, const ShaderProg *sdr) 1.464 +{ 1.465 + int loc = sdr->get_uniform_location(name); 1.466 + if(loc == -1) { 1.467 + return false; 1.468 + } 1.469 + return setup_unistate(get_unistate_index(name), sdr, loc); 1.470 +} 1.471 + 1.472 +void set_world_matrix(const Matrix4x4 &mat) 1.473 +{ 1.474 + static int sidx = -1, sidx_transp, sidx_mat3; 1.475 + 1.476 + if(sidx == -1) { 1.477 + sidx = add_unistate("st_world_matrix", ST_MATRIX4); 1.478 + sidx_mat3 = add_unistate("st_world_matrix3", ST_MATRIX3); 1.479 + sidx_transp = add_unistate("st_world_matrix_transpose", ST_MATRIX4); 1.480 + } 1.481 + 1.482 + set_unistate(sidx, mat); 1.483 + set_unistate(sidx_mat3, Matrix3x3(mat)); 1.484 + set_unistate(sidx_transp, mat[0]); // by using the float* variant, we unset the transpose flag 1.485 +} 1.486 + 1.487 +void set_view_matrix(const Matrix4x4 &mat) 1.488 +{ 1.489 + static int sidx = -1, sidx_transp, sidx_mat3; 1.490 + 1.491 + if(sidx == -1) { 1.492 + sidx = add_unistate("st_view_matrix", ST_MATRIX4); 1.493 + sidx_mat3 = add_unistate("st_view_matrix3", ST_MATRIX3); 1.494 + sidx_transp = add_unistate("st_view_matrix_transpose", ST_MATRIX4); 1.495 + } 1.496 + 1.497 + set_unistate(sidx, mat); 1.498 + set_unistate(sidx_mat3, Matrix3x3(mat)); 1.499 + set_unistate(sidx_transp, mat[0]); // by using the float* variant, we unset the transpose flag 1.500 +} 1.501 + 1.502 +void set_projection_matrix(const Matrix4x4 &mat) 1.503 +{ 1.504 + static int sidx = -1; 1.505 + 1.506 + if(sidx == -1) { 1.507 + sidx = add_unistate("st_proj_matrix", ST_MATRIX4); 1.508 + } 1.509 + 1.510 + set_unistate(sidx, mat); 1.511 +} 1.512 + 1.513 +void set_texture_matrix(const Matrix4x4 &mat) 1.514 +{ 1.515 + static int sidx = -1; 1.516 + 1.517 + if(sidx == -1) { 1.518 + sidx = add_unistate("st_tex_matrix", ST_MATRIX4); 1.519 + } 1.520 + 1.521 + set_unistate(sidx, mat); 1.522 +} 1.523 + 1.524 +Matrix4x4 get_world_matrix() 1.525 +{ 1.526 + static int sidx = -1; 1.527 + 1.528 + if(sidx == -1) { 1.529 + if((sidx = get_unistate_index("st_world_matrix")) == -1) { 1.530 + return Matrix4x4(); 1.531 + } 1.532 + } 1.533 + return get_unistate_mat4(sidx); 1.534 +} 1.535 + 1.536 +Matrix4x4 get_view_matrix() 1.537 +{ 1.538 + static int sidx = -1; 1.539 + 1.540 + if(sidx == -1) { 1.541 + if((sidx = get_unistate_index("st_view_matrix")) == -1) { 1.542 + return Matrix4x4(); 1.543 + } 1.544 + } 1.545 + return get_unistate_mat4(sidx); 1.546 +} 1.547 + 1.548 +Matrix4x4 get_projection_matrix() 1.549 +{ 1.550 + static int sidx = -1; 1.551 + 1.552 + if(sidx == -1) { 1.553 + if((sidx = get_unistate_index("st_proj_matrix")) == -1) { 1.554 + return Matrix4x4(); 1.555 + } 1.556 + } 1.557 + return get_unistate_mat4(sidx); 1.558 +} 1.559 + 1.560 +Matrix4x4 get_texture_matrix() 1.561 +{ 1.562 + static int sidx = -1; 1.563 + 1.564 + if(sidx == -1) { 1.565 + if((sidx = get_unistate_index("st_tex_matrix")) == -1) { 1.566 + return Matrix4x4(); 1.567 + } 1.568 + } 1.569 + return get_unistate_mat4(sidx); 1.570 +} 1.571 + 1.572 +void setup_gl_matrices() 1.573 +{ 1.574 +#ifdef USE_OLDGL 1.575 + Matrix4x4 modelview = get_world_matrix() * get_view_matrix(); 1.576 + Matrix4x4 proj = get_projection_matrix(); 1.577 + Matrix4x4 tex = get_texture_matrix(); 1.578 + 1.579 + glMatrixMode(GL_TEXTURE); 1.580 + glLoadTransposeMatrixf(tex[0]); 1.581 + glMatrixMode(GL_PROJECTION); 1.582 + glLoadTransposeMatrixf(proj[0]); 1.583 + glMatrixMode(GL_MODELVIEW); 1.584 + glLoadTransposeMatrixf(modelview[0]); 1.585 +#endif 1.586 +} 1.587 + 1.588 +static const char *typestr(StType type) 1.589 +{ 1.590 + switch(type) { 1.591 + case ST_INT: 1.592 + return "int"; 1.593 + case ST_INT2: 1.594 + return "ivec2"; 1.595 + case ST_INT3: 1.596 + return "ivec3"; 1.597 + case ST_INT4: 1.598 + return "ivec4"; 1.599 + case ST_FLOAT: 1.600 + return "float"; 1.601 + case ST_FLOAT2: 1.602 + return "vec2"; 1.603 + case ST_FLOAT3: 1.604 + return "vec3"; 1.605 + case ST_FLOAT4: 1.606 + return "vec4"; 1.607 + case ST_MATRIX3: 1.608 + return "mat3"; 1.609 + case ST_MATRIX4: 1.610 + return "mat4"; 1.611 + 1.612 + default: 1.613 + break; 1.614 + } 1.615 + return "<unknown>"; 1.616 +} 1.617 + 1.618 +static int type_nelem(StType type) 1.619 +{ 1.620 + switch(type) { 1.621 + case ST_INT: 1.622 + case ST_FLOAT: 1.623 + return 1; 1.624 + case ST_INT2: 1.625 + case ST_FLOAT2: 1.626 + return 2; 1.627 + case ST_INT3: 1.628 + case ST_FLOAT3: 1.629 + return 3; 1.630 + case ST_INT4: 1.631 + case ST_FLOAT4: 1.632 + return 4; 1.633 + case ST_MATRIX3: 1.634 + return 9; 1.635 + case ST_MATRIX4: 1.636 + return 16; 1.637 + 1.638 + default: 1.639 + break; 1.640 + } 1.641 + 1.642 + return 0; 1.643 +} 1.644 + 1.645 +static StType float_type(int elem) 1.646 +{ 1.647 + switch(elem) { 1.648 + case 1: 1.649 + return ST_FLOAT; 1.650 + case 2: 1.651 + return ST_FLOAT2; 1.652 + case 3: 1.653 + return ST_FLOAT3; 1.654 + case 4: 1.655 + return ST_FLOAT4; 1.656 + case 9: 1.657 + return ST_MATRIX3; 1.658 + case 16: 1.659 + return ST_MATRIX4; 1.660 + default: 1.661 + break; 1.662 + } 1.663 + return ST_UNKNOWN; 1.664 +} 1.665 + 1.666 +static StType int_type(int elem) 1.667 +{ 1.668 + switch(elem) { 1.669 + case 1: 1.670 + return ST_INT; 1.671 + case 2: 1.672 + return ST_INT2; 1.673 + case 3: 1.674 + return ST_INT3; 1.675 + case 4: 1.676 + return ST_INT4; 1.677 + default: 1.678 + break; 1.679 + } 1.680 + return ST_UNKNOWN; 1.681 +}