/* 0 - up left, 1 - up right, 2 - down right, 3 - down left */ int get_diagonal_index(mesh_t *mesh, int direction, int cur_y, int cur_x) { switch (direction) { case 0: return MESH_INDEX((cur_y - 1), (cur_x - 1)); case 1: return MESH_INDEX((cur_y - 1), (cur_x + 1)); case 2: return MESH_INDEX((cur_y + 1), (cur_x + 1)); case 3: return MESH_INDEX((cur_y + 1), (cur_x - 1)); } return 0; }
/* Corner update for the diffusion test problem */ void diff_update_corner_dirichlet(mesh_t *mesh, mesh_t *mesh_old, int cur_y, int cur_x, int boundary_side1, int boundary_side2) { int k; cell_t *cur_cell, *cur_cell_old, *adj_cell; double A, sum_A, sum_A_R, num, denom, phi_h_dt, xi; cur_cell = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; cur_cell_old = &mesh_old->cell[MESH_INDEX(cur_y, cur_x)]; sum_A = 0; sum_A_R = 0; xi = 2 * cur_cell->diffusion / mesh->dim.h; /* Updates saturation for the current cell on the new mesh */ for (k = 0; k < 4; k++) { if ((k != boundary_side1) && (k != boundary_side2)) { adj_cell = &mesh_old->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; sum_A += cur_cell_old->A_d[k]; sum_A_R += cur_cell_old->A_d[k] * adj_cell->robin[(k + 2) % 4]; } } phi_h_dt = (mesh->global.porosity * mesh->dim.h / mesh->dim.dt); num = cur_cell_old->source_d * mesh->dim.h + sum_A_R + phi_h_dt * cur_cell_old->saturation_prev; denom = phi_h_dt + sum_A + xi; cur_cell->saturation = num / denom; /* Updates flux for the current cell on the new mesh */ for (k = 0; k < 4; k++) { if ((k != boundary_side1) && (k != boundary_side2)) { adj_cell = &mesh_old->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; A = cur_cell->A_d[k]; cur_cell->flux_d[k] = A * (cur_cell->saturation - adj_cell->robin[(k + 2) % 4]); } } /* Updates the saturation at the edges of the current cell in the new mesh */ for (k = 0; k < 4; k ++) { if ((k != boundary_side1) && (k != boundary_side2)) { adj_cell = &mesh_old->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; cur_cell->l_d[k] = cur_cell->beta[k] * cur_cell->flux_d[k] + adj_cell->robin[(k + 2) % 4]; } } }
/* Finds the maxiumum time step for transport */ void mesh_max_time_step(mesh_t *mesh, mesh_t *mesh_old) { double max = 0, mult = 0, vel_norm = 0, global_max = 0; cell_t *cur_cell; for (int i = 0; i < mesh->dim.ydim; i++) { for (int j = 0; j < mesh->dim.xdim; j++) { cur_cell = &mesh_old->cell[MESH_INDEX(i, j)]; vel_norm = sqrt(pow(cur_cell->velocity_x, 2) + pow(cur_cell->velocity_y, 2)); mult = cur_cell->pm_w_deriv / mesh->global.porosity * vel_norm; if (mult > max) max = mult; } } MPI_Allreduce(&max, &global_max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); double time = (0.95 * mesh->dim.h / 2) / global_max; if (time > (mesh->dim.dt / 5.0)) { mesh->dim.dt_transport = mesh->dim.dt / 5.0; mesh_old->dim.dt_transport = mesh->dim.dt / 5.0; } else { mesh->dim.dt_transport = time; mesh_old->dim.dt_transport = time; } }
void setup_transport_test(mesh_t *mesh) { cell_t *cur_cell; cur_cell = &mesh->cell[MESH_INDEX((mesh->dim.ydim - 1), 0)]; cur_cell->saturation = 0.84; }
/* Computes robin conditions for the diffusion problem */ void diff_compute_robin(mesh_t *mesh, int cur_y, int cur_x) { cell_t *cur_cell = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; for (int k = 0; k < 4; k++) { cur_cell->robin[k] = cur_cell->beta[k] * cur_cell->flux_d[k] + cur_cell->l_d[k]; } }
void press_update_corner(mesh_t *mesh, mesh_t *mesh_old, int cur_y, int cur_x, int boundary_side1, int boundary_side2) { int k; cell_t *cur_cell, *cur_cell_old, *adj_cell; double sum_A, sum_A_R, A; cur_cell = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; cur_cell_old = &mesh_old->cell[MESH_INDEX(cur_y, cur_x)]; sum_A = 0; sum_A_R = 0; for (k = 0; k < 4; k++) { if ((k != boundary_side1) && (k != boundary_side2)) { adj_cell = &mesh_old->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; sum_A += cur_cell_old->A_p[k]; sum_A_R += cur_cell_old->A_p[k] * adj_cell->robin[(k + 2) % 4]; } } /* Updates the pressure at the current cell on the new mesh */ cur_cell->pressure = (cur_cell_old->source * mesh->dim.h + sum_A_R) / sum_A; /* Updates the flux at the current cell on the new mesh */ for (k = 0; k < 4; k++) { if ((k != boundary_side1) && (k != boundary_side2)) { adj_cell = &mesh_old->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; A = cur_cell->A_p[k]; cur_cell->flux_p[k] = A * (cur_cell->pressure - adj_cell->robin[(k + 2) % 4]); } } /* Updates the pressure at the edges of the current cell in the new mesh */ for (k = 0; k < 4; k ++) { if ((k != boundary_side1) && (k != boundary_side2)) { adj_cell = &mesh_old->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; cur_cell->l_p[k] = cur_cell->beta[k] * cur_cell->flux_p[k] + adj_cell->robin[(k + 2) % 4]; } } }
/* Computes A_alpha = xi/(1+beta_alpha*xi), xi = 2k/h */ void press_compute_A(mesh_t *mesh, int cur_y, int cur_x) { double xi; cell_t *cur_cell; cur_cell = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; xi = 2.0 * cur_cell->perm * total_mobility(cur_cell, &mesh->global)/ mesh->dim.h; // printf("lambda: %e\n", total_mobility(cur_cell, &mesh->global)); for (int k = 0; k < 4; k++) { cur_cell->A_p[k] = xi / (1.0 + cur_cell->beta[k] * xi); } }
/* Updates the saturation and flux for the diffusion problem on interior cells */ void diff_update_interior(mesh_t *mesh, mesh_t *mesh_old, int cur_y, int cur_x) { int k; cell_t *cur_cell, *cur_cell_old, *adj_cell; double A, sum_A, sum_A_R, num, denom, phi_h_dt; cur_cell = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; cur_cell_old = &mesh_old->cell[MESH_INDEX(cur_y, cur_x)]; sum_A = 0; sum_A_R = 0; /* Updates saturation for the current cell on the new mesh */ for (k = 0; k < 4; k++) { adj_cell = &mesh_old->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; sum_A += cur_cell_old->A_d[k]; sum_A_R += cur_cell_old->A_d[k] * adj_cell->robin[(k + 2) % 4]; } phi_h_dt = (mesh->global.porosity * mesh->dim.h / mesh->dim.dt); num = cur_cell_old->source_d * mesh->dim.h + sum_A_R + phi_h_dt * cur_cell_old->saturation_prev; denom = phi_h_dt + sum_A; cur_cell->saturation = num / denom; /* Updates flux for the current cell on the new mesh */ for (k = 0; k < 4; k++) { adj_cell = &mesh_old->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; A = cur_cell->A_d[k]; cur_cell->flux_d[k] = A * (cur_cell->saturation - adj_cell->robin[(k + 2) % 4]); } /* Updates the pressure at the edges of the current cell in the new mesh */ for (k = 0; k < 4; k ++) { adj_cell = &mesh_old->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; cur_cell->l_d[k] = cur_cell->beta[k] * cur_cell->flux_d[k] + adj_cell->robin[(k + 2) % 4]; } }
/* Computes the velocity information on the mesh */ void mesh_compute_velocity(mesh_t *mesh) { cell_t *cur_cell; for (int i = 0; i < mesh->dim.ydim; i++) { for (int j = 0; j < mesh->dim.xdim; j++) { cur_cell = &mesh->cell[MESH_INDEX(i, j)]; cur_cell->velocity_y = (cur_cell->flux_p[0] - cur_cell->flux_p[2]) / 2; cur_cell->velocity_x = (cur_cell->flux_p[1] - cur_cell->flux_p[3]) / 2; } } }
/* Records production well data */ void record_production_wells(production_wells_t *wells, mesh_t *mesh, int time_step) { cell_t *cur_cell; prod_well_t *cur_well; int y, x; for (int i = 0; i < wells->num_wells; i++) { cur_well = &wells->wells[i]; y = cur_well->y_pos; x = cur_well->x_pos; cur_cell = &mesh->cell[MESH_INDEX(y, x)]; cur_well->oil_sat_recording[time_step] = 1.0 - cur_cell->saturation; } }
/* Computes A_alpha = xi/(1+beta_alpha*xi), xi = - 2D/h */ void diff_compute_A(mesh_t *mesh, int cur_y, int cur_x) { double xi; cell_t *cur_cell; cur_cell = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; xi = 2.0 * cur_cell->diffusion / mesh->dim.h; for (int k = 0; k < 4; k++) { cur_cell->A_d[k] = xi / (cur_cell->beta[k] * xi - 1.0); // if ((cur_y == mesh->dim.ydim - 1) && (cur_x == 0)) // printf("A: %e\n", cur_cell->A_d[k]); } }
/* Initializes Production Wells */ production_wells_t init_production_wells(mesh_t *mesh) { cell_t *cur_cell; production_wells_t prod_wells; /* First sweep to determine number of production wells */ for (int i = 0; i < mesh->dim.ydim; i++) { for (int j = 0; j < mesh->dim.xdim; j++) { cur_cell = &mesh->cell[MESH_INDEX(i, j)]; if (cur_cell->source < 0) prod_wells.num_wells++; } } /* Allocates memory for array of wells */ prod_wells.wells = malloc(prod_wells.num_wells * sizeof(prod_well_t)); /* Allocates memory for oil saturation recordings within wells */ for (int i = 0; i < prod_wells.num_wells; i++) { prod_wells.wells[i].oil_sat_recording = malloc(mesh->dim.num_ts * sizeof(double)); } /* Records the x and y position for each well */ int well_count = 0; for (int i = 0; i < mesh->dim.ydim; i++) { for (int j = 0; j < mesh->dim.xdim; j++) { cur_cell = &mesh->cell[MESH_INDEX(i, j)]; if (cur_cell->source < 0) { prod_wells.wells[well_count].y_pos = i; prod_wells.wells[well_count].x_pos = j; prod_wells.wells[well_count].oil_sat_recording[0] = 1 - cur_cell->saturation; } } } return prod_wells; }
/* Direction = 0 for x, 1 for y */ double trans_get_old_position(mesh_t *mesh, int cur_y, int cur_x, int direction) { cell_t *cur_cell = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; double pos; pos = (-1.0) * cur_cell->pm_w_deriv * mesh->dim.dt_transport; pos /= mesh->global.porosity; if (direction == 0) return pos * cur_cell->velocity_x; else if (direction == 1) return pos * cur_cell->velocity_y; else return 0; }
/* Combutes beta at the current cell for diffusion problem */ void diff_compute_beta(mesh_t *mesh, int cur_y, int cur_x, double beta_coef) { cell_t *cur_cell, *adj_cell; double diff_eff; cur_cell = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; for (int k = 0; k < 4; k++) { adj_cell = &mesh->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; if (adj_cell->diffusion == 0) { cur_cell->beta[k] = 0; } else { diff_eff = 2.0 * adj_cell->diffusion * cur_cell->diffusion; diff_eff /= (adj_cell->diffusion + cur_cell->diffusion); cur_cell->beta[k] =(-1.0) * beta_coef * mesh->dim.h / diff_eff; } } }
void setup_diffusion_test(mesh_t *mesh) { cell_t *cur_cell; double delta_x = mesh->dim.xlen / mesh->dim.xdim; double x; mesh->global.porosity = 1; for (int i = 0; i < mesh->dim.ydim; i++) { for (int j = 0; j < mesh->dim.xdim; j++) { x = delta_x * j; cur_cell = &mesh->cell[MESH_INDEX(i, j)]; cur_cell->saturation = 0; cur_cell->saturation_prev = sin(M_PI * x) + 0.5 * sin(3.0 * M_PI * x); cur_cell->diffusion = 1; } } }
/* Computes beta at the current cell for pressure problem */ void press_compute_beta(mesh_t *mesh, int cur_y, int cur_x, double beta_coef) { double perm_eff; cell_t *cur_cell, *adj_cell; double total_mob, adj_total_mob; cur_cell = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; total_mob = total_mobility(cur_cell, &mesh->global); for (int k = 0; k < 4; k++) { adj_cell = &mesh->cell[get_adjacent_index(mesh, k, cur_y, cur_x)]; adj_total_mob = total_mobility(adj_cell, &mesh->global); // printf("cur y %d, cur x %d, adj total mob %e\n", cur_y, cur_x, adj_total_mob); if (adj_cell->perm == 0) { cur_cell->beta[k] = 0; } else { perm_eff = 2 * adj_cell->perm * adj_total_mob * cur_cell->perm * total_mob; perm_eff /= (adj_cell->perm * adj_total_mob + cur_cell->perm * total_mob); cur_cell->beta[k] = beta_coef * mesh->dim.h / perm_eff; } // if (adj_cell->perm == 0) { // cur_cell->beta[k] = 0; // } else { // perm_eff = 2 * adj_cell->perm * cur_cell->perm; // perm_eff /= (adj_cell->perm + cur_cell->perm); // cur_cell->beta[k] = beta_coef * mesh->dim.h / perm_eff; // } /* temp fix for weird inf bug */ if ((cur_cell->beta[k] == INFINITY) || (cur_cell->beta[k] == NAN)) { cur_cell->beta[k] = 0; } } }
static void init_static_index_arrays (TestState *state) { guint n_indices; int x, y; guint16 *i; guint dir; /* - Each row takes (2 + 2 * MESH_WIDTH indices) * - Thats 2 to start the triangle strip then 2 indices to add 2 triangles * per mesh quad. * - We have MESH_HEIGHT rows * - It takes one extra index for linking between rows (MESH_HEIGHT - 1) * - A 2 x 3 mesh == 20 indices... */ n_indices = (2 + 2 * MESH_WIDTH) * MESH_HEIGHT + (MESH_HEIGHT - 1); state->static_indices = g_malloc (sizeof (guint16) * n_indices); state->n_static_indices = n_indices; #define MESH_INDEX(X, Y) (Y) * (MESH_WIDTH + 1) + (X) i = state->static_indices; /* NB: front facing == anti-clockwise winding */ i[0] = MESH_INDEX (0, 0); i[1] = MESH_INDEX (0, 1); i += 2; #define LEFT 0 #define RIGHT 1 dir = RIGHT; for (y = 0; y < MESH_HEIGHT; y++) { for (x = 0; x < MESH_WIDTH; x++) { /* Add 2 triangles per mesh quad... */ if (dir == RIGHT) { i[0] = MESH_INDEX (x + 1, y); i[1] = MESH_INDEX (x + 1, y + 1); } else { i[0] = MESH_INDEX (MESH_WIDTH - x - 1, y); i[1] = MESH_INDEX (MESH_WIDTH - x - 1, y + 1); } i += 2; } /* Link rows... */ if (y == (MESH_HEIGHT - 1)) break; if (dir == RIGHT) { i[0] = MESH_INDEX (MESH_WIDTH, y + 1); i[1] = MESH_INDEX (MESH_WIDTH, y + 1); i[2] = MESH_INDEX (MESH_WIDTH, y + 2); } else { i[0] = MESH_INDEX (0, y + 1); i[1] = MESH_INDEX (0, y + 1); i[2] = MESH_INDEX (0, y + 2); } i += 3; dir = !dir; } #undef MESH_INDEX state->indices = cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT, state->static_indices, state->n_static_indices); }
void trans_update_corner(mesh_t *mesh, mesh_t *mesh_old, int cur_y, int cur_x, int boundary_side1, int boundary_side2) { cell_t *cur_cell, *cur_cell_old, *adj_cell_vert, *adj_cell_hor, *adj_cell_diag; double y_comp, x_comp; /* Gets the x and y components of the backwards in time vector for method */ /* of characteristics */ y_comp = trans_get_old_position(mesh_old, cur_y, cur_x, 1); x_comp = trans_get_old_position(mesh_old, cur_y, cur_x, 0); cur_cell = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; cur_cell_old = &mesh->cell[MESH_INDEX(cur_y, cur_x)]; /* Gets the quadrant the foot is in */ int quad = get_quadrant(y_comp, x_comp); int corner_type = get_corner_config(boundary_side1, boundary_side2); /* Sets components to proportions of full cell */ y_comp = fabs(y_comp / mesh->dim.h); x_comp = fabs(x_comp / mesh->dim.h); // printf("ycomp %e, xcomp %e\n", y_comp, x_comp); /* Selects the configuration of cells */ switch (corner_type) { case 1: switch (quad) { case 1: dup_cell_corner(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag); break; case 2: dup_cell_vert(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, 3); break; case 3: assign_cells(mesh_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, quad); break; default: dup_cell_hor(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, 2); break; } break; case 2: switch (quad) { case 1: dup_cell_vert(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, 1); break; case 2: dup_cell_corner(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag); break; case 3: dup_cell_hor(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, 2); break; default: assign_cells(mesh_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, quad); break; } break; case 3: switch (quad) { case 1: assign_cells(mesh_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, quad); break; case 2: dup_cell_hor(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, 0); break; case 3: dup_cell_corner(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag); break; default: dup_cell_vert(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, 1); break; } break; default: switch (quad) { case 1: dup_cell_hor(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, 0); break; case 2: assign_cells(mesh_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, quad); break; case 3: dup_cell_vert(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag, cur_y, cur_x, 3); break; default: dup_cell_corner(mesh, cur_cell_old, &adj_cell_hor, &adj_cell_vert, &adj_cell_diag); break; } } cur_cell->saturation = trans_get_average_sat(cur_cell_old, adj_cell_hor, adj_cell_vert, adj_cell_diag, y_comp, x_comp); // printf("sat: %e\n", cur_cell->saturation); }
static void clutter_deform_effect_init_arrays (ClutterDeformEffect *self) { ClutterDeformEffectPrivate *priv = self->priv; GLushort *static_indices, *static_back_indices; GLushort *idx, *back_idx; gint x, y, direction; gint n_tiles; clutter_deform_effect_free_arrays (self); priv->n_indices = (2 + 2 * priv->x_tiles) * priv->y_tiles + (priv->y_tiles - 1); static_indices = g_new (GLushort, priv->n_indices); static_back_indices = g_new (GLushort, priv->n_indices); #define MESH_INDEX(x,y) ((y) * (priv->x_tiles + 1) + (x)) /* compute all the triangles from the various tiles */ direction = 1; idx = static_indices; idx[0] = MESH_INDEX (0, 0); idx[1] = MESH_INDEX (0, 1); idx += 2; back_idx = static_back_indices; back_idx[0] = MESH_INDEX (priv->x_tiles, 0); back_idx[1] = MESH_INDEX (priv->x_tiles, 1); back_idx += 2; for (y = 0; y < priv->y_tiles; y++) { for (x = 0; x < priv->x_tiles; x++) { if (direction) { idx[0] = MESH_INDEX (x + 1, y); idx[1] = MESH_INDEX (x + 1, y + 1); back_idx[0] = MESH_INDEX (priv->x_tiles - (x + 1), y); back_idx[1] = MESH_INDEX (priv->x_tiles - (x + 1), y + 1); } else { idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y); idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1); back_idx[0] = MESH_INDEX (x + 1, y); back_idx[1] = MESH_INDEX (x + 1, y + 1); } idx += 2; back_idx += 2; } if (y == (priv->y_tiles - 1)) break; if (direction) { idx[0] = MESH_INDEX (priv->x_tiles, y + 1); idx[1] = MESH_INDEX (priv->x_tiles, y + 1); idx[2] = MESH_INDEX (priv->x_tiles, y + 2); back_idx[0] = MESH_INDEX (0, y + 1); back_idx[1] = MESH_INDEX (0, y + 1); back_idx[2] = MESH_INDEX (0, y + 2); } else { idx[0] = MESH_INDEX (0, y + 1); idx[1] = MESH_INDEX (0, y + 1); idx[2] = MESH_INDEX (0, y + 2); back_idx[0] = MESH_INDEX (priv->x_tiles, y + 1); back_idx[1] = MESH_INDEX (priv->x_tiles, y + 1); back_idx[2] = MESH_INDEX (priv->x_tiles, y + 2); } idx += 3; back_idx += 3; direction = !direction; } #undef MESH_INDEX priv->indices = cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT, static_indices, priv->n_indices); priv->back_indices = cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT, static_back_indices, priv->n_indices); g_free (static_indices); g_free (static_back_indices); n_tiles = (priv->x_tiles + 1) * (priv->y_tiles + 1); priv->vertices = g_new (CoglTextureVertex, n_tiles); priv->vbo = cogl_vertex_buffer_new (n_tiles); priv->is_dirty = TRUE; }
static void clutter_deform_effect_init_arrays (ClutterDeformEffect *self) { ClutterDeformEffectPrivate *priv = self->priv; gint x, y, direction, n_indices; CoglAttribute *attributes[3]; guint16 *static_indices; CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); CoglIndices *indices; guint16 *idx; int i; clutter_deform_effect_free_arrays (self); n_indices = ((2 + 2 * priv->x_tiles) * priv->y_tiles + (priv->y_tiles - 1)); static_indices = g_new (guint16, n_indices); #define MESH_INDEX(x,y) ((y) * (priv->x_tiles + 1) + (x)) /* compute all the triangles from the various tiles */ direction = 1; idx = static_indices; idx[0] = MESH_INDEX (0, 0); idx[1] = MESH_INDEX (0, 1); idx += 2; for (y = 0; y < priv->y_tiles; y++) { for (x = 0; x < priv->x_tiles; x++) { if (direction) { idx[0] = MESH_INDEX (x + 1, y); idx[1] = MESH_INDEX (x + 1, y + 1); } else { idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y); idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1); } idx += 2; } if (y == (priv->y_tiles - 1)) break; if (direction) { idx[0] = MESH_INDEX (priv->x_tiles, y + 1); idx[1] = MESH_INDEX (priv->x_tiles, y + 1); idx[2] = MESH_INDEX (priv->x_tiles, y + 2); } else { idx[0] = MESH_INDEX (0, y + 1); idx[1] = MESH_INDEX (0, y + 1); idx[2] = MESH_INDEX (0, y + 2); } idx += 3; direction = !direction; } #undef MESH_INDEX indices = cogl_indices_new (ctx, COGL_INDICES_TYPE_UNSIGNED_SHORT, static_indices, n_indices); g_free (static_indices); priv->n_vertices = (priv->x_tiles + 1) * (priv->y_tiles + 1); priv->buffer = cogl_attribute_buffer_new (ctx, sizeof (CoglVertexP3T2C4) * priv->n_vertices, NULL); /* The application is expected to continuously modify the vertices so we should give a hint to Cogl about that */ cogl_buffer_set_update_hint (COGL_BUFFER (priv->buffer), COGL_BUFFER_UPDATE_HINT_DYNAMIC); attributes[0] = cogl_attribute_new (priv->buffer, "cogl_position_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, x), 3, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (priv->buffer, "cogl_tex_coord0_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[2] = cogl_attribute_new (priv->buffer, "cogl_color_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); priv->primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLE_STRIP, priv->n_vertices, attributes, 3 /* n_attributes */); cogl_primitive_set_indices (priv->primitive, indices, n_indices); if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DEFORM_TILES)) { priv->lines_primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINE_STRIP, priv->n_vertices, attributes, 2 /* n_attributes */); cogl_primitive_set_indices (priv->lines_primitive, indices, n_indices); } cogl_object_unref (indices); for (i = 0; i < 3; i++) cogl_object_unref (attributes[i]); priv->is_dirty = TRUE; }