[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [56665] trunk/blender: Smoke: Add new " Full Sample" option to high resolution smoke panel.
Miika Hamalainen
blender at miikah.org
Fri May 10 18:18:01 CEST 2013
Revision: 56665
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=56665
Author: miikah
Date: 2013-05-10 16:18:00 +0000 (Fri, 10 May 2013)
Log Message:
-----------
Smoke: Add new "Full Sample" option to high resolution smoke panel.
This is hopefully the ultimate solution against smoke blockiness near emitter.
Previously high resolution flow/emitter voxels were generated based on the low resolution ones. So if you had 32 resolution and 4 division high resolution, it still used smoke flow generated from those 32 resolution voxels. Now I introduced a new sampling method called "Full Sample" that generates full resolution flow for for high resolution domain as well.
Read more about it in my blog post: https://www.miikahweb.com/en/blog/2013/05/10/getting-rid-of-smoke-blockiness
Also changed "quick smoke" operator default voxel data interpolation mode to "Cubic B-Spline" to smoothen out it even more.
Modified Paths:
--------------
trunk/blender/release/scripts/startup/bl_operators/object_quick_effects.py
trunk/blender/release/scripts/startup/bl_ui/properties_physics_smoke.py
trunk/blender/source/blender/blenkernel/BKE_blender.h
trunk/blender/source/blender/blenkernel/intern/smoke.c
trunk/blender/source/blender/blenloader/intern/readfile.c
trunk/blender/source/blender/makesdna/DNA_smoke_types.h
trunk/blender/source/blender/makesrna/intern/rna_smoke.c
Modified: trunk/blender/release/scripts/startup/bl_operators/object_quick_effects.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_operators/object_quick_effects.py 2013-05-10 15:56:32 UTC (rev 56664)
+++ trunk/blender/release/scripts/startup/bl_operators/object_quick_effects.py 2013-05-10 16:18:00 UTC (rev 56665)
@@ -363,6 +363,7 @@
tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
tex.voxel_data.domain_object = obj
+ tex.voxel_data.interpolation = 'TRICUBIC_BSPLINE'
tex_slot = mat.texture_slots.add()
tex_slot.texture = tex
@@ -375,6 +376,7 @@
tex = bpy.data.textures.new("Flame", 'VOXEL_DATA')
tex.voxel_data.domain_object = obj
tex.voxel_data.smoke_data_type = 'SMOKEFLAME'
+ tex.voxel_data.interpolation = 'TRICUBIC_BSPLINE'
tex.use_color_ramp = True
tex_slot = mat.texture_slots.add()
Modified: trunk/blender/release/scripts/startup/bl_ui/properties_physics_smoke.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/properties_physics_smoke.py 2013-05-10 15:56:32 UTC (rev 56664)
+++ trunk/blender/release/scripts/startup/bl_ui/properties_physics_smoke.py 2013-05-10 16:18:00 UTC (rev 56665)
@@ -244,7 +244,8 @@
col = split.column()
col.label(text="Resolution:")
col.prop(md, "amplify", text="Divisions")
- col.prop(md, "use_smooth_emitter")
+ col.label(text="Flow Sampling:")
+ col.row().prop(md, "highres_sampling", text="")
col = split.column()
col.label(text="Noise Method:")
Modified: trunk/blender/source/blender/blenkernel/BKE_blender.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_blender.h 2013-05-10 15:56:32 UTC (rev 56664)
+++ trunk/blender/source/blender/blenkernel/BKE_blender.h 2013-05-10 16:18:00 UTC (rev 56665)
@@ -42,7 +42,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 267
-#define BLENDER_SUBVERSION 0
+#define BLENDER_SUBVERSION 1
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
Modified: trunk/blender/source/blender/blenkernel/intern/smoke.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/smoke.c 2013-05-10 15:56:32 UTC (rev 56664)
+++ trunk/blender/source/blender/blenkernel/intern/smoke.c 2013-05-10 16:18:00 UTC (rev 56665)
@@ -525,6 +525,7 @@
smd->domain->vorticity = 2.0;
smd->domain->border_collisions = SM_BORDER_OPEN; // open domain
smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG | MOD_SMOKE_HIGH_SMOOTH;
+ smd->domain->highres_sampling = SM_HRES_FULLSAMPLE;
smd->domain->strength = 2.0;
smd->domain->noise = MOD_SMOKE_NOISEWAVE;
smd->domain->diss_speed = 5;
@@ -899,6 +900,7 @@
typedef struct EmissionMap {
float *influence;
+ float *influence_high;
float *velocity;
int min[3], max[3], res[3];
int total_cells, valid;
@@ -908,8 +910,10 @@
{
int i = 0;
if (!em->valid) {
- VECCOPY(em->min, point);
- VECCOPY(em->max, point);
+ for (; i < 3; i++) {
+ em->min[i] = (int)floor(point[i]);
+ em->max[i] = (int)ceil(point[i]);
+ }
em->valid = 1;
}
else {
@@ -943,7 +947,7 @@
}
}
-static void em_allocateData(EmissionMap *em, int use_velocity)
+static void em_allocateData(EmissionMap *em, int use_velocity, int hires_mul)
{
int i, res[3];
@@ -959,12 +963,20 @@
em->influence = MEM_callocN(sizeof(float) * em->total_cells, "smoke_flow_influence");
if (use_velocity)
em->velocity = MEM_callocN(sizeof(float) * em->total_cells * 3, "smoke_flow_velocity");
+
+ /* allocate high resolution map if required */
+ if (hires_mul > 1) {
+ int total_cells_high = em->total_cells * (hires_mul * hires_mul * hires_mul);
+ em->influence_high = MEM_callocN(sizeof(float) * total_cells_high, "smoke_flow_influence_high");
+ }
}
static void em_freeData(EmissionMap *em)
{
if (em->influence)
MEM_freeN(em->influence);
+ if (em->influence_high)
+ MEM_freeN(em->influence_high);
if (em->velocity)
MEM_freeN(em->velocity);
}
@@ -1034,7 +1046,7 @@
/* set emission map */
clampBoundsInDomain(sds, em->min, em->max, NULL, NULL, 1, dt);
- em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY);
+ em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY, 0);
for (p = 0; p < valid_particles; p++)
{
@@ -1096,6 +1108,131 @@
}
}
+static void sample_derived_mesh(SmokeFlowSettings *sfs, MVert *mvert, MTFace *tface, MFace *mface, float *influence_map, float *velocity_map, int index, int base_res[3], float flow_center[3], BVHTreeFromMesh *treeData, float ray_start[3],
+ float *vert_vel, int has_velocity, int defgrp_index, MDeformVert *dvert, float x, float y, float z)
+{
+ float ray_dir[3] = {1.0f, 0.0f, 0.0f};
+ BVHTreeRayHit hit = {0};
+ BVHTreeNearest nearest = {0};
+
+ float volume_factor = 0.0f;
+ float sample_str = 0.0f;
+
+ hit.index = -1;
+ hit.dist = 9999;
+ nearest.index = -1;
+ nearest.dist = sfs->surface_distance * sfs->surface_distance; /* find_nearest uses squared distance */
+
+ /* Check volume collision */
+ if (sfs->volume_density) {
+ if (BLI_bvhtree_ray_cast(treeData->tree, ray_start, ray_dir, 0.0f, &hit, treeData->raycast_callback, treeData) != -1) {
+ float dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2];
+ /* If ray and hit face normal are facing same direction
+ * hit point is inside a closed mesh. */
+ if (dot >= 0) {
+ /* Also cast a ray in opposite direction to make sure
+ * point is at least surrounded by two faces */
+ negate_v3(ray_dir);
+ hit.index = -1;
+ hit.dist = 9999;
+
+ BLI_bvhtree_ray_cast(treeData->tree, ray_start, ray_dir, 0.0f, &hit, treeData->raycast_callback, treeData);
+ if (hit.index != -1) {
+ volume_factor = sfs->volume_density;
+ }
+ }
+ }
+ }
+
+ /* find the nearest point on the mesh */
+ if (BLI_bvhtree_find_nearest(treeData->tree, ray_start, &nearest, treeData->nearest_callback, treeData) != -1) {
+ float weights[4];
+ int v1, v2, v3, f_index = nearest.index;
+ float n1[3], n2[3], n3[3], hit_normal[3];
+
+ /* emit from surface based on distance */
+ if (sfs->surface_distance) {
+ sample_str = sqrtf(nearest.dist) / sfs->surface_distance;
+ CLAMP(sample_str, 0.0f, 1.0f);
+ sample_str = pow(1.0f - sample_str, 0.5f);
+ }
+ else
+ sample_str = 0.0f;
+
+ /* calculate barycentric weights for nearest point */
+ v1 = mface[f_index].v1;
+ v2 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v3 : mface[f_index].v2;
+ v3 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v4 : mface[f_index].v3;
+ interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co);
+
+ if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && velocity_map) {
+ /* apply normal directional velocity */
+ if (sfs->vel_normal) {
+ /* interpolate vertex normal vectors to get nearest point normal */
+ normal_short_to_float_v3(n1, mvert[v1].no);
+ normal_short_to_float_v3(n2, mvert[v2].no);
+ normal_short_to_float_v3(n3, mvert[v3].no);
+ interp_v3_v3v3v3(hit_normal, n1, n2, n3, weights);
+ normalize_v3(hit_normal);
+ /* apply normal directional and random velocity
+ * - TODO: random disabled for now since it doesnt really work well as pressure calc smoothens it out... */
+ velocity_map[index * 3] += hit_normal[0] * sfs->vel_normal * 0.25f;
+ velocity_map[index * 3 + 1] += hit_normal[1] * sfs->vel_normal * 0.25f;
+ velocity_map[index * 3 + 2] += hit_normal[2] * sfs->vel_normal * 0.25f;
+ /* TODO: for fire emitted from mesh surface we can use
+ * Vf = Vs + (Ps/Pf - 1)*S to model gaseous expansion from solid to fuel */
+ }
+ /* apply object velocity */
+ if (has_velocity && sfs->vel_multi) {
+ float hit_vel[3];
+ interp_v3_v3v3v3(hit_vel, &vert_vel[v1 * 3], &vert_vel[v2 * 3], &vert_vel[v3 * 3], weights);
+ velocity_map[index * 3] += hit_vel[0] * sfs->vel_multi;
+ velocity_map[index * 3 + 1] += hit_vel[1] * sfs->vel_multi;
+ velocity_map[index * 3 + 2] += hit_vel[2] * sfs->vel_multi;
+ }
+ }
+
+ /* apply vertex group influence if used */
+ if (defgrp_index != -1 && dvert) {
+ float weight_mask = defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] +
+ defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] +
+ defvert_find_weight(&dvert[v3], defgrp_index) * weights[2];
+ sample_str *= weight_mask;
+ }
+
+ /* apply emission texture */
+ if ((sfs->flags & MOD_SMOKE_FLOW_TEXTUREEMIT) && sfs->noise_texture) {
+ float tex_co[3] = {0};
+ TexResult texres;
+
+ if (sfs->texture_type == MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO) {
+ tex_co[0] = ((x - flow_center[0]) / base_res[0]) / sfs->texture_size;
+ tex_co[1] = ((y - flow_center[1]) / base_res[1]) / sfs->texture_size;
+ tex_co[2] = ((z - flow_center[2]) / base_res[2] - sfs->texture_offset) / sfs->texture_size;
+ }
+ else if (tface) {
+ interp_v2_v2v2v2(tex_co, tface[f_index].uv[0], tface[f_index].uv[(nearest.flags & BVH_ONQUAD) ? 2 : 1],
+ tface[f_index].uv[(nearest.flags & BVH_ONQUAD) ? 3 : 2], weights);
+ /* map between -1.0f and 1.0f */
+ tex_co[0] = tex_co[0] * 2.0f - 1.0f;
+ tex_co[1] = tex_co[1] * 2.0f - 1.0f;
+ tex_co[2] = sfs->texture_offset;
+ }
+ texres.nor = NULL;
+ get_texture_value(sfs->noise_texture, tex_co, &texres);
+ sample_str *= texres.tin;
+ }
+ }
+
+ /* multiply initial velocity by emitter influence */
+ if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && velocity_map) {
+ mul_v3_fl(&velocity_map[index * 3], sample_str);
+ }
+
+ /* apply final influence based on volume factor */
+ influence_map[index] = MAX2(volume_factor, sample_str);
+}
+
static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, float dt)
{
if (!sfs->dm) return;
@@ -1113,6 +1250,8 @@
float *vert_vel = NULL;
int has_velocity = 0;
+ float min[3], max[3], res[3];
+ int hires_multiplier = 1;
CDDM_calc_normals(dm);
mvert = dm->getVertArray(dm);
@@ -1165,141 +1304,57 @@
mul_m4_v3(flow_ob->obmat, flow_center);
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list