static void a3d_sprite_draw(a3d_widget_t* widget) { assert(widget); LOGD("debug"); a3d_sprite_t* self = (a3d_sprite_t*) widget; a3d_screen_t* screen = widget->screen; a3d_mat4f_t mvp; // draw sprite a3d_vec4f_t* c = &self->color; float alpha = widget->fade*c->a; if(alpha > 0.0f) { float w = 0.0f; float h = 0.0f; float x = widget->rect_draw.l; float y = widget->rect_draw.t; float ww = widget->rect_draw.w; float hh = widget->rect_draw.h; a3d_screen_sizef(screen, &w, &h); a3d_mat4f_ortho(&mvp, 1, 0.0f, w, h, 0.0f, 0.0f, 2.0f); a3d_mat4f_translate(&mvp, 0, x + ww/2.0f, y + hh/2.0f, -1.0f); a3d_mat4f_scale(&mvp, 0, ww, hh, 1.0f); a3d_mat4f_rotate(&mvp, 0, self->theta, 0.0f, 0.0f, 1.0f); a3d_spriteShader_t* shader = a3d_screen_spriteShader(screen); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glUseProgram(shader->prog); glEnableVertexAttribArray(shader->attr_vertex); glEnableVertexAttribArray(shader->attr_coords); glBindTexture(GL_TEXTURE_2D, self->id_tex[self->index]); glBindBuffer(GL_ARRAY_BUFFER, self->id_vertex); glVertexAttribPointer(shader->attr_vertex, 4, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, self->id_coords); glVertexAttribPointer(shader->attr_coords, 2, GL_FLOAT, GL_FALSE, 0, 0); glUniform4f(shader->unif_color, c->r, c->g, c->b, alpha); glUniformMatrix4fv(shader->unif_mvp, 1, GL_FALSE, (GLfloat*) &mvp); glUniform1i(shader->unif_sampler, 0); glDrawArrays(GL_TRIANGLES, 0, 6); glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisableVertexAttribArray(shader->attr_coords); glDisableVertexAttribArray(shader->attr_vertex); glUseProgram(0); glDisable(GL_BLEND); } }
void a3d_mat4f_orthonormal_copy(const a3d_mat4f_t* self, a3d_mat4f_t* copy) { assert(self); assert(copy); LOGD("debug"); /* * perform modified Gram-Schmitt ortho-normalization */ a3d_vec4f_t v0 = { .x = self->m00, .y = self->m01, .z = self->m02, .w = self->m03 }; a3d_vec4f_t v1 = { .x = self->m10, .y = self->m11, .z = self->m12, .w = self->m13 }; a3d_vec4f_t v2 = { .x = self->m20, .y = self->m21, .z = self->m22, .w = self->m23 }; a3d_vec4f_t v3 = { .x = self->m30, .y = self->m31, .z = self->m32, .w = self->m33 }; // normalize u0 a3d_vec4f_t u0; a3d_vec4f_normalize_copy(&v0, &u0); // subtract the component of v1 in the direction of u0 // normalize u1 a3d_vec4f_t u1; a3d_vec4f_t projuv; a3d_mat4f_projuv(&u0, &v1, &projuv); a3d_vec4f_subv_copy(&v1, &projuv, &u1); a3d_vec4f_normalize(&u1); // subtract the component of v2 in the direction of u1 // subtract the component of u2 in the direction of u0 // normalize u2 a3d_vec4f_t u2; a3d_mat4f_projuv(&u1, &v2, &projuv); a3d_vec4f_subv_copy(&v2, &projuv, &u2); a3d_mat4f_projuv(&u0, &u2, &projuv); a3d_vec4f_subv(&u2, &projuv); a3d_vec4f_normalize(&u2); // subtract the component of v3 in the direction of u2 // subtract the component of u3 in the direction of u1 // subtract the component of u3 in the direction of u0 // normalize u3 a3d_vec4f_t u3; a3d_mat4f_projuv(&u2, &v3, &projuv); a3d_vec4f_subv_copy(&v3, &projuv, &u3); a3d_mat4f_projuv(&u1, &u3, &projuv); a3d_vec4f_subv(&u3, &projuv); a3d_mat4f_projuv(&u0, &u3, &projuv); a3d_vec4f_subv(&u3, &projuv); a3d_vec4f_normalize(&u3); // copy the orthonormal vectors copy->m00 = u0.x; copy->m01 = u0.y; copy->m02 = u0.z; copy->m03 = u0.w; copy->m10 = u1.x; copy->m11 = u1.y; copy->m12 = u1.z; copy->m13 = u1.w; copy->m20 = u2.x; copy->m21 = u2.y; copy->m22 = u2.z; copy->m23 = u2.w; copy->m30 = u3.x; copy->m31 = u3.y; copy->m32 = u3.z; copy->m33 = u3.w; } /* * quaternion operations */ void a3d_mat4f_rotateq(a3d_mat4f_t* self, int load, const a3d_quaternion_t* q) { assert(self); assert(q); LOGD("debug load=%i", load); float x2 = q->v.x*q->v.x; float y2 = q->v.y*q->v.y; float z2 = q->v.z*q->v.z; float xy = q->v.x*q->v.y; float xz = q->v.x*q->v.z; float yz = q->v.y*q->v.z; float xw = q->v.x*q->s; float yw = q->v.y*q->s; float zw = q->v.z*q->s; // requires normalized quaternions a3d_mat4f_t m = { 1.0f - 2.0f*(y2 + z2), 2.0f*(xy - zw), 2.0f*(xz + yw), 0.0f, 2.0f*(xy + zw), 1.0f - 2.0f*(x2 + z2), 2.0f*(yz - xw), 0.0f, 2.0f*(xz - yw), 2.0f*(yz + xw), 1.0f - 2.0f*(x2 + y2), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; if(load) a3d_mat4f_copy(&m, self); else a3d_mat4f_mulm(self, &m); } /* * GL matrix operations */ void a3d_mat4f_lookat(a3d_mat4f_t* self, int load, GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx, GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy, GLfloat upz) { assert(self); LOGD("debug load=%i, eye=(%f,%f,%f), center=(%f,%f,%f), up=(%f,%f,%f)", load, eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz); a3d_vec3f_t eye = { eyex, eyey, eyez }; a3d_vec3f_t center = { centerx, centery, centerz }; a3d_vec3f_t up = { upx, upy, upz }; a3d_vec3f_t n; a3d_vec3f_subv_copy(¢er, &eye, &n); a3d_vec3f_normalize(&n); a3d_vec3f_normalize(&up); a3d_vec3f_t u; a3d_vec3f_t v; a3d_vec3f_cross_copy(&n, &up, &u); a3d_vec3f_cross_copy(&u, &n, &v); a3d_vec3f_normalize(&u); a3d_vec3f_normalize(&v); a3d_mat4f_t m = { u.x, v.x, -n.x, 0.0f, u.y, v.y, -n.y, 0.0f, u.z, v.z, -n.z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; a3d_mat4f_translate(&m, 0, -eye.x, -eye.y, -eye.z); if(load) a3d_mat4f_copy(&m, self); else a3d_mat4f_mulm(self, &m); } void a3d_mat4f_perspective(a3d_mat4f_t* self, int load, GLfloat fovy, GLfloat aspect, GLfloat znear, GLfloat zfar) { assert(self); LOGD("debug load=%i, fovy=%f, aspect=%f, znear=%f, zfar=%f", load, fovy, aspect, znear, zfar); GLfloat f = 1.0f/tanf(fovy*(M_PI/180.0f)/2.0f); GLfloat m00 = f/aspect; GLfloat m11 = f; GLfloat m22 = (zfar + znear)/(znear - zfar); GLfloat m23 = (2.0f*zfar*znear)/(znear - zfar); a3d_mat4f_t m = { m00, 0.0f, 0.0f, 0.0f, 0.0f, m11, 0.0f, 0.0f, 0.0f, 0.0f, m22, -1.0f, 0.0f, 0.0f, m23, 0.0f, }; if(load) a3d_mat4f_copy(&m, self); else a3d_mat4f_mulm(self, &m); } void a3d_mat4f_perspectiveStereo(a3d_mat4f_t* pmL, a3d_mat4f_t* pmR, int load, GLfloat fovy, GLfloat aspect, GLfloat znear, GLfloat zfar, GLfloat convergence, GLfloat eye_separation) { assert(pmL); assert(pmR); // http://www.animesh.me/2011/05/rendering-3d-anaglyph-in-opengl.html GLfloat tan_fovy2 = tanf(fovy*(M_PI/180.0f)/2.0f); GLfloat es2 = eye_separation/2.0f; GLfloat top = znear*tan_fovy2; GLfloat bottom = -top; GLfloat a = aspect*tan_fovy2*convergence; GLfloat b = a - es2; GLfloat c = a + es2; GLfloat d = znear/convergence; GLfloat left = -b*d; GLfloat right = c*d; // left perspective matrix a3d_mat4f_frustum(pmL, load, left, right, bottom, top, znear, zfar); // right perspective matrix left = -c*d; right = b*d; a3d_mat4f_frustum(pmR, load, left, right, bottom, top, znear, zfar); }