Exemple #1
0
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(&center, &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);
}
Exemple #2
0
void gear_draw(gear_t* self, a3d_mat4f_t* mvp, a3d_mat4f_t* mvm)
{
	assert(self);
	LOGD("debug");

	a3d_mat3f_t nm;
	a3d_mat4f_normalmatrix(mvm, &nm);

	a3d_vec3f_t light_position;
	a3d_vec3f_load(&light_position, 5.0f, 5.0f, 10.0);
	a3d_vec3f_normalize(&light_position);   // TODO - optimize

	// front, back, front teeth and back teeth
	glUseProgram(self->face_program);
	glEnableVertexAttribArray(self->face_attribute_vertex);

	// compute color for flat shaded surface
	a3d_vec3f_t normal_front;
	a3d_vec4f_t color;
	a3d_vec3f_load(&normal_front, 0.0f, 0.0f, 1.0f);
	a3d_mat3f_mulv(&nm, &normal_front);
	a3d_vec3f_normalize(&normal_front);
	a3d_vec4f_load(&color, 0.2f, 0.2f, 0.2f, 1.0f);   // ambient
	GLfloat ndotlp = a3d_vec3f_dot(&normal_front, &light_position);
	if(ndotlp > 0.0f)
	{
		a3d_vec4f_t diffuse;
		a3d_vec4f_load(&diffuse, ndotlp, ndotlp, ndotlp, 0.0f);
		a3d_vec4f_addv(&color, &diffuse);       // ambient + diffuse
		a3d_vec4f_mulv(&color, &self->color);   // color * (ambient + diffuse)
	}
	else
	{
		a3d_vec4f_mulv(&color, &self->color);
	}

	glUniform4fv(self->face_uniform_color, 1, (GLfloat*) &color);
	glUniformMatrix4fv(self->face_uniform_mvp, 1, GL_FALSE, (GLfloat*) mvp);
	glBindBuffer(GL_ARRAY_BUFFER, self->front_vid);
	glVertexAttribPointer(self->face_attribute_vertex, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, self->front_ec);

	glBindBuffer(GL_ARRAY_BUFFER, self->front_teeth_vid);
	glVertexAttribPointer(self->face_attribute_vertex, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glDrawArrays(GL_TRIANGLES, 0, self->front_teeth_ec);

	// compute color for flat shaded surface
	a3d_vec3f_t normal_back;
	a3d_vec3f_load(&normal_back, 0.0f, 0.0f, -1.0f);
	a3d_mat3f_mulv(&nm, &normal_back);
	a3d_vec3f_normalize(&normal_back);
	a3d_vec4f_load(&color, 0.2f, 0.2f, 0.2f, 1.0f);   // reload ambient
	ndotlp = a3d_vec3f_dot(&normal_back, &light_position);
	if(ndotlp > 0.0f)
	{
		a3d_vec4f_t diffuse;
		a3d_vec4f_load(&diffuse, ndotlp, ndotlp, ndotlp, 0.0f);
		a3d_vec4f_addv(&color, &diffuse);       // ambient + diffuse
		a3d_vec4f_mulv(&color, &self->color);   // color * (ambient + diffuse)
	}
	else
	{
		a3d_vec4f_mulv(&color, &self->color);
	}

	glUniform4fv(self->face_uniform_color, 1, (GLfloat*) &color);
	glBindBuffer(GL_ARRAY_BUFFER, self->back_vid);
	glVertexAttribPointer(self->face_attribute_vertex, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, self->back_ec);

	glBindBuffer(GL_ARRAY_BUFFER, self->back_teeth_vid);
	glVertexAttribPointer(self->face_attribute_vertex, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glDrawArrays(GL_TRIANGLES, 0, self->back_teeth_ec);

	glDisableVertexAttribArray(self->face_attribute_vertex);

	// outward teeth
	glUseProgram(self->outward_program);
	glEnableVertexAttribArray(self->outward_attribute_vertex);
	glEnableVertexAttribArray(self->outward_attribute_normal);

	glUniform4fv(self->outward_uniform_color, 1, (GLfloat*) &self->color);
	glUniformMatrix3fv(self->outward_uniform_nm, 1, GL_FALSE, (GLfloat*) &nm);
	glUniformMatrix4fv(self->outward_uniform_mvp, 1, GL_FALSE, (GLfloat*) mvp);
	glBindBuffer(GL_ARRAY_BUFFER, self->outward_vid);
	glVertexAttribPointer(self->outward_attribute_vertex, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glBindBuffer(GL_ARRAY_BUFFER, self->outward_nid);
	glVertexAttribPointer(self->outward_attribute_normal, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, self->outward_ec);

	glDisableVertexAttribArray(self->outward_attribute_normal);
	glDisableVertexAttribArray(self->outward_attribute_vertex);

	// cylinder
	glUseProgram(self->cylinder_program);
	glEnableVertexAttribArray(self->cylinder_attribute_vertex);
	glEnableVertexAttribArray(self->cylinder_attribute_normal);

	glUniform4fv(self->cylinder_uniform_color, 1, (GLfloat*) &self->color);
	glUniformMatrix3fv(self->cylinder_uniform_nm, 1, GL_FALSE, (GLfloat*) &nm);
	glUniformMatrix4fv(self->cylinder_uniform_mvp, 1, GL_FALSE, (GLfloat*) mvp);
	glBindBuffer(GL_ARRAY_BUFFER, self->cylinder_vid);
	glVertexAttribPointer(self->cylinder_attribute_vertex, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glBindBuffer(GL_ARRAY_BUFFER, self->cylinder_nid);
	glVertexAttribPointer(self->cylinder_attribute_normal, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, self->cylinder_ec);

	glDisableVertexAttribArray(self->cylinder_attribute_normal);
	glDisableVertexAttribArray(self->cylinder_attribute_vertex);
	glUseProgram(0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
}