static DerivedMesh *doOcean(ModifierData *md, Object *ob, DerivedMesh *derivedData, int UNUSED(useRenderParams)) { OceanModifierData *omd = (OceanModifierData *) md; DerivedMesh *dm = NULL; OceanResult ocr; MVert *mverts, *mv; MLoop *mloops; int i, j; int num_verts; int num_faces; int cfra; /* use cached & inverted value for speed * expanded this would read... * * (axis / (omd->size * omd->spatial_size)) + 0.5f) */ #define OCEAN_CO(_size_co_inv, _v) ((_v * _size_co_inv) + 0.5f) const float size_co_inv = 1.0f / (omd->size * omd->spatial_size); /* can happen in when size is small, avoid bad array lookups later and quit now */ if (!finite(size_co_inv)) { return derivedData; } /* update modifier */ if (omd->refresh & MOD_OCEAN_REFRESH_ADD) omd->ocean = BKE_ocean_add(); if (omd->refresh & MOD_OCEAN_REFRESH_RESET) init_ocean_modifier(omd); 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); BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra); } else { simulate_ocean_modifier(omd); } if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) { dm = generate_ocean_geometry(omd); DM_ensure_normals(dm); } else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) { dm = CDDM_copy(derivedData); } cfra = md->scene->r.cfra; 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 (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; /* 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]); if (omd->oceancache && omd->cached == true) { BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v); foam = ocr.foam; CLAMP(foam, 0.0f, 1.0f); } else { BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); 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--); } } } } /* 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]); 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); mv->co[2] += ocr.disp[1]; if (omd->chop_amount > 0.0f) { mv->co[0] += ocr.disp[0]; mv->co[1] += ocr.disp[2]; } } #undef OCEAN_CO return dm; }
/* ***** actual texture sampling ***** */ int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres) { OceanTex *ot = tex->ot; ModifierData *md; OceanModifierData *omd; texres->tin = 0.0f; if ( !(ot) || !(ot->object) || !(md = (ModifierData *)modifiers_findByType(ot->object, eModifierType_Ocean)) || !(omd = (OceanModifierData *)md)->ocean) { return 0; } else { const int do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS); int cfra = R.r.cfra; int retval = TEX_INT; OceanResult ocr; const float u = 0.5f + 0.5f * texvec[0]; const float v = 0.5f + 0.5f * texvec[1]; if (omd->oceancache && omd->cached == true) { CLAMP(cfra, omd->bakestart, omd->bakeend); cfra -= omd->bakestart; /* shift to 0 based */ BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v); } else { /* non-cached */ if (G.is_rendering) BKE_ocean_eval_uv_catrom(omd->ocean, &ocr, u, v); else BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); ocr.foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage); } switch (ot->output) { case TEX_OCN_DISPLACEMENT: /* XYZ displacement */ texres->tr = 0.5f + 0.5f * ocr.disp[0]; texres->tg = 0.5f + 0.5f * ocr.disp[2]; texres->tb = 0.5f + 0.5f * ocr.disp[1]; texres->tr = MAX2(0.0f, texres->tr); texres->tg = MAX2(0.0f, texres->tg); texres->tb = MAX2(0.0f, texres->tb); BRICONTRGB; retval = TEX_RGB; break; case TEX_OCN_EMINUS: /* -ve eigenvectors ? */ texres->tr = ocr.Eminus[0]; texres->tg = ocr.Eminus[2]; texres->tb = ocr.Eminus[1]; retval = TEX_RGB; break; case TEX_OCN_EPLUS: /* -ve eigenvectors ? */ texres->tr = ocr.Eplus[0]; texres->tg = ocr.Eplus[2]; texres->tb = ocr.Eplus[1]; retval = TEX_RGB; break; case TEX_OCN_JPLUS: texres->tin = ocr.Jplus; retval = TEX_INT; break; case TEX_OCN_FOAM: texres->tin = ocr.foam; BRICONT; retval = TEX_INT; break; } /* if normals needed */ if (texres->nor && do_normals) { normalize_v3_v3(texres->nor, ocr.normal); retval |= TEX_NOR; } texres->ta = 1.0f; return retval; } }