void armature_matrices(Armature *a, int frame, mat4 *matrices) { int i; for(i = 0; i < a->nbones; i++) { Bone *bone = &a->bones[i]; Pose *bpose = &bone->poses[frame]; mat4 tmp; mat4_identity(matrices[i]); quat q; memcpy(&q, bpose->rotation, sizeof(float) * 4); quaternion_to_mat4(q, tmp); mat4_translate(matrices[i], -bone->head[0], -bone->head[1], -bone->head[2]); mat4_mult(matrices[i], tmp, matrices[i]); mat4_translate(matrices[i], bone->head[0], bone->head[1], bone->head[2]); mat4_translate(matrices[i], bpose->position[0], bpose->position[1], bpose->position[2]); if(bone_hasparent(bone)) { mat4_mult(matrices[bone->parent->id], matrices[i], matrices[i]); } } }
void model_draw(struct Model *model, float *mMat, float *vMat, float *pMat) { glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); mat4 t_matrix; mat4_identity(t_matrix); mat4_mult(mMat, t_matrix, t_matrix); mat4_mult(vMat, t_matrix, t_matrix); mat4_mult(pMat, t_matrix, t_matrix); //mat4_transpose(t_matrix); int i; for(i = 0; i < varray_length(&model->features); i++) { static int FALSE = 0; const ModelFeature *feature = varray_get(&model->features, i); glbProgramTexture(glbdrawmodel, GLB_FRAGMENT_SHADER, 0, feature->color); glbProgramUniformMatrix(glbdrawmodel, GLB_VERTEX_SHADER, 0, sizeof(int), true, &FALSE); glbProgramUniformMatrix(glbdrawmodel, GLB_VERTEX_SHADER, 1, sizeof(float[16]), true, t_matrix); glbProgramDrawIndexed(glbdrawmodel, feature->mesh->vbuffer, feature->mesh->ibuffer); } }
void mesh_draw_ts (struct Mesh *mesh, GLBTexture *tex, struct Armature *arm, int frame, float *mMat, float *vMat, float *pMat) { glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); mat4 t_matrix; mat4_identity(t_matrix); mat4_mult(mMat, t_matrix, t_matrix); mat4_mult(vMat, t_matrix, t_matrix); mat4_mult(pMat, t_matrix, t_matrix); mat4 *bmat = alloca(sizeof(mat4) * arm->nbones); armature_matrices(arm, frame, bmat); static bool TRUE = 1; glbProgramTexture(glbdrawmodel, GLB_FRAGMENT_SHADER, 0, tex); glbProgramUniform(glbdrawmodel, GLB_VERTEX_SHADER, 0, sizeof(bool), &TRUE); glbProgramUniformMatrix(glbdrawmodel, GLB_VERTEX_SHADER, 1, sizeof(float[16]), true, t_matrix); glbProgramUniformMatrix(glbdrawmodel, GLB_VERTEX_SHADER, 2, sizeof(float[16]) * arm->nbones, true, bmat); glbProgramOutput(glbdrawmodel, glbframebuffer); glbProgramDrawIndexed(glbdrawmodel, mesh->vbuffer, mesh->ibuffer); }
/* draw3D {{{*/ void gl_drawbones(Armature *arm, int frame, float *mMat, float *vMat, float *pMat) { static Shader *drawbones; static GLuint tmatloc; static GLuint bone_enloc; static GLuint boneloc; static int once = 1; if(once) { drawbones = malloc(sizeof(Shader)); shader_init(drawbones, "clockwork/glsl/drawbones"); shader_add_attrib(drawbones, "position", 3, GL_FLOAT, false, 32, (void*) 0); shader_add_fragment_output(drawbones, "fragColor"); tmatloc = glGetUniformLocation(drawbones->program, "t_matrix"); bone_enloc = glGetUniformLocation(drawbones->program, "bones_enable"); boneloc = glGetUniformLocation(drawbones->program, "bones"); once = 0; } glDisable(GL_DEPTH_TEST); static GLuint bonetmp = 0; if(!bonetmp) { glGenBuffers(1, &bonetmp); } glBindBuffer(GL_ARRAY_BUFFER, bonetmp); glBufferData(GL_ARRAY_BUFFER, arm->nbones * 64, NULL, GL_STREAM_DRAW); struct Mesh_vert *bones = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); int i; for(i = 0; i < arm->nbones; i++) { //TODO: remove memcpy(&bones[i * 2].position, &arm->bones[i].head, sizeof(float[3])); memcpy(&bones[i * 2 + 1].position, &arm->bones[i].tail, sizeof(float[3])); } glUnmapBuffer(GL_ARRAY_BUFFER); mat4 t_matrix; mat4_identity(t_matrix); mat4_mult(mMat, t_matrix, t_matrix); mat4_mult(vMat, t_matrix, t_matrix); mat4_mult(pMat, t_matrix, t_matrix); gl_bindshader(drawbones); gl_bindshaderattributes(); //TODO: remove glUniformMatrix4fv(tmatloc, 1, true, t_matrix); glUniform1i(bone_enloc, true); mat4 *m = alloca(arm->nbones * sizeof(mat4)); armature_matrices(arm, frame, m); glUniformMatrix4fv(boneloc, arm->nbones, true, (float*)m); glDrawArrays(GL_LINES, 0, arm->nbones * 2); glBindBuffer(GL_ARRAY_BUFFER, 0); gl_unbindshader(); glEnable(GL_DEPTH_TEST); }
void MatrixMultiplyShear(mat4_t m, vec_t x, vec_t y) { mat4_t tmp, shear; mat4_copy(m, tmp); MatrixSetupShear(shear, x, y); mat4_mult(tmp, shear, m); }
void MatrixMultiplyZRotation(mat4_t m, vec_t degrees) { mat4_t tmp, rot; mat4_copy(m, tmp); MatrixSetupZRotation(rot, degrees); mat4_mult(tmp, rot, m); }
void GL_LoadProjectionMatrix(const mat4_t m) { if (mat4_compare(GLSTACK_PM, m)) { return; } mat4_copy(m, GLSTACK_PM); mat4_mult(GLSTACK_PM, GLSTACK_MVM, GLSTACK_MVPM); }
void GL_LoadModelViewMatrix(const mat4_t m) { if (mat4_compare(GLSTACK_MVM, m)) { return; } mat4_copy(m, GLSTACK_MVM); mat4_mult(GLSTACK_PM, GLSTACK_MVM, GLSTACK_MVPM); }
void frustum_set(frustum_t* frustum, const mat4f_t* proj, const mat4f_t* view) { mat4f_t clip; mat4_mult(&clip, proj, view); // right plane frustum->planes[0].x = clip.m41 - clip.m11; frustum->planes[0].y = clip.m42 - clip.m12; frustum->planes[0].z = clip.m43 - clip.m13; frustum->planes[0].w = clip.m44 - clip.m14; // left plane frustum->planes[1].x = clip.m41 + clip.m11; frustum->planes[1].y = clip.m42 + clip.m12; frustum->planes[1].z = clip.m43 + clip.m13; frustum->planes[1].w = clip.m44 + clip.m14; // top plane frustum->planes[2].x = clip.m41 - clip.m21; frustum->planes[2].y = clip.m42 - clip.m22; frustum->planes[2].z = clip.m43 - clip.m23; frustum->planes[2].w = clip.m44 - clip.m24; // bottom plane frustum->planes[3].x = clip.m41 + clip.m21; frustum->planes[3].y = clip.m42 + clip.m22; frustum->planes[3].z = clip.m43 + clip.m23; frustum->planes[3].w = clip.m44 + clip.m24; // far plane frustum->planes[4].x = clip.m41 - clip.m31; frustum->planes[4].y = clip.m42 - clip.m32; frustum->planes[4].z = clip.m43 - clip.m33; frustum->planes[4].w = clip.m44 - clip.m34; // near plane frustum->planes[5].x = clip.m41 + clip.m31; frustum->planes[5].y = clip.m42 + clip.m32; frustum->planes[5].z = clip.m43 + clip.m33; frustum->planes[5].w = clip.m44 + clip.m34; int i = 0; for (i = 0; i < 6; ++i) { plane_t* p = &frustum->planes[i]; float len = sqrt(p->x * p->x + p->y * p->y + p->z * p->z); p->x /= len; p->y /= len; p->z /= len; p->w /= len; } }
void MatrixMultiplyTranslation(mat4_t m, vec_t x, vec_t y, vec_t z) { #if 1 mat4_t tmp, trans; mat4_copy(m, tmp); mat4_reset_translate(trans, x, y, z); mat4_mult(tmp, trans, m); #else m[12] += m[0] * x + m[4] * y + m[8] * z; m[13] += m[1] * x + m[5] * y + m[9] * z; m[14] += m[2] * x + m[6] * y + m[10] * z; m[15] += m[3] * x + m[7] * y + m[11] * z; #endif }
void basic_test(void){ float ALIGN_16 a_rows[16] = { 1, 5, 0, 0, 2, 1, 3, 5, 6, 9, 0, 2, 5, 3, 8, 9 }; float ALIGN_16 b_rows[16] = { 4, 0, 2, 0, 1, 2, 7, 1, 0, 0, 2, 0, 1, 2, 0, 1 }; mat4_t a = mat4_from_rows(a_rows); mat4_t b = mat4_from_rows(b_rows); printf("Multiplying a:\n"); mat4_print(a); printf("With b:\n"); mat4_print(b); printf("Multiplication result:\n"); a = mat4_mult(a, b); mat4_print(a); vec4_t v = vec4_new(1, 2, 3, 1); a = mat4_translate(v); printf("translation matrix for [1, 2, 3]:\n"); mat4_print(a); printf("Translated vector:\n"); v = mat4_vec_mult(a, v); vec4_print(v); a = mat4_rotate(90, vec4_new(1, 0, 0, 0)); printf("Rotation matrix:\n"); mat4_print(a); v = mat4_vec_mult(a, vec4_new(0, 1, 0, 0)); printf("+Y vec rotated 90 deg about +X:\n"); vec4_print(v); }
void mat4_rotateY(mat4_t mat, float deg) { float matRot[16]; mat4_rotationY(matRot, deg); mat4_mult(mat, matRot); }
int main(int argc, char **argv){ /* vertices for a triangle */ /* Why does triangle[] = { vec4_new(...) } result in a segfault when returning * from _mm_load_ps? */ /* Just want a sort of 3D object, but not a closed object otherwise it's hard * to tell what's going on w/ flat shading */ vec4_t object[18]; //+Z face object[0] = vec4_new(-1, -1, 1, 1); object[1] = vec4_new(1, -1, 1, 1); object[2] = vec4_new(1, 1, 1, 1); object[3] = vec4_new(1, 1, 1, 1); object[4] = vec4_new(-1, 1, 1, 1); object[5] = vec4_new(-1, -1, 1, 1); //+X face object[6] = vec4_new(1, -1, 1, 1); object[7] = vec4_new(1, -1, -1, 1); object[8] = vec4_new(1, 1, -1, 1); object[9] = vec4_new(1, 1, -1, 1); object[10] = vec4_new(1, 1, 1, 1); object[11] = vec4_new(1, -1, 1, 1); //-X face object[12] = vec4_new(-1, -1, 1, 1); object[13] = vec4_new(-1, -1, -1, 1); object[14] = vec4_new(-1, 1, -1, 1); object[15] = vec4_new(-1, 1, -1, 1); object[16] = vec4_new(-1, 1, 1, 1); object[17] = vec4_new(-1, -1, 1, 1); if (SDL_Init(SDL_INIT_EVERYTHING) != 0){ fprintf(stderr, "SDL Init error: %s\n", SDL_GetError()); return 1; } SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); #ifdef DEBUG SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); #endif SDL_Window *win = SDL_CreateWindow("SSE GL Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIN_WIDTH, WIN_HEIGHT, SDL_WINDOW_OPENGL); SDL_GLContext context = SDL_GL_CreateContext(win); if (check_GL_error("Opened win + context")){ SDL_GL_DeleteContext(context); SDL_DestroyWindow(win); return 1; } glewExperimental = GL_TRUE; GLenum err = glewInit(); if (err != GLEW_OK){ fprintf(stderr, "GLEW init error %d\n", err); SDL_GL_DeleteContext(context); SDL_DestroyWindow(win); return 1; } check_GL_error("Post GLEW init"); #ifdef DEBUG glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); glDebugMessageCallbackARB(gl_debug_callback, NULL); glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); #endif glClearColor(0, 0, 0, 1); glClearDepth(1); glEnable(GL_DEPTH_TEST); //Model's vao and vbo GLuint model[2]; glGenVertexArrays(1, model); glBindVertexArray(model[0]); glGenBuffers(1, model + 1); glBindBuffer(GL_ARRAY_BUFFER, model[1]); glBufferData(GL_ARRAY_BUFFER, 4 * 6 * 3 * sizeof(GLfloat), object, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); if (check_GL_error("Setup buffers")){ return 1; } GLint vshader = make_shader(vert_shader_src, GL_VERTEX_SHADER); GLint fshader = make_shader(frag_shader_src, GL_FRAGMENT_SHADER); if (vshader == -1 || fshader == -1){ return 1; } GLint program = make_program(vshader, fshader); if (program == -1){ return 1; } glDeleteShader(vshader); glDeleteShader(fshader); mat4_t model_mat = mat4_mult(mat4_rotate(45, vec4_new(1, 1, 0, 0)), mat4_scale(2, 2, 2)); model_mat = mat4_mult(mat4_translate(vec4_new(0, 2, -5, 1)), model_mat); mat4_t view_mat = mat4_look_at(vec4_new(0, 0, 5, 0), vec4_new(0, 0, 0, 0), vec4_new(0, 1, 0, 0)); mat4_t proj_mat = mat4_perspective(75, ((float)WIN_WIDTH) / WIN_HEIGHT, 1, 100); glUseProgram(program); GLuint model_unif = glGetUniformLocation(program, "model"); GLuint view_unif = glGetUniformLocation(program, "view"); GLuint proj_unif = glGetUniformLocation(program, "proj"); glUniformMatrix4fv(model_unif, 1, GL_FALSE, (GLfloat*)&model_mat); glUniformMatrix4fv(view_unif, 1, GL_FALSE, (GLfloat*)&view_mat); glUniformMatrix4fv(proj_unif, 1, GL_FALSE, (GLfloat*)&proj_mat); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 18); SDL_GL_SwapWindow(win); check_GL_error("Post Draw"); SDL_Event e; int quit = 0; while (!quit){ while (SDL_PollEvent(&e)){ if (e.type == SDL_QUIT || e.type == SDL_KEYDOWN){ quit = 1; } } } glDeleteProgram(program); glDeleteVertexArrays(1, model); glDeleteBuffers(1, model + 1); SDL_GL_DeleteContext(context); SDL_DestroyWindow(win); return 0; }
int update() { if (get_active_screen() == NULL) { return 1; } timestamp_t current = {0}; timestamp_set(¤t); long dt = timestamp_diff(¤t, &timer); if (dt > 0) { timer = current; screen_update(dt); } long fps_dt = timestamp_diff(¤t, &fps_timer); LOGD("DT: %ld", fps_dt); if (fps_dt > 500) { fps = frames * 1000.0f / (float)fps_dt; fps_timer = current; frames = 0; LOGI("FPS: %.2f", fps); } else { ++frames; } char fps_str[32] = {0}; sprintf(fps_str, "FPS: %.2f", fps); const rect_t fps_rect = { 8.0f, 8.0f, 256.0f, 32.0f }; const rgba_t fps_color = { 1.0f, 0.0f, 0.0f, 0.8f }; mat4f_t transform = {0}; mat4_mult(&transform, &camera.proj, &camera.view); rect_t screen = { 0, 0, screen_size.x, screen_size.y }; rgba_t color = {0.7f, 0.7f, 0.0f, 1.0f }; gfx_set_target(gfx, "test_target", &screen); gfx_enable_depth_buffer(gfx, 1); gfx_clear(gfx); screen_render(gfx, &camera); gfx_set_shader(gfx, "text"); gfx_set_uniform_mat4f(gfx, "uMVP", 1, &transform); draw_text(fps_str, &fps_rect, 0.0f, 4.9f, &fps_color); gfx_flush(gfx); static int take_screenshot = 0; if (take_screenshot && frames == 0) { take_screenshot = 0; image_t* img = NULL; if (gfx_take_screenshot(gfx, &img) == 0) { image_save_to_png(img, "screenshot.png"); image_free(img); } } gfx_set_target(gfx, NULL, &screen); gfx_enable_depth_buffer(gfx, 0); gfx_clear(gfx); int32_t sampler = 0; rect_t uv = { 0, screen.height/buffer_size.y, screen.width/buffer_size.x, -screen.height/buffer_size.y }; gfx_set_shader(gfx, "postprocess"); gfx_set_uniform_mat4f(gfx, "uMVP", 1, &transform); gfx_set_uniform_1i(gfx, "uTex", 1, &sampler); gfx_set_texture(gfx, "test_texture", sampler); gfx_render_textured_rect(gfx, &screen, 1.0f, &uv); gfx_set_texture(gfx, NULL, sampler); gfx_flush(gfx); return 0; }
void cam_get_mvp(mat4 mvp, Camera *camera, mat4 model) { mat4_mult(mvp, model, camera->vp); }
void __cam_update_vp(Camera *camera) { mat4_mult(camera->vp, camera->v, camera->p); }