Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/modifiers/intern/MOD_ocean.c')
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c305
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,
};