diff options
Diffstat (limited to 'source/blender/modifiers/intern/MOD_ocean.c')
-rw-r--r-- | source/blender/modifiers/intern/MOD_ocean.c | 305 |
1 files changed, 162 insertions, 143 deletions
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 913c2f25c15..a90a51e9ddc 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -37,6 +37,7 @@ #include "BLI_math.h" #include "BLI_math_inline.h" +#include "BLI_task.h" #include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" @@ -265,125 +266,144 @@ static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, floa #ifdef WITH_OCEANSIM -#ifdef _OPENMP -#define OMP_MIN_RES 18 -#endif - -static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd) -{ - DerivedMesh *result; - +typedef struct GenerateOceanGeometryData { MVert *mverts; MPoly *mpolys; MLoop *mloops; int *origindex; + MLoopUV *mloopuvs; - int cdlayer; + int res_x, res_y; + int rx, ry; + float ox, oy; + float sx, sy; + float ix, iy; +} GenerateOceanGeometryData; - const int rx = omd->resolution * omd->resolution; - const int ry = omd->resolution * omd->resolution; - const int res_x = rx * omd->repeat_x; - const int res_y = ry * omd->repeat_y; +static void generate_ocean_geometry_vertices(void *userdata, const int y) +{ + GenerateOceanGeometryData *gogd = userdata; + int x; + + for (x = 0; x <= gogd->res_x; x++) { + const int i = y * (gogd->res_x + 1) + x; + float *co = gogd->mverts[i].co; + co[0] = gogd->ox + (x * gogd->sx); + co[1] = gogd->oy + (y * gogd->sy); + co[2] = 0.0f; + } +} - const int num_verts = (res_x + 1) * (res_y + 1); - /* const int num_edges = (res_x * res_y * 2) + res_x + res_y; */ /* UNUSED BMESH */ - const int num_faces = res_x * res_y; +static void generate_ocean_geometry_polygons(void *userdata, const int y) +{ + GenerateOceanGeometryData *gogd = userdata; + int x; + + for (x = 0; x < gogd->res_x; x++) { + const int fi = y * gogd->res_x + x; + const int vi = y * (gogd->res_x + 1) + x; + MPoly *mp = &gogd->mpolys[fi]; + MLoop *ml = &gogd->mloops[fi * 4]; + + ml->v = vi; + ml++; + ml->v = vi + 1; + ml++; + ml->v = vi + 1 + gogd->res_x + 1; + ml++; + ml->v = vi + gogd->res_x + 1; + ml++; + + mp->loopstart = fi * 4; + mp->totloop = 4; + + mp->flag |= ME_SMOOTH; + + /* generated geometry does not map to original faces */ + gogd->origindex[fi] = ORIGINDEX_NONE; + } +} - float sx = omd->size * omd->spatial_size; - float sy = omd->size * omd->spatial_size; - const float ox = -sx / 2.0f; - const float oy = -sy / 2.0f; +static void generate_ocean_geometry_uvs(void *userdata, const int y) +{ + GenerateOceanGeometryData *gogd = userdata; + int x; - float ix, iy; + for (x = 0; x < gogd->res_x; x++) { + const int i = y * gogd->res_x + x; + MLoopUV *luv = &gogd->mloopuvs[i * 4]; + + luv->uv[0] = x * gogd->ix; + luv->uv[1] = y * gogd->iy; + luv++; + + luv->uv[0] = (x + 1) * gogd->ix; + luv->uv[1] = y * gogd->iy; + luv++; + + luv->uv[0] = (x + 1) * gogd->ix; + luv->uv[1] = (y + 1) * gogd->iy; + luv++; + + luv->uv[0] = x * gogd->ix; + luv->uv[1] = (y + 1) * gogd->iy; + luv++; + } +} + +static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd) +{ + DerivedMesh *result; + + GenerateOceanGeometryData gogd; + + int num_verts; + int num_polys; + + const bool use_threading = omd->resolution > 4; - int x, y; + 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; - sx /= rx; - sy /= ry; + num_verts = (gogd.res_x + 1) * (gogd.res_y + 1); + num_polys = gogd.res_x * gogd.res_y; - result = CDDM_new(num_verts, 0, 0, num_faces * 4, num_faces); + 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; - mverts = CDDM_get_verts(result); - mpolys = CDDM_get_polys(result); - mloops = CDDM_get_loops(result); + gogd.sx /= gogd.rx; + gogd.sy /= gogd.ry; - origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX); + 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 */ -#pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES) - for (y = 0; y <= res_y; y++) { - for (x = 0; x <= res_x; x++) { - const int i = y * (res_x + 1) + x; - float *co = mverts[i].co; - co[0] = ox + (x * sx); - co[1] = oy + (y * sy); - co[2] = 0; - } - } + BLI_task_parallel_range(0, gogd.res_y + 1, &gogd, generate_ocean_geometry_vertices, use_threading); /* create faces */ -#pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES) - for (y = 0; y < res_y; y++) { - for (x = 0; x < res_x; x++) { - const int fi = y * res_x + x; - const int vi = y * (res_x + 1) + x; - MPoly *mp = &mpolys[fi]; - MLoop *ml = &mloops[fi * 4]; - - ml->v = vi; - ml++; - ml->v = vi + 1; - ml++; - ml->v = vi + 1 + res_x + 1; - ml++; - ml->v = vi + res_x + 1; - ml++; - - mp->loopstart = fi * 4; - mp->totloop = 4; - - mp->flag |= ME_SMOOTH; - - /* generated geometry does not map to original faces */ - origindex[fi] = ORIGINDEX_NONE; - } - } + BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_polygons, use_threading); CDDM_calc_edges(result); /* add uvs */ - cdlayer = CustomData_number_of_layers(&result->loopData, CD_MLOOPUV); - if (cdlayer < MAX_MTFACE) { - MLoopUV *mloopuvs = CustomData_add_layer(&result->loopData, CD_MLOOPUV, CD_CALLOC, NULL, num_faces * 4); - CustomData_add_layer(&result->polyData, CD_MTEXPOLY, CD_CALLOC, NULL, num_faces); - - if (mloopuvs) { /* unlikely to fail */ - ix = 1.0 / rx; - iy = 1.0 / ry; -#pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES) - for (y = 0; y < res_y; y++) { - for (x = 0; x < res_x; x++) { - const int i = y * res_x + x; - MLoopUV *luv = &mloopuvs[i * 4]; - - luv->uv[0] = x * ix; - luv->uv[1] = y * iy; - luv++; - - luv->uv[0] = (x + 1) * ix; - luv->uv[1] = y * iy; - luv++; - - luv->uv[0] = (x + 1) * ix; - luv->uv[1] = (y + 1) * iy; - luv++; - - luv->uv[0] = x * ix; - luv->uv[1] = (y + 1) * iy; - luv++; + 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); } } @@ -401,15 +421,10 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob, DerivedMesh *dm = NULL; OceanResult ocr; - MVert *mverts, *mv; - MLoop *mloops; - - int i, j; - - int num_verts; - int num_faces; + MVert *mverts; int cfra; + int i, j; /* use cached & inverted value for speed * expanded this would read... @@ -425,18 +440,22 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob, } /* update modifier */ - if (omd->refresh & MOD_OCEAN_REFRESH_ADD) + if (omd->refresh & MOD_OCEAN_REFRESH_ADD) { omd->ocean = BKE_ocean_add(); - if (omd->refresh & MOD_OCEAN_REFRESH_RESET) + } + if (omd->refresh & MOD_OCEAN_REFRESH_RESET) { init_ocean_modifier(omd); - if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE) + } + if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE) { clear_cache_data(omd); - + } omd->refresh = 0; /* do ocean simulation */ if (omd->cached == true) { - if (!omd->oceancache) init_cache_data(ob, omd); + if (!omd->oceancache) { + init_cache_data(ob, omd); + } BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra); } else { @@ -455,38 +474,31 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob, CLAMP(cfra, omd->bakestart, omd->bakeend); cfra -= omd->bakestart; /* shift to 0 based */ - num_verts = dm->getNumVerts(dm); - num_faces = dm->getNumPolys(dm); - mverts = dm->getVertArray(dm); - mloops = dm->getLoopArray(dm); /* add vcols before displacement - allows lookup based on position */ if (omd->flag & MOD_OCEAN_GENERATE_FOAM) { - int cdlayer = CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL); - - if (cdlayer < MAX_MCOL) { - MLoopCol *mloopcols = CustomData_add_layer_named(&dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, - num_faces * 4, omd->foamlayername); + if (CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL) < MAX_MCOL) { + const int num_polys = dm->getNumPolys(dm); + const int num_loops = dm->getNumLoops(dm); + MLoop *mloops = dm->getLoopArray(dm); + MLoopCol *mloopcols = CustomData_add_layer_named( + &dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->foamlayername); if (mloopcols) { /* unlikely to fail */ - MLoopCol *mlcol; MPoly *mpolys = dm->getPolyArray(dm); MPoly *mp; - float foam; - - for (i = 0, mp = mpolys; i < num_faces; i++, mp++) { - j = mp->totloop - 1; + for (i = 0, mp = mpolys; i < num_polys; i++, mp++) { + MLoop *ml = &mloops[mp->loopstart]; + MLoopCol *mlcol = &mloopcols[mp->loopstart]; - /* highly unlikely */ - if (j <= 0) continue; - - do { - const float *co = mverts[mloops[mp->loopstart + j].v].co; - const float u = OCEAN_CO(size_co_inv, co[0]); - const float v = OCEAN_CO(size_co_inv, co[1]); + for (j = mp->totloop; j--; ml++, mlcol++) { + const float *vco = mverts[ml->v].co; + const float u = OCEAN_CO(size_co_inv, vco[0]); + const float v = OCEAN_CO(size_co_inv, vco[1]); + float foam; if (omd->oceancache && omd->cached == true) { BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v); @@ -498,11 +510,10 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob, foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage); } - mlcol = &mloopcols[mp->loopstart + j]; mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255); /* This needs to be set (render engine uses) */ mlcol->a = 255; - } while (j--); + } } } } @@ -511,21 +522,28 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob, /* displace the geometry */ - /* #pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES) */ - for (i = 0, mv = mverts; i < num_verts; i++, mv++) { - const float u = OCEAN_CO(size_co_inv, mv->co[0]); - const float v = OCEAN_CO(size_co_inv, mv->co[1]); + /* Note: tried to parallelized that one and previous foam loop, but gives 20% slower results... odd. */ + { + const int num_verts = dm->getNumVerts(dm); - if (omd->oceancache && omd->cached == true) - BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v); - else - BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); + for (i = 0; i < num_verts; i++) { + float *vco = mverts[i].co; + const float u = OCEAN_CO(size_co_inv, vco[0]); + const float v = OCEAN_CO(size_co_inv, vco[1]); - mv->co[2] += ocr.disp[1]; + if (omd->oceancache && omd->cached == true) { + BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v); + } + else { + BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); + } + + vco[2] += ocr.disp[1]; - if (omd->chop_amount > 0.0f) { - mv->co[0] += ocr.disp[0]; - mv->co[1] += ocr.disp[2]; + if (omd->chop_amount > 0.0f) { + vco[0] += ocr.disp[0]; + vco[1] += ocr.disp[2]; + } } } @@ -585,4 +603,5 @@ ModifierTypeInfo modifierType_Ocean = { /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, }; |