static void graphene_matrix_transpose_transform_vec4 (const graphene_matrix_t *m, const graphene_vec4_t *v, graphene_vec4_t *res) { float x, y, z, w; x = graphene_simd4f_get_x (graphene_simd4f_sum (graphene_simd4f_mul (m->value.x, v->value))); y = graphene_simd4f_get_x (graphene_simd4f_sum (graphene_simd4f_mul (m->value.y, v->value))); z = graphene_simd4f_get_x (graphene_simd4f_sum (graphene_simd4f_mul (m->value.z, v->value))); w = graphene_simd4f_get_x (graphene_simd4f_sum (graphene_simd4f_mul (m->value.w, v->value))); graphene_vec4_init (res, x, y, z, w); }
static void quaternion_vec4_to_from (mutest_spec_t *spec) { graphene_quaternion_t *q; graphene_vec4_t v, check; graphene_vec4_init (&v, 1.f, 2.f, 3.f, 4.f); q = graphene_quaternion_init_from_vec4 (graphene_quaternion_alloc (), &v); graphene_quaternion_to_vec4 (q, &check); mutest_expect ("roundtrip between init_from_vec4 and to_vec4 to yield the same vector", mutest_bool_value (graphene_vec4_near (&v, &check, 0.0001f)), mutest_to_be_true, NULL); graphene_quaternion_free (q); }
static void quaternion_operators_normalize (mutest_spec_t *spec) { graphene_quaternion_t q1, q2; graphene_vec4_t v1, v2; graphene_quaternion_init (&q1, 1.f, 2.f, 3.f, 4.f); graphene_quaternion_normalize (&q1, &q2); graphene_vec4_init (&v1, 1.f, 2.f, 3.f, 4.f); graphene_vec4_normalize (&v1, &v1); graphene_quaternion_to_vec4 (&q2, &v2); mutest_expect ("normalizing a quaternion is the same as normalizing the equivalent vec4", mutest_bool_value (graphene_vec4_near (&v1, &v2, 0.00001f)), mutest_to_be_true, NULL); }
static void gthree_basic_material_real_set_uniforms (GthreeMaterial *material, GthreeUniforms *uniforms, GthreeCamera *camera) { GthreeBasicMaterial *basic = GTHREE_BASIC_MATERIAL (material); GthreeBasicMaterialPrivate *priv = gthree_basic_material_get_instance_private (basic); GthreeTexture *scale_map; GthreeUniform *uni; GTHREE_MATERIAL_CLASS (gthree_basic_material_parent_class)->set_uniforms (material, uniforms, camera); uni = gthree_uniforms_lookup_from_string (uniforms, "diffuse"); if (uni != NULL) gthree_uniform_set_color (uni, &priv->color); uni = gthree_uniforms_lookup_from_string (uniforms, "map"); if (uni != NULL) gthree_uniform_set_texture (uni, priv->map); /* uv repeat and offset setting priorities * 1. color map * 2. specular map * 3. normal map * 4. bump map * 5. alpha map */ scale_map = NULL; if (priv->map != NULL) scale_map = priv->map; // ... other maps if (scale_map != NULL) { const graphene_vec2_t *repeat = gthree_texture_get_repeat (scale_map); const graphene_vec2_t *offset = gthree_texture_get_offset (scale_map); graphene_vec4_t offset_repeat; graphene_vec4_init (&offset_repeat, graphene_vec2_get_x (offset), graphene_vec2_get_y (offset), graphene_vec2_get_x (repeat), graphene_vec2_get_y (repeat)); uni = gthree_uniforms_lookup_from_string (uniforms, "offsetRepeat"); if (uni != NULL) gthree_uniform_set_vec4 (uni, &offset_repeat); } uni = gthree_uniforms_lookup_from_string (uniforms, "envMap"); if (uni != NULL) gthree_uniform_set_texture (uni, priv->env_map); uni = gthree_uniforms_lookup_from_string (uniforms, "useRefract"); if (uni != NULL) gthree_uniform_set_int (uni, priv->env_map && gthree_texture_get_mapping (priv->env_map) == GTHREE_MAPPING_CUBE_REFRACTION); uni = gthree_uniforms_lookup_from_string (uniforms, "flipEnvMap"); if (uni != NULL) gthree_uniform_set_float (uni, (TRUE /* TODO: material.envMap instanceof THREE.WebGLRenderTargetCube */) ? 1 : -1); uni = gthree_uniforms_lookup_from_string (uniforms, "combine"); if (uni != NULL) gthree_uniform_set_int (uni, priv->combine); uni = gthree_uniforms_lookup_from_string (uniforms, "refractionRatio"); if (uni != NULL) gthree_uniform_set_float (uni, priv->refraction_ratio); // TODO: More from refreshUniformsCommon }
static gboolean matrix_decompose_3d (const graphene_matrix_t *m, graphene_point3d_t *scale_r, float shear_r[3], graphene_quaternion_t *rotate_r, graphene_point3d_t *translate_r, graphene_vec4_t *perspective_r) { graphene_matrix_t local, perspective; float shear_xy, shear_xz, shear_yz; float scale_x, scale_y, scale_z; graphene_simd4f_t dot, cross; if (graphene_matrix_get_value (m, 3, 3) == 0.f) return FALSE; local = *m; /* normalize the matrix */ graphene_matrix_normalize (&local, &local); /* perspective is used to solve for the perspective component, * but it also provides an easy way to test for singularity of * the upper 3x3 component */ perspective = local; perspective.value.w = graphene_simd4f_init (0.f, 0.f, 0.f, 1.f); if (graphene_matrix_determinant (&perspective) == 0.f) return FALSE; /* isolate the perspective */ if (graphene_simd4f_is_zero3 (local.value.w)) { graphene_matrix_t tmp; /* perspective_r is the right hand side of the equation */ perspective_r->value = local.value.w; /* solve the equation by inverting perspective and multiplying * the inverse with the perspective vector */ graphene_matrix_inverse (&perspective, &tmp); graphene_matrix_transpose_transform_vec4 (&tmp, perspective_r, perspective_r); /* clear the perspective partition */ local.value.w = graphene_simd4f_init (0.f, 0.f, 0.f, 1.f); } else graphene_vec4_init (perspective_r, 0.f, 0.f, 0.f, 1.f); /* next, take care of the translation partition */ translate_r->x = graphene_simd4f_get_x (local.value.w); translate_r->y = graphene_simd4f_get_y (local.value.w); translate_r->z = graphene_simd4f_get_z (local.value.w); local.value.w = graphene_simd4f_init (0.f, 0.f, 0.f, graphene_simd4f_get_w (local.value.w)); /* now get scale and shear */ /* compute the X scale factor and normalize the first row */ scale_x = graphene_simd4f_get_x (graphene_simd4f_length4 (local.value.x)); local.value.x = graphene_simd4f_div (local.value.x, graphene_simd4f_splat (scale_x)); /* compute XY shear factor and the second row orthogonal to the first */ shear_xy = graphene_simd4f_get_x (graphene_simd4f_dot4 (local.value.x, local.value.y)); local.value.y = graphene_simd4f_sub (local.value.y, graphene_simd4f_mul (local.value.x, graphene_simd4f_splat (shear_xy))); /* now, compute the Y scale factor and normalize the second row */ scale_y = graphene_simd4f_get_x (graphene_simd4f_length4 (local.value.y)); local.value.y = graphene_simd4f_div (local.value.y, graphene_simd4f_splat (scale_y)); shear_xy /= scale_y; /* compute XZ and YZ shears, make the third row orthogonal */ shear_xz = graphene_simd4f_get_x (graphene_simd4f_dot4 (local.value.x, local.value.z)); local.value.z = graphene_simd4f_sub (local.value.z, graphene_simd4f_mul (local.value.x, graphene_simd4f_splat (shear_xz))); shear_yz = graphene_simd4f_get_x (graphene_simd4f_dot4 (local.value.y, local.value.z)); local.value.z = graphene_simd4f_sub (local.value.z, graphene_simd4f_mul (local.value.y, graphene_simd4f_splat (shear_yz))); /* next, get the Z scale and normalize the third row */ scale_z = graphene_simd4f_get_x (graphene_simd4f_length4 (local.value.z)); local.value.z = graphene_simd4f_div (local.value.z, graphene_simd4f_splat (scale_z)); shear_xz /= scale_z; shear_yz /= scale_z; shear_r[XY_SHEAR] = shear_xy; shear_r[XZ_SHEAR] = shear_xz; shear_r[YZ_SHEAR] = shear_yz; /* at this point, the matrix is orthonormal. we check for a * coordinate system flip. if the determinant is -1, then * negate the matrix and the scaling factors */ dot = graphene_simd4f_cross3 (local.value.y, local.value.z); cross = graphene_simd4f_dot4 (local.value.x, dot); if (graphene_simd4f_get_x (cross) < 0.f) { scale_x *= -1.f; scale_y *= -1.f; scale_z *= -1.f; graphene_simd4f_mul (local.value.x, graphene_simd4f_splat (-1.f)); graphene_simd4f_mul (local.value.y, graphene_simd4f_splat (-1.f)); graphene_simd4f_mul (local.value.z, graphene_simd4f_splat (-1.f)); } graphene_point3d_init (scale_r, scale_x, scale_y, scale_z); /* get the rotations out */ graphene_quaternion_init_from_matrix (rotate_r, &local); return TRUE; }
/** * graphene_matrix_interpolate: * @a: ... * @b: ... * @factor: ... * @res: (out caller-allocates): ... * * ... * * Since: 1.0 */ void graphene_matrix_interpolate (const graphene_matrix_t *a, const graphene_matrix_t *b, double factor, graphene_matrix_t *res) { graphene_point3d_t scale_a = { 1.f, 1.f, 1.f }, translate_a; graphene_vec4_t perspective_a; graphene_quaternion_t rotate_a; float shear_a[3] = { 0.f, 0.f, 0.f }; graphene_point3d_t scale_b = { 1.f, 1.f, 1.f }, translate_b; graphene_vec4_t perspective_b; graphene_quaternion_t rotate_b; float shear_b[3] = { 0.f, 0.f, 0.f }; graphene_point3d_t scale_r = { 1.f, 1.f, 1.f }, translate_r; graphene_quaternion_t rotate_r; graphene_matrix_t tmp; float shear; g_return_if_fail (a != NULL && b != NULL); g_return_if_fail (res != NULL); if (graphene_matrix_is_2d (a) && graphene_matrix_is_2d (b)) { graphene_vec4_init (&perspective_a, 0.f, 0.f, 0.f, 1.f); graphene_vec4_init (&perspective_b, 0.f, 0.f, 0.f, 1.f); matrix_decompose_2d (a, &scale_a, shear_a, &rotate_a, &translate_a); matrix_decompose_2d (b, &scale_b, shear_b, &rotate_b, &translate_b); } else { matrix_decompose_3d (a, &scale_a, shear_a, &rotate_a, &translate_a, &perspective_a); matrix_decompose_3d (b, &scale_b, shear_b, &rotate_b, &translate_b, &perspective_b); } res->value.w = graphene_simd4f_interpolate (perspective_a.value, perspective_b.value, factor); graphene_point3d_interpolate (&translate_a, &translate_b, factor, &translate_r); graphene_matrix_translate (res, &translate_r); graphene_quaternion_slerp (&rotate_a, &rotate_b, factor, &rotate_r); graphene_quaternion_to_matrix (&rotate_r, &tmp); if (!graphene_matrix_is_identity (&tmp)) graphene_matrix_multiply (&tmp, res, res); shear = shear_a[YZ_SHEAR] + (shear_b[YZ_SHEAR] - shear_a[YZ_SHEAR]) * factor; if (shear != 0.f) graphene_matrix_skew_yz (res, shear); shear = shear_a[XZ_SHEAR] + (shear_b[XZ_SHEAR] - shear_a[XZ_SHEAR]) * factor; if (shear != 0.f) graphene_matrix_skew_xz (res, shear); shear = shear_a[XY_SHEAR] + (shear_b[XY_SHEAR] - shear_a[XY_SHEAR]) * factor; if (shear != 0.f) graphene_matrix_skew_xy (res, shear); graphene_point3d_interpolate (&scale_a, &scale_b, factor, &scale_r); if (scale_r.x != 1.f && scale_r.y != 1.f && scale_r.z != 0.f) graphene_matrix_scale (res, scale_r.x, scale_r.y, scale_r.z); }