/* returns a derived mesh if dm == NULL, for deforming modifiers that need it */ DerivedMesh *get_dm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], bool use_normals, bool use_orco) { if (dm) { /* pass */ } else if (ob->type == OB_MESH) { if (em) dm = CDDM_from_editbmesh(em, false, false); else dm = CDDM_from_mesh((struct Mesh *)(ob->data)); if (vertexCos) { CDDM_apply_vert_coords(dm, vertexCos); dm->dirty |= DM_DIRTY_NORMALS; } if (use_orco) { DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob)); } } else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { dm = CDDM_from_curve(ob); } if (use_normals) { if (LIKELY(dm)) { DM_ensure_normals(dm); } } return dm; }
void modwrap_deformVertsEM( ModifierData *md, Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts); }
struct DerivedMesh *modwrap_applyModifier( ModifierData *md, Object *ob, struct DerivedMesh *dm, ModifierApplyFlag flag) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } return mti->applyModifier(md, ob, dm, flag); }
void modwrap_deformVerts( ModifierData *md, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, ModifierApplyFlag flag) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag); }
/* returns a cdderivedmesh if dm == NULL or is another type of derivedmesh */ DerivedMesh *get_cddm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], bool use_normals) { if (dm) { if (dm->type != DM_TYPE_CDDM) { dm = CDDM_copy(dm); CDDM_apply_vert_coords(dm, vertexCos); } if (use_normals) { DM_ensure_normals(dm); } } else { dm = get_dm(ob, em, dm, vertexCos, use_normals, false); } return dm; }
/** * This function populates an array of verts for the triangles of a mesh * Tangent and Normals are also stored */ static void mesh_calc_tri_tessface( TriTessFace *triangles, Mesh *me, bool tangent, DerivedMesh *dm) { int i; MVert *mvert; TSpace *tspace; float *precomputed_normals = NULL; bool calculate_normal; const int tottri = poly_to_tri_count(me->totpoly, me->totloop); MLoopTri *looptri; /* calculate normal for each polygon only once */ unsigned int mpoly_prev = UINT_MAX; float no[3]; mvert = CustomData_get_layer(&me->vdata, CD_MVERT); looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__); if (tangent) { DM_ensure_normals(dm); DM_calc_loop_tangents(dm); precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL); calculate_normal = precomputed_normals ? false : true; tspace = dm->getLoopDataArray(dm, CD_TANGENT); BLI_assert(tspace); } BKE_mesh_recalc_looptri( me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri); for (i = 0; i < tottri; i++) { MLoopTri *lt = &looptri[i]; MPoly *mp = &me->mpoly[lt->poly]; triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v]; triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v]; triangles[i].mverts[2] = &mvert[me->mloop[lt->tri[2]].v]; triangles[i].is_smooth = (mp->flag & ME_SMOOTH) != 0; if (tangent) { triangles[i].tspace[0] = &tspace[lt->tri[0]]; triangles[i].tspace[1] = &tspace[lt->tri[1]]; triangles[i].tspace[2] = &tspace[lt->tri[2]]; if (calculate_normal) { if (lt->poly != mpoly_prev) { const MPoly *mp = &me->mpoly[lt->poly]; BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no); mpoly_prev = lt->poly; } copy_v3_v3(triangles[i].normal, no); } else { copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]); } } } MEM_freeN(looptri); }
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; }
/** * This function populates an array of verts for the triangles of a mesh * Tangent and Normals are also stored */ static void mesh_calc_tri_tessface( TriTessFace *triangles, Mesh *me, bool tangent, DerivedMesh *dm) { int i; int p_id; MFace *mface; MVert *mvert; TSpace *tspace; float *precomputed_normals = NULL; bool calculate_normal; mface = CustomData_get_layer(&me->fdata, CD_MFACE); mvert = CustomData_get_layer(&me->vdata, CD_MVERT); if (tangent) { DM_ensure_normals(dm); DM_add_tangent_layer(dm); precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL); calculate_normal = precomputed_normals ? false : true; //mface = dm->getTessFaceArray(dm); //mvert = dm->getVertArray(dm); tspace = dm->getTessFaceDataArray(dm, CD_TANGENT); BLI_assert(tspace); } p_id = -1; for (i = 0; i < me->totface; i++) { MFace *mf = &mface[i]; TSpace *ts = tangent ? &tspace[i * 4] : NULL; p_id++; triangles[p_id].mverts[0] = &mvert[mf->v1]; triangles[p_id].mverts[1] = &mvert[mf->v2]; triangles[p_id].mverts[2] = &mvert[mf->v3]; triangles[p_id].is_smooth = (mf->flag & ME_SMOOTH) != 0; if (tangent) { triangles[p_id].tspace[0] = &ts[0]; triangles[p_id].tspace[1] = &ts[1]; triangles[p_id].tspace[2] = &ts[2]; if (calculate_normal) { if (mf->v4 != 0) { normal_quad_v3(triangles[p_id].normal, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co); } else { normal_tri_v3(triangles[p_id].normal, triangles[p_id].mverts[0]->co, triangles[p_id].mverts[1]->co, triangles[p_id].mverts[2]->co); } } else { copy_v3_v3(triangles[p_id].normal, &precomputed_normals[3 * i]); } } /* 4 vertices in the face */ if (mf->v4 != 0) { p_id++; triangles[p_id].mverts[0] = &mvert[mf->v1]; triangles[p_id].mverts[1] = &mvert[mf->v3]; triangles[p_id].mverts[2] = &mvert[mf->v4]; triangles[p_id].is_smooth = (mf->flag & ME_SMOOTH) != 0; if (tangent) { triangles[p_id].tspace[0] = &ts[0]; triangles[p_id].tspace[1] = &ts[2]; triangles[p_id].tspace[2] = &ts[3]; /* same normal as the other "triangle" */ copy_v3_v3(triangles[p_id].normal, triangles[p_id - 1].normal); } } } BLI_assert(p_id < me->totface * 2); }