CoglBool cogl_matrix_stack_get_inverse (CoglMatrixStack *stack, CoglMatrix *inverse) { CoglMatrix matrix; CoglMatrix *internal = cogl_matrix_stack_get (stack, &matrix); if (internal) return cogl_matrix_get_inverse (internal, inverse); else return cogl_matrix_get_inverse (&matrix, inverse); }
void rig_camera_update_view (RigEngine *engine, RutEntity *camera, CoglBool shadow_pass) { RutCamera *camera_component = rut_entity_get_component (camera, RUT_COMPONENT_TYPE_CAMERA); CoglMatrix transform; CoglMatrix inverse_transform; CoglMatrix view; /* translate to z_2d and scale */ if (!shadow_pass) view = engine->main_view; else view = engine->identity; /* apply the camera viewing transform */ rut_graphable_get_transform (camera, &transform); cogl_matrix_get_inverse (&transform, &inverse_transform); cogl_matrix_multiply (&view, &view, &inverse_transform); if (shadow_pass) { CoglMatrix flipped_view; cogl_matrix_init_identity (&flipped_view); cogl_matrix_scale (&flipped_view, 1, -1, 1); cogl_matrix_multiply (&flipped_view, &flipped_view, &view); rut_camera_set_view_transform (camera_component, &flipped_view); } else rut_camera_set_view_transform (camera_component, &view); }
static void get_light_modelviewprojection (const CoglMatrix *model_transform, RutEntity *light, const CoglMatrix *light_projection, CoglMatrix *light_mvp) { const CoglMatrix *light_transform; CoglMatrix light_view; /* TODO: cache the bias * light_projection * light_view matrix! */ /* Move the unit engine from [-1,1] to [0,1], column major order */ float bias[16] = { .5f, .0f, .0f, .0f, .0f, .5f, .0f, .0f, .0f, .0f, .5f, .0f, .5f, .5f, .5f, 1.f }; light_transform = rut_entity_get_transform (light); cogl_matrix_get_inverse (light_transform, &light_view); cogl_matrix_init_from_array (light_mvp, bias); cogl_matrix_multiply (light_mvp, light_mvp, light_projection); cogl_matrix_multiply (light_mvp, light_mvp, &light_view); cogl_matrix_multiply (light_mvp, light_mvp, model_transform); }
gboolean _cogl_matrix_stack_get_inverse (CoglMatrixStack *stack, CoglMatrix *inverse) { CoglMatrixState *state; state = _cogl_matrix_stack_top_mutable (stack, TRUE); return cogl_matrix_get_inverse (&state->matrix, inverse); }
const CoglMatrix * rut_camera_get_inverse_view_transform (RutCamera *camera) { if (camera->inverse_view_age == camera->view_age) return &camera->inverse_view; if (!cogl_matrix_get_inverse (&camera->view, &camera->inverse_view)) return NULL; camera->inverse_view_age = camera->view_age; return &camera->inverse_view; }
const CoglMatrix * rut_camera_get_inverse_projection (RutCamera *camera) { const CoglMatrix *projection; if (camera->inverse_projection_age == camera->projection_age) return &camera->inverse_projection; projection = rut_camera_get_projection (camera); if (!cogl_matrix_get_inverse (projection, &camera->inverse_projection)) return NULL; camera->inverse_projection_age = camera->projection_age; return &camera->inverse_projection; }
static RutInputEventStatus _rut_button_input_cb (RutInputRegion *region, RutInputEvent *event, void *user_data) { RutButton *button = user_data; if(rut_input_event_get_type (event) == RUT_INPUT_EVENT_TYPE_MOTION && rut_motion_event_get_action (event) == RUT_MOTION_EVENT_ACTION_DOWN) { RutShell *shell = button->ctx->shell; ButtonGrabState *state = g_slice_new (ButtonGrabState); const CoglMatrix *view; state->button = button; state->camera = rut_input_event_get_camera (event); view = rut_camera_get_view_transform (state->camera); state->transform = *view; rut_graphable_apply_transform (button, &state->transform); if (!cogl_matrix_get_inverse (&state->transform, &state->inverse_transform)) { g_warning ("Failed to calculate inverse of button transform\n"); g_slice_free (ButtonGrabState, state); return RUT_INPUT_EVENT_STATUS_UNHANDLED; } rut_shell_grab_input (shell, state->camera, _rut_button_grab_input_cb, state); //button->grab_x = rut_motion_event_get_x (event); //button->grab_y = rut_motion_event_get_y (event); button->state = BUTTON_STATE_ACTIVE; rut_shell_queue_redraw (button->ctx->shell); return RUT_INPUT_EVENT_STATUS_HANDLED; } return RUT_INPUT_EVENT_STATUS_UNHANDLED; }
/** * mash_light_set_direction_uniform: * @light: The #MashLight which is generating the shader * @uniform_location: The location of the uniform * @direction_in: The untransformed direction uniform * * This is a convenience intended to be used within * mash_light_update_uniforms() to help set uniforms. It * should not generally need to be called by an application unless it * is implementing its own lighting algorithms. * * This is intended to help when setting a direction * uniform. @direction_in should be an untransformed array of 3 floats * representing a vector. The vector will be transformed into eye * space according to the inverse transposed matrix of @light so that * it won't change direction for non-uniform scaling transformations. */ void mash_light_set_direction_uniform (MashLight *light, CoglHandle program, int uniform_location, const float *direction_in) { float light_direction[4]; CoglMatrix matrix, inverse_matrix; float magnitude; memcpy (light_direction, direction_in, sizeof (light_direction)); mash_light_get_modelview_matrix (light, &matrix); /* To safely transform the direction when the matrix might not be orthogonal we need the transposed inverse matrix */ cogl_matrix_get_inverse (&matrix, &inverse_matrix); transpose_matrix (&inverse_matrix, &matrix); cogl_matrix_transform_point (&matrix, light_direction + 0, light_direction + 1, light_direction + 2, light_direction + 3); /* Normalize the light direction */ magnitude = sqrtf ((light_direction[0] * light_direction[0]) + (light_direction[1] * light_direction[1]) + (light_direction[2] * light_direction[2])); light_direction[0] /= magnitude; light_direction[1] /= magnitude; light_direction[2] /= magnitude; cogl_program_set_uniform_float (program, uniform_location, 3, 1, light_direction); }
static void get_normal_matrix (const CoglMatrix *matrix, float *normal_matrix) { CoglMatrix inverse_matrix; /* Invert the matrix */ cogl_matrix_get_inverse (matrix, &inverse_matrix); /* Transpose it while converting it to 3x3 */ normal_matrix[0] = inverse_matrix.xx; normal_matrix[1] = inverse_matrix.xy; normal_matrix[2] = inverse_matrix.xz; normal_matrix[3] = inverse_matrix.yx; normal_matrix[4] = inverse_matrix.yy; normal_matrix[5] = inverse_matrix.yz; normal_matrix[6] = inverse_matrix.zx; normal_matrix[7] = inverse_matrix.zy; normal_matrix[8] = inverse_matrix.zz; }
bool map_window_coords_to_overlay_coord (RutCamera *camera, /* 2d ui camera */ RutObject *overlay, /* camera-view overlay */ float *x, float *y) { CoglMatrix transform; CoglMatrix inverse_transform; rut_graphable_get_modelview (overlay, camera, &transform); if (!cogl_matrix_get_inverse (&transform, &inverse_transform)) return FALSE; rut_camera_unproject_coord (camera, &transform, &inverse_transform, 0, /* object_coord_z */ x, y); return TRUE; }
/*< private > * clutter_util_matrix_decompose: * @src: the matrix to decompose * @scale_p: (out caller-allocates): return location for a vertex containing * the scaling factors * @shear_p: (out) (array length=3): return location for an array of 3 * elements containing the skew factors (XY, XZ, and YZ respectively) * @rotate_p: (out caller-allocates): return location for a vertex containing * the Euler angles * @translate_p: (out caller-allocates): return location for a vertex * containing the translation vector * @perspective_p: (out caller-allocates: return location for a 4D vertex * containing the perspective * * Decomposes a #ClutterMatrix into the transformations that compose it. * * This code is based on the matrix decomposition algorithm as published in * the CSS Transforms specification by the W3C CSS working group, available * at http://www.w3.org/TR/css3-transforms/. * * The algorithm, in turn, is based on the "unmatrix" method published in * "Graphics Gems II, edited by Jim Arvo", which is available at: * http://tog.acm.org/resources/GraphicsGems/gemsii/unmatrix.c * * Return value: %TRUE if the decomposition was successful, and %FALSE * if the matrix is singular */ gboolean _clutter_util_matrix_decompose (const ClutterMatrix *src, ClutterVertex *scale_p, float shear_p[3], ClutterVertex *rotate_p, ClutterVertex *translate_p, ClutterVertex4 *perspective_p) { CoglMatrix matrix = *src; CoglMatrix perspective; ClutterVertex4 vertex_tmp; ClutterVertex row[3], pdum; int i, j; #define XY_SHEAR 0 #define XZ_SHEAR 1 #define YZ_SHEAR 2 #define MAT(m,r,c) ((float *)(m))[(c) * 4 + (r)] /* normalize the matrix */ if (matrix.ww == 0.f) return FALSE; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { MAT (&matrix, j, i) /= MAT (&matrix, 3, 3); } } /* perspective is used to solve for perspective, but it also provides * an easy way to test for singularity of the upper 3x3 component */ perspective = matrix; /* transpose */ MAT (&perspective, 3, 0) = 0.f; MAT (&perspective, 3, 1) = 0.f; MAT (&perspective, 3, 2) = 0.f; MAT (&perspective, 3, 3) = 1.f; if (_clutter_util_matrix_determinant (&perspective) == 0.f) return FALSE; if (MAT (&matrix, 3, 0) != 0.f || MAT (&matrix, 3, 1) != 0.f || MAT (&matrix, 3, 2) != 0.f) { CoglMatrix perspective_inv; ClutterVertex4 p; vertex_tmp.x = MAT (&matrix, 3, 0); vertex_tmp.y = MAT (&matrix, 3, 1); vertex_tmp.z = MAT (&matrix, 3, 2); vertex_tmp.w = MAT (&matrix, 3, 3); /* solve the equation by inverting perspective... */ cogl_matrix_get_inverse (&perspective, &perspective_inv); /* ... and multiplying vertex_tmp by the inverse */ _clutter_util_matrix_transpose_vector4_transform (&perspective_inv, &vertex_tmp, &p); *perspective_p = p; /* clear the perspective part */ MAT (&matrix, 3, 0) = 0.0f; MAT (&matrix, 3, 1) = 0.0f; MAT (&matrix, 3, 2) = 0.0f; MAT (&matrix, 3, 3) = 1.0f; } else { /* no perspective */ perspective_p->x = 0.0f; perspective_p->y = 0.0f; perspective_p->z = 0.0f; perspective_p->w = 1.0f; } /* translation */ translate_p->x = MAT (&matrix, 0, 3); MAT (&matrix, 0, 3) = 0.f; translate_p->y = MAT (&matrix, 1, 3); MAT (&matrix, 1, 3) = 0.f; translate_p->z = MAT (&matrix, 2, 3); MAT (&matrix, 2, 3) = 0.f; /* scale and shear; we split the upper 3x3 matrix into rows */ for (i = 0; i < 3; i++) { row[i].x = MAT (&matrix, i, 0); row[i].y = MAT (&matrix, i, 1); row[i].z = MAT (&matrix, i, 2); } /* compute scale.x and normalize the first row */ scale_p->x = _clutter_util_vertex_length (&row[0]); _clutter_util_vertex_normalize (&row[0]); /* compute XY shear and make the second row orthogonal to the first */ shear_p[XY_SHEAR] = _clutter_util_vertex_dot (&row[0], &row[1]); _clutter_util_vertex_combine (&row[1], &row[0], 1.0, -shear_p[XY_SHEAR], &row[1]); /* compute the Y scale and normalize the second row */ scale_p->y = _clutter_util_vertex_length (&row[1]); _clutter_util_vertex_normalize (&row[1]); shear_p[XY_SHEAR] /= scale_p->y; /* compute XZ and YZ shears, orthogonalize the third row */ shear_p[XZ_SHEAR] = _clutter_util_vertex_dot (&row[0], &row[2]); _clutter_util_vertex_combine (&row[2], &row[0], 1.0, -shear_p[XZ_SHEAR], &row[2]); shear_p[YZ_SHEAR] = _clutter_util_vertex_dot (&row[1], &row[2]); _clutter_util_vertex_combine (&row[2], &row[1], 1.0, -shear_p[YZ_SHEAR], &row[2]); /* get the Z scale and normalize the third row*/ scale_p->z = _clutter_util_vertex_length (&row[2]); _clutter_util_vertex_normalize (&row[2]); shear_p[XZ_SHEAR] /= scale_p->z; shear_p[YZ_SHEAR] /= scale_p->z; /* at this point, the matrix (inside row[]) is orthonormal. * check for a coordinate system flip; if the determinant * is -1, then negate the matrix and scaling factors */ _clutter_util_vertex_cross (&row[1], &row[2], &pdum); if (_clutter_util_vertex_dot (&row[0], &pdum) < 0.f) { scale_p->x *= -1.f; for (i = 0; i < 3; i++) { row[i].x *= -1.f; row[i].y *= -1.f; row[i].z *= -1.f; } } /* now get the rotations out */ rotate_p->y = asinf (-row[0].z); if (cosf (rotate_p->y) != 0.f) { rotate_p->x = atan2f (row[1].z, row[2].z); rotate_p->z = atan2f (row[0].y, row[0].x); } else { rotate_p->x = atan2f (-row[2].x, row[1].y); rotate_p->z = 0.f; } #undef XY_SHEAR #undef XZ_SHEAR #undef YZ_SHEAR #undef MAT return TRUE; }