static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd) { DerivedMesh *result; GenerateOceanGeometryData gogd; int num_verts; int num_polys; const bool use_threading = omd->resolution > 4; gogd.rx = omd->resolution * omd->resolution; gogd.ry = omd->resolution * omd->resolution; gogd.res_x = gogd.rx * omd->repeat_x; gogd.res_y = gogd.ry * omd->repeat_y; num_verts = (gogd.res_x + 1) * (gogd.res_y + 1); num_polys = gogd.res_x * gogd.res_y; gogd.sx = omd->size * omd->spatial_size; gogd.sy = omd->size * omd->spatial_size; gogd.ox = -gogd.sx / 2.0f; gogd.oy = -gogd.sy / 2.0f; gogd.sx /= gogd.rx; gogd.sy /= gogd.ry; result = CDDM_new(num_verts, 0, 0, num_polys * 4, num_polys); gogd.mverts = CDDM_get_verts(result); gogd.mpolys = CDDM_get_polys(result); gogd.mloops = CDDM_get_loops(result); gogd.origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX); /* create vertices */ BLI_task_parallel_range(0, gogd.res_y + 1, &gogd, generate_ocean_geometry_vertices, use_threading); /* create faces */ BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_polygons, use_threading); CDDM_calc_edges(result); /* add uvs */ if (CustomData_number_of_layers(&result->loopData, CD_MLOOPUV) < MAX_MTFACE) { gogd.mloopuvs = CustomData_add_layer(&result->loopData, CD_MLOOPUV, CD_CALLOC, NULL, num_polys * 4); CustomData_add_layer(&result->polyData, CD_MTEXPOLY, CD_CALLOC, NULL, num_polys); if (gogd.mloopuvs) { /* unlikely to fail */ gogd.ix = 1.0 / gogd.rx; gogd.iy = 1.0 / gogd.ry; BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_uvs, use_threading); } } result->dirty |= DM_DIRTY_NORMALS; return result; }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag UNUSED(flag)) { UVWarpModifierData *umd = (UVWarpModifierData *) md; int numPolys, numLoops; MPoly *mpoly; MLoop *mloop; MLoopUV *mloopuv; MDeformVert *dvert; int defgrp_index; char uvname[MAX_CUSTOMDATA_LAYER_NAME]; float mat_src[4][4]; float mat_dst[4][4]; float imat_dst[4][4]; float warp_mat[4][4]; const int axis_u = umd->axis_u; const int axis_v = umd->axis_v; /* make sure there are UV Maps available */ if (!CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) { return dm; } else if (ELEM(NULL, umd->object_src, umd->object_dst)) { modifier_setError(md, "From/To objects must be set"); return dm; } /* make sure anything moving UVs is available */ matrix_from_obj_pchan(mat_src, umd->object_src, umd->bone_src); matrix_from_obj_pchan(mat_dst, umd->object_dst, umd->bone_dst); invert_m4_m4(imat_dst, mat_dst); mul_m4_m4m4(warp_mat, imat_dst, mat_src); /* apply warp */ if (!is_zero_v2(umd->center)) { float mat_cent[4][4]; float imat_cent[4][4]; unit_m4(mat_cent); mat_cent[3][axis_u] = umd->center[0]; mat_cent[3][axis_v] = umd->center[1]; invert_m4_m4(imat_cent, mat_cent); mul_m4_m4m4(warp_mat, warp_mat, imat_cent); mul_m4_m4m4(warp_mat, mat_cent, warp_mat); } /* make sure we're using an existing layer */ CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, umd->uvlayer_name, uvname); numPolys = dm->getNumPolys(dm); numLoops = dm->getNumLoops(dm); mpoly = dm->getPolyArray(dm); mloop = dm->getLoopArray(dm); /* make sure we are not modifying the original UV map */ mloopuv = CustomData_duplicate_referenced_layer_named(&dm->loopData, CD_MLOOPUV, uvname, numLoops); modifier_get_vgroup(ob, dm, umd->vgroup_name, &dvert, &defgrp_index); UVWarpData data = {.mpoly = mpoly, .mloop = mloop, .mloopuv = mloopuv, .dvert = dvert, .defgrp_index = defgrp_index, .warp_mat = warp_mat, .axis_u = axis_u, .axis_v = axis_v}; BLI_task_parallel_range(0, numPolys, &data, uv_warp_compute, numPolys > 1000); dm->dirty |= DM_DIRTY_TESS_CDLAYERS; return dm; }