/* Builds a bvh tree where nodes are the vertices of the given dm */ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis) { BVHTree *tree; MVert *vert; bool vert_allocated; BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS); BLI_rw_mutex_unlock(&cache_rwlock); vert = DM_get_vert_array(dm, &vert_allocated); /* Not in cache */ if (tree == NULL) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS); if (tree == NULL) { tree = bvhtree_from_mesh_verts_create_tree(epsilon, tree_type, axis, vert, dm->getNumVerts(dm), NULL, -1); if (tree) { /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTS); } } BLI_rw_mutex_unlock(&cache_rwlock); } else { /* printf("BVHTree is already build, using cached tree\n"); */ } /* Setup BVHTreeFromMesh */ bvhtree_from_mesh_verts_setup_data(data, tree, true, epsilon, vert, vert_allocated); return data->tree; }
/* Builds a bvh tree where nodes are the tesselated faces of the given dm */ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis) { BMEditMesh *em = data->em_evil; const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_FACES; BVHTree *tree; MVert *vert = NULL; MFace *face = NULL; bool vert_allocated = false, face_allocated = false; BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); tree = bvhcache_find(&dm->bvhCache, bvhcache_type); BLI_rw_mutex_unlock(&cache_rwlock); if (em == NULL) { vert = DM_get_vert_array(dm, &vert_allocated); face = DM_get_tessface_array(dm, &face_allocated); } /* Not in cache */ if (tree == NULL) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); tree = bvhcache_find(&dm->bvhCache, bvhcache_type); if (tree == NULL) { int numFaces; /* BMESH specific check that we have tessfaces, * we _could_ tessellate here but rather not - campbell * * this assert checks we have tessfaces, * if not caller should use DM_ensure_tessface() */ if (em) { numFaces = em->tottri; } else { numFaces = dm->getNumTessFaces(dm); BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0)); } tree = bvhtree_from_mesh_faces_create_tree(epsilon, tree_type, axis, em, vert, face, numFaces, NULL, -1); if (tree) { /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ bvhcache_insert(&dm->bvhCache, tree, bvhcache_type); } } BLI_rw_mutex_unlock(&cache_rwlock); } else { /* printf("BVHTree is already build, using cached tree\n"); */ } /* Setup BVHTreeFromMesh */ bvhtree_from_mesh_faces_setup_data(data, tree, true, epsilon, em, vert, vert_allocated, face, face_allocated); return data->tree; }
static void rna_SmokeModifier_velocity_grid_get(PointerRNA *ptr, float *values) { #ifdef WITH_SMOKE SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data; int length[RNA_MAX_ARRAY_DIMENSION]; int size = rna_SmokeModifier_velocity_grid_get_length(ptr, length); float *vx, *vy, *vz; int i; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); vx = smoke_get_velocity_x(sds->fluid); vy = smoke_get_velocity_y(sds->fluid); vz = smoke_get_velocity_z(sds->fluid); for (i = 0; i < size; i += 3) { *(values++) = *(vx++); *(values++) = *(vy++); *(values++) = *(vz++); } BLI_rw_mutex_unlock(sds->fluid_mutex); #else UNUSED_VARS(ptr, values); #endif }
static void set_height_normalize_factor(struct Ocean *oc) { float res = 1.0; float max_h = 0.0; int i, j; if (!oc->_do_disp_y) return; oc->normalize_factor = 1.0; BKE_simulate_ocean(oc, 0.0, 1.0, 0); BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ); for (i = 0; i < oc->_M; ++i) { for (j = 0; j < oc->_N; ++j) { if (max_h < fabsf(oc->_disp_y[i * oc->_N + j])) { max_h = fabsf(oc->_disp_y[i * oc->_N + j]); } } } BLI_rw_mutex_unlock(&oc->oceanmutex); if (max_h == 0.0f) max_h = 0.00001f; /* just in case ... */ res = 1.0f / (max_h); oc->normalize_factor = res; }
static void rna_SmokeModifier_color_grid_get(PointerRNA *ptr, float *values) { #ifdef WITH_SMOKE SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); if (sds->flags & MOD_SMOKE_HIGHRES) { if (smoke_turbulence_has_colors(sds->wt)) smoke_turbulence_get_rgba(sds->wt, values, 0); else smoke_turbulence_get_rgba_from_density(sds->wt, sds->active_color, values, 0); } else { if (smoke_has_colors(sds->fluid)) smoke_get_rgba(sds->fluid, values, 0); else smoke_get_rgba_from_density(sds->fluid, sds->active_color, values, 0); } BLI_rw_mutex_unlock(sds->fluid_mutex); #else UNUSED_VARS(ptr, values); #endif }
/* note that this doesn't wrap properly for i, j < 0, but its not really meant for that being just a way to get * the raw data out to save in some image format. */ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j) { BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ); i = abs(i) % oc->_M; j = abs(j) % oc->_N; ocr->disp[1] = oc->_do_disp_y ? (float)oc->_disp_y[i * oc->_N + j] : 0.0f; if (oc->_do_chop) { ocr->disp[0] = oc->_disp_x[i * oc->_N + j]; ocr->disp[2] = oc->_disp_z[i * oc->_N + j]; } else { ocr->disp[0] = 0.0f; ocr->disp[2] = 0.0f; } if (oc->_do_normals) { ocr->normal[0] = oc->_N_x[i * oc->_N + j]; ocr->normal[1] = oc->_N_y /* oc->_N_y[i * oc->_N + j] (MEM01) */; ocr->normal[2] = oc->_N_z[i * oc->_N + j]; normalize_v3(ocr->normal); } if (oc->_do_jacobian) { compute_eigenstuff(ocr, oc->_Jxx[i * oc->_N + j], oc->_Jzz[i * oc->_N + j], oc->_Jxz[i * oc->_N + j]); } BLI_rw_mutex_unlock(&oc->oceanmutex); }
static void rna_SmokeModifier_flame_grid_get(PointerRNA *ptr, float *values) { #ifdef WITH_SMOKE SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data; int length[RNA_MAX_ARRAY_DIMENSION]; int size = rna_SmokeModifier_grid_get_length(ptr, length); float *flame; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) flame = smoke_turbulence_get_flame(sds->wt); else flame = smoke_get_flame(sds->fluid); if (flame) memcpy(values, flame, size * sizeof(float)); else memset(values, 0, size * sizeof(float)); BLI_rw_mutex_unlock(sds->fluid_mutex); #else UNUSED_VARS(ptr, values); #endif }
static void rna_SmokeModifier_heat_grid_get(PointerRNA *ptr, float *values) { #ifdef WITH_SMOKE SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data; int length[RNA_MAX_ARRAY_DIMENSION]; int size = rna_SmokeModifier_heat_grid_get_length(ptr, length); float *heat; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); heat = smoke_get_heat(sds->fluid); if (heat != NULL) { /* scale heat values from -2.0-2.0 to -1.0-1.0. */ for (int i = 0; i < size; i++) { values[i] = heat[i] * 0.5f; } } else { memset(values, 0, size * sizeof(float)); } BLI_rw_mutex_unlock(sds->fluid_mutex); #else UNUSED_VARS(ptr, values); #endif }
int RE_engine_render(Render *re, int do_all) { RenderEngineType *type= RE_engines_find(re->r.engine); RenderEngine *engine; /* verify if we can render */ if (!type->render) return 0; if ((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_USE_PREVIEW)) return 0; if (do_all && !(type->flag & RE_USE_POSTPROCESS)) return 0; if (!do_all && (type->flag & RE_USE_POSTPROCESS)) return 0; /* create render result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) { if (re->result) render_result_free(re->result); re->result= render_result_new(re, &re->disprect, 0, 0); } BLI_rw_mutex_unlock(&re->resultmutex); if (re->result==NULL) return 1; /* set render info */ re->i.cfra= re->scene->r.cfra; BLI_strncpy(re->i.scenename, re->scene->id.name+2, sizeof(re->i.scenename)); re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0; /* render */ engine = RE_engine_create(type); engine->re= re; if (re->flag & R_ANIMATION) engine->flag |= RE_ENGINE_ANIMATION; if (re->r.scemode & R_PREVIEWBUTS) engine->flag |= RE_ENGINE_PREVIEW; engine->camera_override = re->camera_override; if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_PREVIEWBUTS))==0) scene_update_for_newframe(re->main, re->scene, re->lay); if (type->update) type->update(engine, re->main, re->scene); if (type->render) type->render(engine, re->scene); render_result_free_list(&engine->fullresult, engine->fullresult.first); RE_engine_free(engine); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.afbreek = 1; return 1; }
void BKE_free_ocean_data(struct Ocean *oc) { if (!oc) return; BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_WRITE); if (oc->_do_disp_y) { fftw_destroy_plan(oc->_disp_y_plan); MEM_freeN(oc->_disp_y); } if (oc->_do_normals) { MEM_freeN(oc->_fft_in_nx); MEM_freeN(oc->_fft_in_nz); fftw_destroy_plan(oc->_N_x_plan); fftw_destroy_plan(oc->_N_z_plan); MEM_freeN(oc->_N_x); /*fftwf_free(oc->_N_y); (MEM01)*/ MEM_freeN(oc->_N_z); } if (oc->_do_chop) { MEM_freeN(oc->_fft_in_x); MEM_freeN(oc->_fft_in_z); fftw_destroy_plan(oc->_disp_x_plan); fftw_destroy_plan(oc->_disp_z_plan); MEM_freeN(oc->_disp_x); MEM_freeN(oc->_disp_z); } if (oc->_do_jacobian) { MEM_freeN(oc->_fft_in_jxx); MEM_freeN(oc->_fft_in_jzz); MEM_freeN(oc->_fft_in_jxz); fftw_destroy_plan(oc->_Jxx_plan); fftw_destroy_plan(oc->_Jzz_plan); fftw_destroy_plan(oc->_Jxz_plan); MEM_freeN(oc->_Jxx); MEM_freeN(oc->_Jzz); MEM_freeN(oc->_Jxz); } if (oc->_fft_in) MEM_freeN(oc->_fft_in); /* check that ocean data has been initialized */ if (oc->_htilda) { MEM_freeN(oc->_htilda); MEM_freeN(oc->_k); MEM_freeN(oc->_h0); MEM_freeN(oc->_h0_minus); MEM_freeN(oc->_kx); MEM_freeN(oc->_kz); } BLI_rw_mutex_unlock(&oc->oceanmutex); }
rcti* RE_engine_get_current_tiles(Render *re, int *total_tiles_r, bool *r_needs_free) { static rcti tiles_static[BLENDER_MAX_THREADS]; const int allocation_step = BLENDER_MAX_THREADS; RenderPart *pa; int total_tiles = 0; rcti *tiles = tiles_static; int allocation_size = BLENDER_MAX_THREADS; BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ); *r_needs_free = false; if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) { *total_tiles_r = 0; BLI_rw_mutex_unlock(&re->partsmutex); return NULL; } for (pa = re->parts.first; pa; pa = pa->next) { if (pa->status == PART_STATUS_IN_PROGRESS) { if (total_tiles >= allocation_size) { /* Just in case we're using crazy network rendering with more * slaves as BLENDER_MAX_THREADS. */ if (tiles == tiles_static) tiles = MEM_mallocN(allocation_step * sizeof(rcti), "current engine tiles"); else tiles = MEM_reallocN(tiles, (total_tiles + allocation_step) * sizeof(rcti)); allocation_size += allocation_step; *r_needs_free = true; } tiles[total_tiles] = pa->disprect; if (pa->crop) { tiles[total_tiles].xmin += pa->crop; tiles[total_tiles].ymin += pa->crop; tiles[total_tiles].xmax -= pa->crop; tiles[total_tiles].ymax -= pa->crop; } total_tiles++; } } BLI_rw_mutex_unlock(&re->partsmutex); *total_tiles_r = total_tiles; return tiles; }
static void rna_SmokeModifier_density_grid_get(PointerRNA *ptr, float *values) { #ifdef WITH_SMOKE SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data; int length[RNA_MAX_ARRAY_DIMENSION]; int size = rna_SmokeModifier_grid_get_length(ptr, length); float *density; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) density = smoke_turbulence_get_density(sds->wt); else density = smoke_get_density(sds->fluid); memcpy(values, density, size * sizeof(float)); BLI_rw_mutex_unlock(sds->fluid_mutex); #else (void)ptr; (void)values; #endif }
/** * Builds a bvh tree where nodes are the looptri faces of the given dm * * \note for editmesh this is currently a duplicate of bvhtree_from_mesh_faces */ BVHTree *bvhtree_from_mesh_looptri(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis) { BMEditMesh *em = data->em_evil; const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_LOOPTRI; BVHTree *tree; MVert *mvert = NULL; MLoop *mloop = NULL; const MLoopTri *looptri = NULL; bool vert_allocated = false; bool loop_allocated = false; bool looptri_allocated = false; BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); tree = bvhcache_find(&dm->bvhCache, bvhcache_type); BLI_rw_mutex_unlock(&cache_rwlock); if (em == NULL) { MPoly *mpoly; bool poly_allocated = false; mvert = DM_get_vert_array(dm, &vert_allocated); mpoly = DM_get_poly_array(dm, &poly_allocated); mloop = DM_get_loop_array(dm, &loop_allocated); looptri = DM_get_looptri_array( dm, mvert, mpoly, dm->getNumPolys(dm), mloop, dm->getNumLoops(dm), &looptri_allocated); if (poly_allocated) { MEM_freeN(mpoly); } } /* Not in cache */ if (tree == NULL) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); tree = bvhcache_find(&dm->bvhCache, bvhcache_type); if (tree == NULL) { int looptri_num; /* BMESH specific check that we have tessfaces, * we _could_ tessellate here but rather not - campbell * * this assert checks we have tessfaces, * if not caller should use DM_ensure_tessface() */ if (em) { looptri_num = em->tottri; } else { looptri_num = dm->getNumLoopTri(dm); BLI_assert(!(looptri_num == 0 && dm->getNumPolys(dm) != 0)); } tree = bvhtree_from_mesh_looptri_create_tree( epsilon, tree_type, axis, em, mvert, mloop, looptri, looptri_num, NULL, -1); if (tree) { /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ bvhcache_insert(&dm->bvhCache, tree, bvhcache_type); } } BLI_rw_mutex_unlock(&cache_rwlock); } else { /* printf("BVHTree is already build, using cached tree\n"); */ } /* Setup BVHTreeFromMesh */ bvhtree_from_mesh_looptri_setup_data( data, tree, true, epsilon, em, mvert, vert_allocated, mloop, loop_allocated, looptri, looptri_allocated); return data->tree; }
int RE_engine_render(Render *re, int do_all) { RenderEngineType *type = RE_engines_find(re->r.engine); RenderEngine *engine; int persistent_data = re->r.mode & R_PERSISTENT_DATA; /* verify if we can render */ if (!type->render) return 0; if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW)) return 0; if (do_all && !(type->flag & RE_USE_POSTPROCESS)) return 0; if (!do_all && (type->flag & RE_USE_POSTPROCESS)) return 0; /* update animation here so any render layer animation is applied before * creating the render result */ if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) { unsigned int lay = re->lay; /* don't update layers excluded on all render layers */ if (type->flag & RE_USE_EXCLUDE_LAYERS) { SceneRenderLayer *srl; unsigned int non_excluded_lay = 0; if (re->r.scemode & R_SINGLE_LAYER) { srl = BLI_findlink(&re->r.layers, re->r.actlay); if (srl) non_excluded_lay |= ~srl->lay_exclude; } else { for (srl = re->r.layers.first; srl; srl = srl->next) if (!(srl->layflag & SCE_LAY_DISABLE)) non_excluded_lay |= ~srl->lay_exclude; } lay &= non_excluded_lay; } BKE_scene_update_for_newframe(re->main, re->scene, lay); } /* create render result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) { int savebuffers = RR_USE_MEM; if (re->result) render_result_free(re->result); if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE)) savebuffers = RR_USE_EXR; re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS); } BLI_rw_mutex_unlock(&re->resultmutex); if (re->result == NULL) return 1; /* set render info */ re->i.cfra = re->scene->r.cfra; BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name)); re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0; /* render */ engine = re->engine; if (!engine) { engine = RE_engine_create(type); re->engine = engine; } engine->flag |= RE_ENGINE_RENDERING; /* TODO: actually link to a parent which shouldn't happen */ engine->re = re; if (re->flag & R_ANIMATION) engine->flag |= RE_ENGINE_ANIMATION; if (re->r.scemode & R_BUTS_PREVIEW) engine->flag |= RE_ENGINE_PREVIEW; engine->camera_override = re->camera_override; engine->resolution_x = re->winx; engine->resolution_y = re->winy; RE_parts_init(re, FALSE); engine->tile_x = re->partx; engine->tile_y = re->party; if (re->result->do_exr_tile) render_result_exr_file_begin(re); if (type->update) type->update(engine, re->main, re->scene); if (type->render) type->render(engine, re->scene); engine->tile_x = 0; engine->tile_y = 0; engine->flag &= ~RE_ENGINE_RENDERING; render_result_free_list(&engine->fullresult, engine->fullresult.first); /* re->engine becomes zero if user changed active render engine during render */ if (!persistent_data || !re->engine) { RE_engine_free(engine); re->engine = NULL; } if (re->result->do_exr_tile) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_exr_file_end(re); BLI_rw_mutex_unlock(&re->resultmutex); } RE_parts_free(re); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = TRUE; return 1; }
/* Builds a bvh tree where nodes are the edges of the given dm */ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis) { BVHTree *tree; MVert *vert; MEdge *edge; bool vert_allocated, edge_allocated; BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_EDGES); BLI_rw_mutex_unlock(&cache_rwlock); vert = DM_get_vert_array(dm, &vert_allocated); edge = DM_get_edge_array(dm, &edge_allocated); /* Not in cache */ if (tree == NULL) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_EDGES); if (tree == NULL) { int i; int numEdges = dm->getNumEdges(dm); if (vert != NULL && edge != NULL) { /* Create a bvh-tree of the given target */ tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis); if (tree != NULL) { for (i = 0; i < numEdges; i++) { float co[4][3]; copy_v3_v3(co[0], vert[edge[i].v1].co); copy_v3_v3(co[1], vert[edge[i].v2].co); BLI_bvhtree_insert(tree, i, co[0], 2); } BLI_bvhtree_balance(tree); /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES); } } } BLI_rw_mutex_unlock(&cache_rwlock); } else { /* printf("BVHTree is already build, using cached tree\n"); */ } /* Setup BVHTreeFromMesh */ memset(data, 0, sizeof(*data)); data->tree = tree; if (data->tree) { data->cached = true; data->nearest_callback = mesh_edges_nearest_point; data->raycast_callback = mesh_edges_spherecast; data->vert = vert; data->vert_allocated = vert_allocated; data->edge = edge; data->edge_allocated = edge_allocated; data->sphere_radius = epsilon; } else { if (vert_allocated) { MEM_freeN(vert); } if (edge_allocated) { MEM_freeN(edge); } } return data->tree; }
/* Builds a bvh tree.. where nodes are the vertexs of the given mesh */ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis) { BVHTree *tree; MVert *vert; bool vert_allocated; BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTICES); BLI_rw_mutex_unlock(&cache_rwlock); vert = DM_get_vert_array(dm, &vert_allocated); /* Not in cache */ if (tree == NULL) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTICES); if (tree == NULL) { int i; int numVerts = dm->getNumVerts(dm); if (vert != NULL) { tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis); if (tree != NULL) { for (i = 0; i < numVerts; i++) { BLI_bvhtree_insert(tree, i, vert[i].co, 1); } BLI_bvhtree_balance(tree); /* Save on cache for later use */ // printf("BVHTree built and saved on cache\n"); bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTICES); } } } BLI_rw_mutex_unlock(&cache_rwlock); } else { // printf("BVHTree is already build, using cached tree\n"); } /* Setup BVHTreeFromMesh */ memset(data, 0, sizeof(*data)); data->tree = tree; if (data->tree) { data->cached = true; /* a NULL nearest callback works fine * remember the min distance to point is the same as the min distance to BV of point */ data->nearest_callback = NULL; data->raycast_callback = NULL; data->vert = vert; data->vert_allocated = vert_allocated; data->face = DM_get_tessface_array(dm, &data->face_allocated); data->sphere_radius = epsilon; } else { if (vert_allocated) { MEM_freeN(vert); } } return data->tree; }
static void sss_create_tree_mat(Render *re, Material *mat) { SSSPoints *p; RenderResult *rr; ListBase points; float (*co)[3] = NULL, (*color)[3] = NULL, *area = NULL; int totpoint = 0, osa, osaflag, partsdone; if (re->test_break(re->tbh)) return; points.first= points.last= NULL; /* TODO: this is getting a bit ugly, copying all those variables and * setting them back, maybe we need to create our own Render? */ /* do SSS preprocessing render */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); rr= re->result; osa= re->osa; osaflag= re->r.mode & R_OSA; partsdone= re->i.partsdone; re->osa= 0; re->r.mode &= ~R_OSA; re->sss_points= &points; re->sss_mat= mat; re->i.partsdone = FALSE; if (!(re->r.scemode & R_PREVIEWBUTS)) re->result= NULL; BLI_rw_mutex_unlock(&re->resultmutex); RE_TileProcessor(re); BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (!(re->r.scemode & R_PREVIEWBUTS)) { RE_FreeRenderResult(re->result); re->result= rr; } BLI_rw_mutex_unlock(&re->resultmutex); re->i.partsdone= partsdone; re->sss_mat= NULL; re->sss_points= NULL; re->osa= osa; if (osaflag) re->r.mode |= R_OSA; /* no points? no tree */ if (!points.first) return; /* merge points together into a single buffer */ if (!re->test_break(re->tbh)) { for (totpoint=0, p=points.first; p; p=p->next) totpoint += p->totpoint; co= MEM_mallocN(sizeof(*co)*totpoint, "SSSCo"); color= MEM_mallocN(sizeof(*color)*totpoint, "SSSColor"); area= MEM_mallocN(sizeof(*area)*totpoint, "SSSArea"); for (totpoint=0, p=points.first; p; p=p->next) { memcpy(co+totpoint, p->co, sizeof(*co)*p->totpoint); memcpy(color+totpoint, p->color, sizeof(*color)*p->totpoint); memcpy(area+totpoint, p->area, sizeof(*area)*p->totpoint); totpoint += p->totpoint; } } /* free points */ for (p=points.first; p; p=p->next) { MEM_freeN(p->co); MEM_freeN(p->color); MEM_freeN(p->area); } BLI_freelistN(&points); /* build tree */ if (!re->test_break(re->tbh)) { SSSData *sss= MEM_callocN(sizeof(*sss), "SSSData"); float ior= mat->sss_ior, cfac= mat->sss_colfac; float *radius= mat->sss_radius; float fw= mat->sss_front, bw= mat->sss_back; float error = mat->sss_error; error= get_render_aosss_error(&re->r, error); if ((re->r.scemode & R_PREVIEWBUTS) && error < 0.5f) error= 0.5f; sss->ss[0]= scatter_settings_new(mat->sss_col[0], radius[0], ior, cfac, fw, bw); sss->ss[1]= scatter_settings_new(mat->sss_col[1], radius[1], ior, cfac, fw, bw); sss->ss[2]= scatter_settings_new(mat->sss_col[2], radius[2], ior, cfac, fw, bw); sss->tree= scatter_tree_new(sss->ss, mat->sss_scale, error, co, color, area, totpoint); MEM_freeN(co); MEM_freeN(color); MEM_freeN(area); scatter_tree_build(sss->tree); BLI_ghash_insert(re->sss_hash, mat, sss); } else { if (co) MEM_freeN(co); if (color) MEM_freeN(color); if (area) MEM_freeN(area); } }
/* Builds a bvh tree.. where nodes are the faces of the given dm. */ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis) { BMEditMesh *em = data->em_evil; const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_FACES; BVHTree *tree; MVert *vert; MFace *face; bool vert_allocated = false, face_allocated = false; BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); tree = bvhcache_find(&dm->bvhCache, bvhcache_type); BLI_rw_mutex_unlock(&cache_rwlock); if (em == NULL) { vert = DM_get_vert_array(dm, &vert_allocated); face = DM_get_tessface_array(dm, &face_allocated); } /* Not in cache */ if (tree == NULL) { BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); tree = bvhcache_find(&dm->bvhCache, bvhcache_type); if (tree == NULL) { int i; int numFaces; /* BMESH specific check that we have tessfaces, * we _could_ tessellate here but rather not - campbell * * this assert checks we have tessfaces, * if not caller should use DM_ensure_tessface() */ if (em) { numFaces = em->tottri; } else { numFaces = dm->getNumTessFaces(dm); BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0)); } if (numFaces != 0) { /* Create a bvh-tree of the given target */ // printf("%s: building BVH, total=%d\n", __func__, numFaces); tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis); if (tree != NULL) { if (em) { const struct BMLoop *(*looptris)[3] = (void *)em->looptris; /* avoid double-up on face searches for quads-ngons */ bool insert_prev = false; BMFace *f_prev = NULL; /* data->em_evil is only set for snapping, and only for the mesh of the object * which is currently open in edit mode. When set, the bvhtree should not contain * faces that will interfere with snapping (e.g. faces that are hidden/selected * or faces that have selected verts).*/ /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden * and/or selected. Even if the faces themselves are not selected for the snapped * transform, having a vertex selected means the face (and thus it's tessellated * triangles) will be moving and will not be a good snap targets.*/ for (i = 0; i < em->tottri; i++) { const BMLoop **ltri = looptris[i]; BMFace *f = ltri[0]->f; bool insert; /* Start with the assumption the triangle should be included for snapping. */ if (f == f_prev) { insert = insert_prev; } else { if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { /* Don't insert triangles tessellated from faces that are hidden * or selected*/ insert = false; } else { BMLoop *l_iter, *l_first; insert = true; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { /* Don't insert triangles tessellated from faces that have * any selected verts.*/ insert = false; break; } } while ((l_iter = l_iter->next) != l_first); } /* skip if face doesn't change */ f_prev = f; insert_prev = insert; } if (insert) { /* No reason found to block hit-testing the triangle for snap, * so insert it now.*/ float co[3][3]; copy_v3_v3(co[0], ltri[0]->v->co); copy_v3_v3(co[1], ltri[1]->v->co); copy_v3_v3(co[2], ltri[2]->v->co); BLI_bvhtree_insert(tree, i, co[0], 3); } } } else { if (vert != NULL && face != NULL) { for (i = 0; i < numFaces; i++) { float co[4][3]; copy_v3_v3(co[0], vert[face[i].v1].co); copy_v3_v3(co[1], vert[face[i].v2].co); copy_v3_v3(co[2], vert[face[i].v3].co); if (face[i].v4) copy_v3_v3(co[3], vert[face[i].v4].co); BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3); } } } BLI_bvhtree_balance(tree); /* Save on cache for later use */ // printf("BVHTree built and saved on cache\n"); bvhcache_insert(&dm->bvhCache, tree, bvhcache_type); } } } BLI_rw_mutex_unlock(&cache_rwlock); } else { // printf("BVHTree is already build, using cached tree\n"); } /* Setup BVHTreeFromMesh */ memset(data, 0, sizeof(*data)); data->tree = tree; data->em_evil = em; if (data->tree) { data->cached = true; if (em) { data->nearest_callback = editmesh_faces_nearest_point; data->raycast_callback = editmesh_faces_spherecast; } else { data->nearest_callback = mesh_faces_nearest_point; data->raycast_callback = mesh_faces_spherecast; data->vert = vert; data->vert_allocated = vert_allocated; data->face = face; data->face_allocated = face_allocated; } data->sphere_radius = epsilon; } else { if (vert_allocated) { MEM_freeN(vert); } if (face_allocated) { MEM_freeN(face); } } return data->tree; }
void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float v) { int i0, i1, j0, j1; float frac_x, frac_z; float uu, vv; /* first wrap the texture so 0 <= (u, v) < 1 */ u = fmodf(u, 1.0f); v = fmodf(v, 1.0f); if (u < 0) u += 1.0f; if (v < 0) v += 1.0f; BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ); uu = u * oc->_M; vv = v * oc->_N; i0 = (int)floor(uu); j0 = (int)floor(vv); i1 = (i0 + 1); j1 = (j0 + 1); frac_x = uu - i0; frac_z = vv - j0; i0 = i0 % oc->_M; j0 = j0 % oc->_N; i1 = i1 % oc->_M; j1 = j1 % oc->_N; #define BILERP(m) (interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \ interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \ frac_z)) { if (oc->_do_disp_y) { ocr->disp[1] = BILERP(oc->_disp_y); } if (oc->_do_normals) { ocr->normal[0] = BILERP(oc->_N_x); ocr->normal[1] = oc->_N_y /*BILERP(oc->_N_y) (MEM01)*/; ocr->normal[2] = BILERP(oc->_N_z); } if (oc->_do_chop) { ocr->disp[0] = BILERP(oc->_disp_x); ocr->disp[2] = BILERP(oc->_disp_z); } else { ocr->disp[0] = 0.0; ocr->disp[2] = 0.0; } if (oc->_do_jacobian) { compute_eigenstuff(ocr, BILERP(oc->_Jxx), BILERP(oc->_Jzz), BILERP(oc->_Jxz)); } } #undef BILERP BLI_rw_mutex_unlock(&oc->oceanmutex); }
/* use catmullrom interpolation rather than linear */ void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u, float v) { int i0, i1, i2, i3, j0, j1, j2, j3; float frac_x, frac_z; float uu, vv; /* first wrap the texture so 0 <= (u, v) < 1 */ u = fmod(u, 1.0f); v = fmod(v, 1.0f); if (u < 0) u += 1.0f; if (v < 0) v += 1.0f; BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ); uu = u * oc->_M; vv = v * oc->_N; i1 = (int)floor(uu); j1 = (int)floor(vv); i2 = (i1 + 1); j2 = (j1 + 1); frac_x = uu - i1; frac_z = vv - j1; i1 = i1 % oc->_M; j1 = j1 % oc->_N; i2 = i2 % oc->_M; j2 = j2 % oc->_N; i0 = (i1 - 1); i3 = (i2 + 1); i0 = i0 < 0 ? i0 + oc->_M : i0; i3 = i3 >= oc->_M ? i3 - oc->_M : i3; j0 = (j1 - 1); j3 = (j2 + 1); j0 = j0 < 0 ? j0 + oc->_N : j0; j3 = j3 >= oc->_N ? j3 - oc->_N : j3; #define INTERP(m) catrom(catrom(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], \ m[i2 * oc->_N + j0], m[i3 * oc->_N + j0], frac_x), \ catrom(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], \ m[i2 * oc->_N + j1], m[i3 * oc->_N + j1], frac_x), \ catrom(m[i0 * oc->_N + j2], m[i1 * oc->_N + j2], \ m[i2 * oc->_N + j2], m[i3 * oc->_N + j2], frac_x), \ catrom(m[i0 * oc->_N + j3], m[i1 * oc->_N + j3], \ m[i2 * oc->_N + j3], m[i3 * oc->_N + j3], frac_x), \ frac_z) { if (oc->_do_disp_y) { ocr->disp[1] = INTERP(oc->_disp_y); } if (oc->_do_normals) { ocr->normal[0] = INTERP(oc->_N_x); ocr->normal[1] = oc->_N_y /*INTERP(oc->_N_y) (MEM01)*/; ocr->normal[2] = INTERP(oc->_N_z); } if (oc->_do_chop) { ocr->disp[0] = INTERP(oc->_disp_x); ocr->disp[2] = INTERP(oc->_disp_z); } else { ocr->disp[0] = 0.0; ocr->disp[2] = 0.0; } if (oc->_do_jacobian) { compute_eigenstuff(ocr, INTERP(oc->_Jxx), INTERP(oc->_Jzz), INTERP(oc->_Jxz)); } } #undef INTERP BLI_rw_mutex_unlock(&oc->oceanmutex); }
void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount) { int i, j; scale *= o->normalize_factor; BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); /* compute a new htilda */ #pragma omp parallel for private(i, j) for (i = 0; i < o->_M; ++i) { /* note the <= _N/2 here, see the fftw doco about the mechanics of the complex->real fft storage */ for (j = 0; j <= o->_N / 2; ++j) { fftw_complex exp_param1; fftw_complex exp_param2; fftw_complex conj_param; init_complex(exp_param1, 0.0, omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t); init_complex(exp_param2, 0.0, -omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t); exp_complex(exp_param1, exp_param1); exp_complex(exp_param2, exp_param2); conj_complex(conj_param, o->_h0_minus[i * o->_N + j]); mul_complex_c(exp_param1, o->_h0[i * o->_N + j], exp_param1); mul_complex_c(exp_param2, conj_param, exp_param2); add_comlex_c(o->_htilda[i * (1 + o->_N / 2) + j], exp_param1, exp_param2); mul_complex_f(o->_fft_in[i * (1 + o->_N / 2) + j], o->_htilda[i * (1 + o->_N / 2) + j], scale); } } #pragma omp parallel sections private(i, j) { #pragma omp section { if (o->_do_disp_y) { /* y displacement */ fftw_execute(o->_disp_y_plan); } } /* section 1 */ #pragma omp section { if (o->_do_chop) { /* x displacement */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; fftw_complex minus_i; init_complex(minus_i, 0.0, -1.0); init_complex(mul_param, -scale, 0); mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, minus_i); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); mul_complex_f(mul_param, mul_param, ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ? 0.0f : o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } fftw_execute(o->_disp_x_plan); } } /* section 2 */ #pragma omp section { if (o->_do_chop) { /* z displacement */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; fftw_complex minus_i; init_complex(minus_i, 0.0, -1.0); init_complex(mul_param, -scale, 0); mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, minus_i); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); mul_complex_f(mul_param, mul_param, ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ? 0.0f : o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } fftw_execute(o->_disp_z_plan); } } /* section 3 */ #pragma omp section { if (o->_do_jacobian) { /* Jxx */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; /* init_complex(mul_param, -scale, 0); */ init_complex(mul_param, -1, 0); mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); mul_complex_f(mul_param, mul_param, ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ? 0.0f : o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } fftw_execute(o->_Jxx_plan); for (i = 0; i < o->_M; ++i) { for (j = 0; j < o->_N; ++j) { o->_Jxx[i * o->_N + j] += 1.0; } } } } /* section 4 */ #pragma omp section { if (o->_do_jacobian) { /* Jzz */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; /* init_complex(mul_param, -scale, 0); */ init_complex(mul_param, -1, 0); mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); mul_complex_f(mul_param, mul_param, ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ? 0.0f : o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } fftw_execute(o->_Jzz_plan); for (i = 0; i < o->_M; ++i) { for (j = 0; j < o->_N; ++j) { o->_Jzz[i * o->_N + j] += 1.0; } } } } /* section 5 */ #pragma omp section { if (o->_do_jacobian) { /* Jxz */ for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; /* init_complex(mul_param, -scale, 0); */ init_complex(mul_param, -1, 0); mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); mul_complex_f(mul_param, mul_param, ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ? 0.0f : o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jxz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } fftw_execute(o->_Jxz_plan); } } /* section 6 */ #pragma omp section { /* fft normals */ if (o->_do_normals) { for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; init_complex(mul_param, 0.0, -1.0); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); mul_complex_f(mul_param, mul_param, o->_kx[i]); init_complex(o->_fft_in_nx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } fftw_execute(o->_N_x_plan); } } /* section 7 */ #pragma omp section { if (o->_do_normals) { for (i = 0; i < o->_M; ++i) { for (j = 0; j <= o->_N / 2; ++j) { fftw_complex mul_param; init_complex(mul_param, 0.0, -1.0); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); mul_complex_f(mul_param, mul_param, o->_kz[i]); init_complex(o->_fft_in_nz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } fftw_execute(o->_N_z_plan); #if 0 for (i = 0; i < o->_M; ++i) { for (j = 0; j < o->_N; ++j) { o->_N_y[i * o->_N + j] = 1.0f / scale; } } (MEM01) #endif o->_N_y = 1.0f / scale; } } /* section 8 */ } /* omp sections */ BLI_rw_mutex_unlock(&o->oceanmutex); }
void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, float l, float A, float w, float damp, float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals, short do_jacobian, int seed) { int i, j, ii; BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); o->_M = M; o->_N = N; o->_V = V; o->_l = l; o->_A = A; o->_w = w; o->_damp_reflections = 1.0f - damp; o->_wind_alignment = alignment; o->_depth = depth; o->_Lx = Lx; o->_Lz = Lz; o->_wx = cos(w); o->_wz = -sin(w); /* wave direction */ o->_L = V * V / GRAVITY; /* largest wave for a given velocity V */ o->time = time; o->_do_disp_y = do_height_field; o->_do_normals = do_normals; o->_do_chop = do_chop; o->_do_jacobian = do_jacobian; o->_k = (float *) MEM_mallocN(M * (1 + N / 2) * sizeof(float), "ocean_k"); o->_h0 = (fftw_complex *) MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0"); o->_h0_minus = (fftw_complex *) MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0_minus"); o->_kx = (float *) MEM_mallocN(o->_M * sizeof(float), "ocean_kx"); o->_kz = (float *) MEM_mallocN(o->_N * sizeof(float), "ocean_kz"); /* make this robust in the face of erroneous usage */ if (o->_Lx == 0.0f) o->_Lx = 0.001f; if (o->_Lz == 0.0f) o->_Lz = 0.001f; /* the +ve components and DC */ for (i = 0; i <= o->_M / 2; ++i) o->_kx[i] = 2.0f * (float)M_PI * i / o->_Lx; /* the -ve components */ for (i = o->_M - 1, ii = 0; i > o->_M / 2; --i, ++ii) o->_kx[i] = -2.0f * (float)M_PI * ii / o->_Lx; /* the +ve components and DC */ for (i = 0; i <= o->_N / 2; ++i) o->_kz[i] = 2.0f * (float)M_PI * i / o->_Lz; /* the -ve components */ for (i = o->_N - 1, ii = 0; i > o->_N / 2; --i, ++ii) o->_kz[i] = -2.0f * (float)M_PI * ii / o->_Lz; /* pre-calculate the k matrix */ for (i = 0; i < o->_M; ++i) for (j = 0; j <= o->_N / 2; ++j) o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]); /*srand(seed);*/ BLI_srand(seed); for (i = 0; i < o->_M; ++i) { for (j = 0; j < o->_N; ++j) { float r1 = gaussRand(); float r2 = gaussRand(); fftw_complex r1r2; init_complex(r1r2, r1, r2); mul_complex_f(o->_h0[i * o->_N + j], r1r2, (float)(sqrt(Ph(o, o->_kx[i], o->_kz[j]) / 2.0f))); mul_complex_f(o->_h0_minus[i * o->_N + j], r1r2, (float)(sqrt(Ph(o, -o->_kx[i], -o->_kz[j]) / 2.0f))); } } o->_fft_in = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in"); o->_htilda = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda"); if (o->_do_disp_y) { o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y"); o->_disp_y_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in, o->_disp_y, FFTW_ESTIMATE); } if (o->_do_normals) { o->_fft_in_nx = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_nx"); o->_fft_in_nz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_nz"); o->_N_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x"); /* o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01) */ o->_N_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z"); o->_N_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nx, o->_N_x, FFTW_ESTIMATE); o->_N_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nz, o->_N_z, FFTW_ESTIMATE); } if (o->_do_chop) { o->_fft_in_x = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_x"); o->_fft_in_z = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_z"); o->_disp_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x"); o->_disp_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z"); o->_disp_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_x, o->_disp_x, FFTW_ESTIMATE); o->_disp_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_z, o->_disp_z, FFTW_ESTIMATE); } if (o->_do_jacobian) { o->_fft_in_jxx = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jxx"); o->_fft_in_jzz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jzz"); o->_fft_in_jxz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jxz"); o->_Jxx = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx"); o->_Jzz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz"); o->_Jxz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz"); o->_Jxx_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxx, o->_Jxx, FFTW_ESTIMATE); o->_Jzz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jzz, o->_Jzz, FFTW_ESTIMATE); o->_Jxz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxz, o->_Jxz, FFTW_ESTIMATE); } BLI_rw_mutex_unlock(&o->oceanmutex); set_height_normalize_factor(o); }
bool RE_bake_engine( Render *re, Object *object, const BakePixel pixel_array[], const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]) { RenderEngineType *type = RE_engines_find(re->r.engine); RenderEngine *engine; bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0; /* set render info */ re->i.cfra = re->scene->r.cfra; BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2); re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0; /* render */ engine = re->engine; if (!engine) { engine = RE_engine_create(type); re->engine = engine; } engine->flag |= RE_ENGINE_RENDERING; /* TODO: actually link to a parent which shouldn't happen */ engine->re = re; engine->resolution_x = re->winx; engine->resolution_y = re->winy; RE_parts_init(re, false); engine->tile_x = re->r.tilex; engine->tile_y = re->r.tiley; /* update is only called so we create the engine.session */ if (type->update) type->update(engine, re->main, re->scene); if (type->bake) type->bake(engine, re->scene, object, pass_type, pixel_array, num_pixels, depth, result); engine->tile_x = 0; engine->tile_y = 0; engine->flag &= ~RE_ENGINE_RENDERING; BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); /* re->engine becomes zero if user changed active render engine during render */ if (!persistent_data || !re->engine) { RE_engine_free(engine); re->engine = NULL; } RE_parts_free(re); BLI_rw_mutex_unlock(&re->partsmutex); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = true; return true; }
int RE_engine_render(Render *re, int do_all) { RenderEngineType *type = RE_engines_find(re->r.engine); RenderEngine *engine; bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0; /* verify if we can render */ if (!type->render) return 0; if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW)) return 0; if (do_all && !(type->flag & RE_USE_POSTPROCESS)) return 0; if (!do_all && (type->flag & RE_USE_POSTPROCESS)) return 0; /* Lock drawing in UI during data phase. */ if (re->draw_lock) { re->draw_lock(re->dlh, 1); } /* update animation here so any render layer animation is applied before * creating the render result */ if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) { unsigned int lay = re->lay; /* don't update layers excluded on all render layers */ if (type->flag & RE_USE_EXCLUDE_LAYERS) { SceneRenderLayer *srl; unsigned int non_excluded_lay = 0; if (re->r.scemode & R_SINGLE_LAYER) { srl = BLI_findlink(&re->r.layers, re->r.actlay); if (srl) { non_excluded_lay |= ~srl->lay_exclude; /* in this case we must update all because animation for * the scene has not been updated yet, and so may not be * up to date until after BKE_scene_update_for_newframe */ if (render_layer_exclude_animated(re->scene, srl)) non_excluded_lay |= ~0; } } else { for (srl = re->r.layers.first; srl; srl = srl->next) { if (!(srl->layflag & SCE_LAY_DISABLE)) { non_excluded_lay |= ~srl->lay_exclude; if (render_layer_exclude_animated(re->scene, srl)) non_excluded_lay |= ~0; } } } lay &= non_excluded_lay; } BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, re->scene, lay, true); render_update_anim_renderdata(re, &re->scene->r); } /* create render result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) { int savebuffers = RR_USE_MEM; if (re->result) render_result_free(re->result); if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE)) savebuffers = RR_USE_EXR; re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS); } BLI_rw_mutex_unlock(&re->resultmutex); if (re->result == NULL) { /* Clear UI drawing locks. */ if (re->draw_lock) { re->draw_lock(re->dlh, 0); } return 1; } /* set render info */ re->i.cfra = re->scene->r.cfra; BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name)); re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0; /* render */ engine = re->engine; if (!engine) { engine = RE_engine_create(type); re->engine = engine; } engine->flag |= RE_ENGINE_RENDERING; /* TODO: actually link to a parent which shouldn't happen */ engine->re = re; if (re->flag & R_ANIMATION) engine->flag |= RE_ENGINE_ANIMATION; if (re->r.scemode & R_BUTS_PREVIEW) engine->flag |= RE_ENGINE_PREVIEW; engine->camera_override = re->camera_override; engine->layer_override = re->layer_override; engine->resolution_x = re->winx; engine->resolution_y = re->winy; RE_parts_init(re, false); engine->tile_x = re->partx; engine->tile_y = re->party; if (re->result->do_exr_tile) render_result_exr_file_begin(re); if (type->update) type->update(engine, re->main, re->scene); /* Clear UI drawing locks. */ if (re->draw_lock) { re->draw_lock(re->dlh, 0); } if (type->render) type->render(engine, re->scene); engine->tile_x = 0; engine->tile_y = 0; engine->flag &= ~RE_ENGINE_RENDERING; render_result_free_list(&engine->fullresult, engine->fullresult.first); BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); /* re->engine becomes zero if user changed active render engine during render */ if (!persistent_data || !re->engine) { RE_engine_free(engine); re->engine = NULL; } if (re->result->do_exr_tile) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_exr_file_end(re); BLI_rw_mutex_unlock(&re->resultmutex); } if (re->r.scemode & R_EXR_CACHE_FILE) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_exr_file_cache_write(re); BLI_rw_mutex_unlock(&re->resultmutex); } RE_parts_free(re); BLI_rw_mutex_unlock(&re->partsmutex); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = true; #ifdef WITH_FREESTYLE if (re->r.mode & R_EDGE_FRS) RE_RenderFreestyleExternal(re); #endif return 1; }
static void init_frame_smoke(VoxelData *vd, int cfra) { #ifdef WITH_SMOKE Object *ob; ModifierData *md; vd->dataset = NULL; if (vd->object == NULL) return; ob = vd->object; /* draw code for smoke */ if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_Smoke))) { SmokeModifierData *smd = (SmokeModifierData *)md; SmokeDomainSettings *sds = smd->domain; if (sds && sds->fluid) { BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); if (!sds->fluid) { BLI_rw_mutex_unlock(sds->fluid_mutex); return; } if (cfra < sds->point_cache[0]->startframe) ; /* don't show smoke before simulation starts, this could be made an option in the future */ else if (vd->smoked_type == TEX_VD_SMOKEHEAT) { size_t totRes; size_t i; float *heat; if (!smoke_has_heat(sds->fluid)) { BLI_rw_mutex_unlock(sds->fluid_mutex); return; } copy_v3_v3_int(vd->resol, sds->res); totRes = vd_resol_size(vd); vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data"); /* get heat data */ heat = smoke_get_heat(sds->fluid); /* scale heat values from -2.0-2.0 to 0.0-1.0 */ for (i = 0; i < totRes; i++) { vd->dataset[i] = (heat[i] + 2.0f) / 4.0f; } } else if (vd->smoked_type == TEX_VD_SMOKEVEL) { size_t totRes; size_t i; float *xvel, *yvel, *zvel; copy_v3_v3_int(vd->resol, sds->res); totRes = vd_resol_size(vd); vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data"); /* get velocity data */ xvel = smoke_get_velocity_x(sds->fluid); yvel = smoke_get_velocity_y(sds->fluid); zvel = smoke_get_velocity_z(sds->fluid); /* map velocities between 0 and 0.3f */ for (i = 0; i < totRes; i++) { vd->dataset[i] = sqrtf(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f; } } else if (vd->smoked_type == TEX_VD_SMOKEFLAME) { size_t totRes; float *flame; if (sds->flags & MOD_SMOKE_HIGHRES) { if (!smoke_turbulence_has_fuel(sds->wt)) { BLI_rw_mutex_unlock(sds->fluid_mutex); return; } smoke_turbulence_get_res(sds->wt, vd->resol); flame = smoke_turbulence_get_flame(sds->wt); } else { if (!smoke_has_fuel(sds->fluid)) { BLI_rw_mutex_unlock(sds->fluid_mutex); return; } copy_v3_v3_int(vd->resol, sds->res); flame = smoke_get_flame(sds->fluid); } /* always store copy, as smoke internal data can change */ totRes = vd_resol_size(vd); vd->dataset = MEM_mapallocN(sizeof(float)*(totRes), "smoke data"); memcpy(vd->dataset, flame, sizeof(float)*totRes); } else { size_t totCells; int depth = 4; vd->data_type = TEX_VD_RGBA_PREMUL; /* data resolution */ if (sds->flags & MOD_SMOKE_HIGHRES) { smoke_turbulence_get_res(sds->wt, vd->resol); } else { copy_v3_v3_int(vd->resol, sds->res); } /* TODO: is_vd_res_ok(rvd) doesnt check this resolution */ totCells = vd_resol_size(vd) * depth; /* always store copy, as smoke internal data can change */ vd->dataset = MEM_mapallocN(sizeof(float) * totCells, "smoke data"); if (sds->flags & MOD_SMOKE_HIGHRES) { if (smoke_turbulence_has_colors(sds->wt)) { smoke_turbulence_get_rgba(sds->wt, vd->dataset, 1); } else { smoke_turbulence_get_rgba_from_density(sds->wt, sds->active_color, vd->dataset, 1); } } else { if (smoke_has_colors(sds->fluid)) { smoke_get_rgba(sds->fluid, vd->dataset, 1); } else { smoke_get_rgba_from_density(sds->fluid, sds->active_color, vd->dataset, 1); } } } /* end of fluid condition */ BLI_rw_mutex_unlock(sds->fluid_mutex); } } vd->ok = 1; #else // WITH_SMOKE (void)vd; (void)cfra; vd->dataset = NULL; #endif }