/* mode = 0: interpolate normals, * mode = 1: interpolate coord */ static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float crn_y, int mode, float res[3]) { int x0, x1, y0, y1; float u, v; float data[4][3]; x0 = (int) crn_x; x1 = x0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (x0 + 1); y0 = (int) crn_y; y1 = y0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (y0 + 1); u = crn_x - x0; v = crn_y - y0; if (mode == 0) { copy_v3_v3(data[0], CCG_grid_elem_no(key, grid, x0, y0)); copy_v3_v3(data[1], CCG_grid_elem_no(key, grid, x1, y0)); copy_v3_v3(data[2], CCG_grid_elem_no(key, grid, x1, y1)); copy_v3_v3(data[3], CCG_grid_elem_no(key, grid, x0, y1)); } else { copy_v3_v3(data[0], CCG_grid_elem_co(key, grid, x0, y0)); copy_v3_v3(data[1], CCG_grid_elem_co(key, grid, x1, y0)); copy_v3_v3(data[2], CCG_grid_elem_co(key, grid, x1, y1)); copy_v3_v3(data[3], CCG_grid_elem_co(key, grid, x0, y1)); } interp_bilinear_quad_v3(data, u, v, res); }
BLI_INLINE void multires_reshape_propagate_init_patch_corners( MultiresPropagateData *data, CCGElem *delta_grid, const int patch_x, const int patch_y, MultiresPropagateCornerData r_corners[4]) { CCGKey *delta_level_key = &data->top_level_key; const int orig_grid_size = data->reshape_grid_size; const int top_grid_size = data->top_grid_size; const int skip = (top_grid_size - 1) / (orig_grid_size - 1); const int x = patch_x * skip; const int y = patch_y * skip; /* Store coordinate deltas. */ copy_v3_v3(r_corners[0].coord_delta, CCG_grid_elem_co(delta_level_key, delta_grid, x, y)); copy_v3_v3(r_corners[1].coord_delta, CCG_grid_elem_co(delta_level_key, delta_grid, x + skip, y)); copy_v3_v3(r_corners[2].coord_delta, CCG_grid_elem_co(delta_level_key, delta_grid, x, y + skip)); copy_v3_v3(r_corners[3].coord_delta, CCG_grid_elem_co(delta_level_key, delta_grid, x + skip, y + skip)); if (delta_level_key->has_mask) { r_corners[0].mask_delta = *CCG_grid_elem_mask(delta_level_key, delta_grid, x, y); r_corners[1].mask_delta = *CCG_grid_elem_mask(delta_level_key, delta_grid, x + skip, y); r_corners[2].mask_delta = *CCG_grid_elem_mask(delta_level_key, delta_grid, x, y + skip); r_corners[3].mask_delta = *CCG_grid_elem_mask(delta_level_key, delta_grid, x + skip, y + skip); } }
/* Apply smoothed deltas on the actual data layers. */ static void multires_reshape_propagate_apply_delta(MultiresPropagateData *data, CCGElem **delta_grids_data) { const int num_grids = data->num_grids; /* At this point those custom data layers has updated data for the * level we are propagating from. */ MDisps *mdisps = data->mdisps; GridPaintMask *grid_paint_mask = data->grid_paint_mask; CCGKey *orig_key = &data->reshape_level_key; CCGKey *delta_level_key = &data->top_level_key; CCGElem **orig_grids_data = data->orig_grids_data; const int orig_grid_size = data->reshape_grid_size; const int top_grid_size = data->top_grid_size; const int skip = (top_grid_size - 1) / (orig_grid_size - 1); /* Restore grid values at the reshape level. Those values are to be changed * to the accommodate for the smooth delta. */ for (int grid_index = 0; grid_index < num_grids; grid_index++) { CCGElem *orig_grid = orig_grids_data[grid_index]; for (int y = 0; y < orig_grid_size; y++) { const int top_y = y * skip; for (int x = 0; x < orig_grid_size; x++) { const int top_x = x * skip; const int top_index = top_y * top_grid_size + top_x; copy_v3_v3(mdisps[grid_index].disps[top_index], CCG_grid_elem_co(orig_key, orig_grid, x, y)); if (grid_paint_mask != NULL) { grid_paint_mask[grid_index].data[top_index] = *CCG_grid_elem_mask( orig_key, orig_grid, x, y); } } } } /* Add smoothed delta to all the levels. */ for (int grid_index = 0; grid_index < num_grids; grid_index++) { CCGElem *delta_grid = delta_grids_data[grid_index]; for (int y = 0; y < top_grid_size; y++) { for (int x = 0; x < top_grid_size; x++) { const int top_index = y * top_grid_size + x; add_v3_v3(mdisps[grid_index].disps[top_index], CCG_grid_elem_co(delta_level_key, delta_grid, x, y)); if (delta_level_key->has_mask) { grid_paint_mask[grid_index].data[top_index] += *CCG_grid_elem_mask( delta_level_key, delta_grid, x, y); } } } } }
BLI_INLINE void multires_reshape_propagate_and_smooth_delta_grid_patch(MultiresPropagateData *data, CCGElem *delta_grid, const int patch_x, const int patch_y) { CCGKey *delta_level_key = &data->top_level_key; const int orig_grid_size = data->reshape_grid_size; const int top_grid_size = data->top_grid_size; const int skip = (top_grid_size - 1) / (orig_grid_size - 1); const float skip_inv = 1.0f / (float)skip; MultiresPropagateCornerData corners[4]; multires_reshape_propagate_init_patch_corners(data, delta_grid, patch_x, patch_y, corners); const int start_x = patch_x * skip; const int start_y = patch_y * skip; for (int y = 0; y <= skip; y++) { const float v = (float)y * skip_inv; const int final_y = start_y + y; for (int x = 0; x <= skip; x++) { const float u = (float)x * skip_inv; const int final_x = start_x + x; const float linear_weights[4] = { (1.0f - u) * (1.0f - v), u * (1.0f - v), (1.0f - u) * v, u * v}; multires_reshape_propagate_interpolate_coord( CCG_grid_elem_co(delta_level_key, delta_grid, final_x, final_y), corners, linear_weights); if (delta_level_key->has_mask) { float *mask = CCG_grid_elem_mask(delta_level_key, delta_grid, final_x, final_y); *mask = multires_reshape_propagate_interpolate_mask(corners, linear_weights); } } } }
static void multires_reshape_store_original_grids(MultiresPropagateData *data) { const int num_grids = data->num_grids; /* Original data to be backed up. */ const MDisps *mdisps = data->mdisps; const GridPaintMask *grid_paint_mask = data->grid_paint_mask; /* Allocate grids for backup. */ CCGKey *orig_key = &data->reshape_level_key; CCGElem **orig_grids_data = allocate_grids(orig_key, num_grids); /* Fill in grids. */ const int orig_grid_size = data->reshape_grid_size; const int top_grid_size = data->top_grid_size; const int skip = (top_grid_size - 1) / (orig_grid_size - 1); for (int grid_index = 0; grid_index < num_grids; grid_index++) { CCGElem *orig_grid = orig_grids_data[grid_index]; for (int y = 0; y < orig_grid_size; y++) { const int top_y = y * skip; for (int x = 0; x < orig_grid_size; x++) { const int top_x = x * skip; const int top_index = top_y * top_grid_size + top_x; memcpy(CCG_grid_elem_co(orig_key, orig_grid, x, y), mdisps[grid_index].disps[top_index], sizeof(float) * 3); if (orig_key->has_mask) { *CCG_grid_elem_mask( orig_key, orig_grid, x, y) = grid_paint_mask[grid_index].data[top_index]; } } } } /* Store in the context. */ data->orig_grids_data = orig_grids_data; }
static void create_ao_raytree(MultiresBakeRender *bkr, MAOBakeData *ao_data) { DerivedMesh *hidm = bkr->hires_dm; RayObject *raytree; RayFace *face; CCGElem **grid_data; CCGKey key; int num_grids, grid_size /*, face_side */, num_faces; int i; num_grids = hidm->getNumGrids(hidm); grid_size = hidm->getGridSize(hidm); grid_data = hidm->getGridData(hidm); hidm->getGridKey(hidm, &key); /* face_side = (grid_size << 1) - 1; */ /* UNUSED */ num_faces = num_grids * (grid_size - 1) * (grid_size - 1); raytree = ao_data->raytree = RE_rayobject_create(bkr->raytrace_structure, num_faces, bkr->octree_resolution); face = ao_data->rayfaces = (RayFace *) MEM_callocN(num_faces * sizeof(RayFace), "ObjectRen faces"); for (i = 0; i < num_grids; i++) { int x, y; for (x = 0; x < grid_size - 1; x++) { for (y = 0; y < grid_size - 1; y++) { float co[4][3]; copy_v3_v3(co[0], CCG_grid_elem_co(&key, grid_data[i], x, y)); copy_v3_v3(co[1], CCG_grid_elem_co(&key, grid_data[i], x, y + 1)); copy_v3_v3(co[2], CCG_grid_elem_co(&key, grid_data[i], x + 1, y + 1)); copy_v3_v3(co[3], CCG_grid_elem_co(&key, grid_data[i], x + 1, y)); RE_rayface_from_coords(face, ao_data, face, co[0], co[1], co[2], co[3]); RE_rayobject_add(raytree, RE_rayobject_unalignRayFace(face)); face++; } } } RE_rayobject_done(raytree); }
/* Calculate delta of changed reshape level data layers. Delta goes to a * grids at top level (meaning, the result grids are only partially filled * in). */ static void multires_reshape_calculate_delta(MultiresPropagateData *data, CCGElem **delta_grids_data) { const int num_grids = data->num_grids; /* At this point those custom data layers has updated data for the * level we are propagating from. */ const MDisps *mdisps = data->mdisps; const GridPaintMask *grid_paint_mask = data->grid_paint_mask; CCGKey *reshape_key = &data->reshape_level_key; CCGKey *delta_level_key = &data->top_level_key; /* Calculate delta. */ const int top_grid_size = data->top_grid_size; const int reshape_grid_size = data->reshape_grid_size; const int delta_grid_size = data->top_grid_size; const int skip = (top_grid_size - 1) / (reshape_grid_size - 1); for (int grid_index = 0; grid_index < num_grids; grid_index++) { /*const*/ CCGElem *orig_grid = data->orig_grids_data[grid_index]; CCGElem *delta_grid = delta_grids_data[grid_index]; for (int y = 0; y < reshape_grid_size; y++) { const int top_y = y * skip; for (int x = 0; x < reshape_grid_size; x++) { const int top_x = x * skip; const int top_index = top_y * delta_grid_size + top_x; sub_v3_v3v3(CCG_grid_elem_co(delta_level_key, delta_grid, top_x, top_y), mdisps[grid_index].disps[top_index], CCG_grid_elem_co(reshape_key, orig_grid, x, y)); if (delta_level_key->has_mask) { const float old_mask_value = *CCG_grid_elem_mask(reshape_key, orig_grid, x, y); const float new_mask_value = grid_paint_mask[grid_index].data[top_index]; *CCG_grid_elem_mask(delta_level_key, delta_grid, top_x, top_y) = new_mask_value - old_mask_value; } } } } }