Blender V2.61 - r43446
|
00001 00028 #include "MEM_guardedalloc.h" 00029 00030 #include "DNA_customdata_types.h" 00031 #include "DNA_object_types.h" 00032 #include "DNA_meshdata_types.h" 00033 #include "DNA_modifier_types.h" 00034 #include "DNA_scene_types.h" 00035 00036 #include "BKE_cdderivedmesh.h" 00037 #include "BKE_global.h" 00038 #include "BKE_modifier.h" 00039 #include "BKE_ocean.h" 00040 #include "BKE_utildefines.h" 00041 00042 #include "BLI_blenlib.h" 00043 #include "BLI_math.h" 00044 #include "BLI_math_inline.h" 00045 #include "BLI_utildefines.h" 00046 #include "BLI_string.h" 00047 00048 #include "MOD_util.h" 00049 00050 #ifdef WITH_OCEANSIM 00051 static void init_cache_data(Object *ob, struct OceanModifierData *omd) 00052 { 00053 const char *relbase= modifier_path_relbase(ob); 00054 00055 omd->oceancache = BKE_init_ocean_cache(omd->cachepath, relbase, 00056 omd->bakestart, omd->bakeend, omd->wave_scale, 00057 omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution); 00058 } 00059 00060 static void clear_cache_data(struct OceanModifierData *omd) 00061 { 00062 BKE_free_ocean_cache(omd->oceancache); 00063 omd->oceancache = NULL; 00064 omd->cached = FALSE; 00065 } 00066 00067 /* keep in sync with init_ocean_modifier_bake(), object_modifier.c */ 00068 static void init_ocean_modifier(struct OceanModifierData *omd) 00069 { 00070 int do_heightfield, do_chop, do_normals, do_jacobian; 00071 00072 if (!omd || !omd->ocean) return; 00073 00074 do_heightfield = TRUE; 00075 do_chop = (omd->chop_amount > 0); 00076 do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS); 00077 do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM); 00078 00079 BKE_free_ocean_data(omd->ocean); 00080 BKE_init_ocean(omd->ocean, omd->resolution*omd->resolution, omd->resolution*omd->resolution, omd->spatial_size, omd->spatial_size, 00081 omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment, 00082 omd->depth, omd->time, 00083 do_heightfield, do_chop, do_normals, do_jacobian, 00084 omd->seed); 00085 } 00086 00087 static void simulate_ocean_modifier(struct OceanModifierData *omd) 00088 { 00089 if (!omd || !omd->ocean) return; 00090 00091 BKE_simulate_ocean(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount); 00092 } 00093 #endif /* WITH_OCEANSIM */ 00094 00095 00096 00097 /* Modifier Code */ 00098 00099 static void initData(ModifierData *md) 00100 { 00101 #ifdef WITH_OCEANSIM 00102 OceanModifierData *omd = (OceanModifierData*) md; 00103 00104 omd->resolution = 7; 00105 omd->spatial_size = 50; 00106 00107 omd->wave_alignment = 0.0; 00108 omd->wind_velocity = 30.0; 00109 00110 omd->damp = 0.5; 00111 omd->smallest_wave = 0.01; 00112 omd->wave_direction= 0.0; 00113 omd->depth = 200.0; 00114 00115 omd->wave_scale = 1.0; 00116 00117 omd->chop_amount = 1.0; 00118 00119 omd->foam_coverage = 0.0; 00120 00121 omd->seed = 0; 00122 omd->time = 1.0; 00123 00124 omd->refresh = 0; 00125 00126 omd->size = 1.0; 00127 omd->repeat_x = 1; 00128 omd->repeat_y = 1; 00129 00130 modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean"); 00131 00132 omd->cached = 0; 00133 omd->bakestart = 1; 00134 omd->bakeend = 250; 00135 omd->oceancache = NULL; 00136 omd->foam_fade = 0.98; 00137 omd->foamlayername[0] = '\0'; /* layer name empty by default */ 00138 00139 omd->ocean = BKE_add_ocean(); 00140 init_ocean_modifier(omd); 00141 simulate_ocean_modifier(omd); 00142 #else // WITH_OCEANSIM 00143 /* unused */ 00144 (void)md; 00145 #endif // WITH_OCEANSIM 00146 } 00147 00148 static void freeData(ModifierData *md) 00149 { 00150 #ifdef WITH_OCEANSIM 00151 OceanModifierData *omd = (OceanModifierData*) md; 00152 00153 BKE_free_ocean(omd->ocean); 00154 if (omd->oceancache) 00155 BKE_free_ocean_cache(omd->oceancache); 00156 #else // WITH_OCEANSIM 00157 /* unused */ 00158 (void)md; 00159 #endif // WITH_OCEANSIM 00160 } 00161 00162 static void copyData(ModifierData *md, ModifierData *target) 00163 { 00164 #ifdef WITH_OCEANSIM 00165 OceanModifierData *omd = (OceanModifierData*) md; 00166 OceanModifierData *tomd = (OceanModifierData*) target; 00167 00168 tomd->resolution = omd->resolution; 00169 tomd->spatial_size = omd->spatial_size; 00170 00171 tomd->wind_velocity = omd->wind_velocity; 00172 00173 tomd->damp = omd->damp; 00174 tomd->smallest_wave = omd->smallest_wave; 00175 tomd->depth = omd->depth; 00176 00177 tomd->wave_alignment = omd->wave_alignment; 00178 tomd->wave_direction = omd->wave_direction; 00179 tomd->wave_scale = omd->wave_scale; 00180 00181 tomd->chop_amount = omd->chop_amount; 00182 tomd->foam_coverage = omd->foam_coverage; 00183 tomd->time = omd->time; 00184 00185 tomd->seed = omd->seed; 00186 tomd->flag = omd->flag; 00187 00188 tomd->refresh = 0; 00189 00190 00191 tomd->size = omd->size; 00192 tomd->repeat_x = omd->repeat_x; 00193 tomd->repeat_y = omd->repeat_y; 00194 00195 /* XXX todo: copy cache runtime too */ 00196 tomd->cached = 0; 00197 tomd->bakestart = omd->bakestart; 00198 tomd->bakeend = omd->bakeend; 00199 tomd->oceancache = NULL; 00200 00201 tomd->ocean = BKE_add_ocean(); 00202 init_ocean_modifier(tomd); 00203 simulate_ocean_modifier(tomd); 00204 #else // WITH_OCEANSIM 00205 /* unused */ 00206 (void)md; 00207 (void)target; 00208 #endif // WITH_OCEANSIM 00209 } 00210 00211 #ifdef WITH_OCEANSIM 00212 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) 00213 { 00214 OceanModifierData *omd = (OceanModifierData *)md; 00215 CustomDataMask dataMask = 0; 00216 00217 if (omd->flag & MOD_OCEAN_GENERATE_FOAM) 00218 dataMask |= CD_MASK_MCOL; 00219 00220 return dataMask; 00221 } 00222 #else // WITH_OCEANSIM 00223 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) 00224 { 00225 /* unused */ 00226 (void)md; 00227 return 0; 00228 } 00229 #endif // WITH_OCEANSIM 00230 00231 #if 0 00232 static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, float *oy) 00233 { 00234 /* get bounding box of underlying dm */ 00235 int v, totvert=dm->getNumVerts(dm); 00236 float min[3], max[3], delta[3]; 00237 00238 MVert *mvert = dm->getVertDataArray(dm,0); 00239 00240 copy_v3_v3(min, mvert->co); 00241 copy_v3_v3(max, mvert->co); 00242 00243 for(v=1; v<totvert; v++, mvert++) { 00244 min[0]=MIN2(min[0],mvert->co[0]); 00245 min[1]=MIN2(min[1],mvert->co[1]); 00246 min[2]=MIN2(min[2],mvert->co[2]); 00247 00248 max[0]=MAX2(max[0],mvert->co[0]); 00249 max[1]=MAX2(max[1],mvert->co[1]); 00250 max[2]=MAX2(max[2],mvert->co[2]); 00251 } 00252 00253 sub_v3_v3v3(delta, max, min); 00254 00255 *sx = delta[0]; 00256 *sy = delta[1]; 00257 00258 *ox = min[0]; 00259 *oy = min[1]; 00260 } 00261 #endif 00262 00263 #ifdef WITH_OCEANSIM 00264 00265 00266 #define OMP_MIN_RES 18 00267 static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd) 00268 { 00269 DerivedMesh *result; 00270 00271 MVert *mverts; 00272 MFace *mfaces; 00273 int *origindex; 00274 00275 int cdlayer; 00276 00277 const int rx = omd->resolution*omd->resolution; 00278 const int ry = omd->resolution*omd->resolution; 00279 const int res_x = rx * omd->repeat_x; 00280 const int res_y = ry * omd->repeat_y; 00281 00282 const int num_verts = (res_x + 1) * (res_y + 1); 00283 const int num_edges = (res_x * res_y * 2) + res_x + res_y; 00284 const int num_faces = res_x * res_y; 00285 00286 float sx = omd->size * omd->spatial_size; 00287 float sy = omd->size * omd->spatial_size; 00288 const float ox = -sx / 2.0f; 00289 const float oy = -sy / 2.0f; 00290 00291 float ix, iy; 00292 00293 int x, y; 00294 00295 sx /= rx; 00296 sy /= ry; 00297 00298 result = CDDM_new(num_verts, num_edges, num_faces); 00299 00300 mverts = CDDM_get_verts(result); 00301 mfaces = CDDM_get_faces(result); 00302 origindex= result->getFaceDataArray(result, CD_ORIGINDEX); 00303 00304 /* create vertices */ 00305 #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES) 00306 for (y=0; y < res_y+1; y++) { 00307 for (x=0; x < res_x+1; x++) { 00308 const int i = y*(res_x+1) + x; 00309 float *co= mverts[i].co; 00310 co[0] = ox + (x * sx); 00311 co[1] = oy + (y * sy); 00312 co[2] = 0; 00313 } 00314 } 00315 00316 /* create faces */ 00317 #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES) 00318 for (y=0; y < res_y; y++) { 00319 for (x=0; x < res_x; x++) { 00320 const int fi = y*res_x + x; 00321 const int vi = y*(res_x+1) + x; 00322 MFace *mf= &mfaces[fi]; 00323 mf->v1 = vi; 00324 mf->v2 = vi + 1; 00325 mf->v3 = vi + 1 + res_x+1; 00326 mf->v4 = vi + res_x+1; 00327 00328 mf->flag |= ME_SMOOTH; 00329 00330 /* generated geometry does not map to original faces */ 00331 origindex[fi] = ORIGINDEX_NONE; 00332 } 00333 } 00334 00335 CDDM_calc_edges(result); 00336 00337 /* add uvs */ 00338 cdlayer= CustomData_number_of_layers(&result->faceData, CD_MTFACE); 00339 if(cdlayer < MAX_MTFACE) { 00340 MTFace *tfaces= CustomData_add_layer(&result->faceData, CD_MTFACE, CD_CALLOC, NULL, num_faces); 00341 00342 if (tfaces) { /* unlikely to fail */ 00343 ix = 1.0 / rx; 00344 iy = 1.0 / ry; 00345 #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES) 00346 for (y=0; y < res_y; y++) { 00347 for (x=0; x < res_x; x++) { 00348 const int i = y*res_x + x; 00349 tfaces[i].uv[0][0] = x * ix; 00350 tfaces[i].uv[0][1] = y * iy; 00351 00352 tfaces[i].uv[1][0] = (x+1) * ix; 00353 tfaces[i].uv[1][1] = y * iy; 00354 00355 tfaces[i].uv[2][0] = (x+1) * ix; 00356 tfaces[i].uv[2][1] = (y+1) * iy; 00357 00358 tfaces[i].uv[3][0] = x * ix; 00359 tfaces[i].uv[3][1] = (y+1) * iy; 00360 } 00361 } 00362 } 00363 } 00364 00365 return result; 00366 } 00367 00368 static DerivedMesh *doOcean(ModifierData *md, Object *ob, 00369 DerivedMesh *derivedData, 00370 int UNUSED(useRenderParams)) 00371 { 00372 OceanModifierData *omd = (OceanModifierData*) md; 00373 00374 DerivedMesh *dm=NULL; 00375 OceanResult ocr; 00376 00377 MVert *mverts, *mv; 00378 00379 int i, j; 00380 00381 int num_verts; 00382 int num_faces; 00383 00384 int cfra; 00385 00386 /* use cached & inverted value for speed 00387 * expanded this would read... 00388 * 00389 * (axis / (omd->size * omd->spatial_size)) + 0.5f) */ 00390 #define OCEAN_CO(_size_co_inv, _v) ((_v * _size_co_inv) + 0.5f) 00391 00392 const float size_co_inv= 1.0f / (omd->size * omd->spatial_size); 00393 00394 /* update modifier */ 00395 if (omd->refresh & MOD_OCEAN_REFRESH_ADD) 00396 omd->ocean = BKE_add_ocean(); 00397 if (omd->refresh & MOD_OCEAN_REFRESH_RESET) 00398 init_ocean_modifier(omd); 00399 if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE) 00400 clear_cache_data(omd); 00401 00402 omd->refresh = 0; 00403 00404 /* do ocean simulation */ 00405 if (omd->cached == TRUE) { 00406 if (!omd->oceancache) init_cache_data(ob, omd); 00407 BKE_simulate_ocean_cache(omd->oceancache, md->scene->r.cfra); 00408 } 00409 else { 00410 simulate_ocean_modifier(omd); 00411 } 00412 00413 if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) 00414 dm = generate_ocean_geometry(omd); 00415 else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) { 00416 dm = CDDM_copy(derivedData); 00417 } 00418 00419 cfra = md->scene->r.cfra; 00420 CLAMP(cfra, omd->bakestart, omd->bakeend); 00421 cfra -= omd->bakestart; // shift to 0 based 00422 00423 num_verts = dm->getNumVerts(dm); 00424 num_faces = dm->getNumFaces(dm); 00425 00426 mverts = dm->getVertArray(dm); 00427 00428 /* add vcols before displacement - allows lookup based on position */ 00429 00430 if (omd->flag & MOD_OCEAN_GENERATE_FOAM) { 00431 int cdlayer= CustomData_number_of_layers(&dm->faceData, CD_MCOL); 00432 00433 if(cdlayer < MAX_MCOL) { 00434 MCol *mcols= CustomData_add_layer_named(&dm->faceData, CD_MCOL, CD_CALLOC, NULL, num_faces, omd->foamlayername); 00435 00436 if (mcols) { /* unlikely to fail */ 00437 MCol *mc; 00438 MFace *mfaces= dm->getFaceArray(dm); 00439 MFace *mf; 00440 00441 float foam; 00442 00443 for (i = 0, mf= mfaces; i < num_faces; i++, mf++) { 00444 j= mf->v4 ? 3 : 2; 00445 do { 00446 const float *co= mverts[*(&mf->v1 + j)].co; 00447 const float u = OCEAN_CO(size_co_inv, co[0]); 00448 const float v = OCEAN_CO(size_co_inv, co[1]); 00449 00450 if (omd->oceancache && omd->cached==TRUE) { 00451 BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v); 00452 foam = ocr.foam; 00453 CLAMP(foam, 0.0f, 1.0f); 00454 } 00455 else { 00456 BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); 00457 foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage); 00458 } 00459 00460 mc= &mcols[i*4 + j]; 00461 mc->r = mc->g = mc->b = (char)(foam * 255); 00462 /* mc->a = 255; */ /* no need to set */ 00463 } while (j--); 00464 } 00465 } 00466 } 00467 } 00468 00469 00470 /* displace the geometry */ 00471 00472 //#pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES) 00473 for (i=0, mv= mverts; i< num_verts; i++, mv++) { 00474 const float u = OCEAN_CO(size_co_inv, mv->co[0]); 00475 const float v = OCEAN_CO(size_co_inv, mv->co[1]); 00476 00477 if (omd->oceancache && omd->cached==TRUE) 00478 BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v); 00479 else 00480 BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); 00481 00482 mv->co[2] += ocr.disp[1]; 00483 00484 if (omd->chop_amount > 0.0f) { 00485 mv->co[0] += ocr.disp[0]; 00486 mv->co[1] += ocr.disp[2]; 00487 } 00488 } 00489 00490 #undef OCEAN_CO 00491 00492 return dm; 00493 } 00494 #else // WITH_OCEANSIM 00495 static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob), 00496 DerivedMesh *derivedData, 00497 int UNUSED(useRenderParams)) 00498 { 00499 /* unused */ 00500 (void)md; 00501 return derivedData; 00502 } 00503 #endif // WITH_OCEANSIM 00504 00505 static DerivedMesh *applyModifier(ModifierData *md, Object *ob, 00506 DerivedMesh *derivedData, 00507 int UNUSED(useRenderParams), 00508 int UNUSED(isFinalCalc)) 00509 { 00510 DerivedMesh *result; 00511 00512 result = doOcean(md, ob, derivedData, 0); 00513 00514 if(result != derivedData) 00515 CDDM_calc_normals(result); 00516 00517 return result; 00518 } 00519 00520 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob, 00521 struct EditMesh *UNUSED(editData), 00522 DerivedMesh *derivedData) 00523 { 00524 return applyModifier(md, ob, derivedData, 0, 1); 00525 } 00526 00527 00528 00529 ModifierTypeInfo modifierType_Ocean = { 00530 /* name */ "Ocean", 00531 /* structName */ "OceanModifierData", 00532 /* structSize */ sizeof(OceanModifierData), 00533 /* type */ eModifierTypeType_Constructive, 00534 /* flags */ eModifierTypeFlag_AcceptsMesh 00535 | eModifierTypeFlag_SupportsEditmode 00536 | eModifierTypeFlag_EnableInEditmode, 00537 00538 /* copyData */ copyData, 00539 /* deformMatrices */ NULL, 00540 /* deformVerts */ NULL, 00541 /* deformVertsEM */ NULL, 00542 /* deformMatricesEM */ NULL, 00543 /* applyModifier */ applyModifier, 00544 /* applyModifierEM */ applyModifierEM, 00545 /* initData */ initData, 00546 /* requiredDataMask */ requiredDataMask, 00547 /* freeData */ freeData, 00548 /* isDisabled */ NULL, 00549 /* updateDepgraph */ NULL, 00550 /* dependsOnTime */ NULL, 00551 /* dependsOnNormals */ NULL, 00552 /* foreachObjectLink */ NULL, 00553 /* foreachIDLink */ NULL, 00554 };