From 4446acbf17748f30b163016cfc4b88bba8653517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dietrich?= Date: Sat, 24 Sep 2016 21:41:16 +0200 Subject: Viewport smoke: add support for axis aligned slicing. Current approach uses view aligned slicing to generate polygons for GL texturing such that the generated polygons are always facing the view plane. Now it is also possible to use object aligned slicing, which creates polygons by slicing the object perpendicular to whichever axis is facing the most the view plane. It is also possible to create a single slice for inspecting the volume, or for 2D rendering effects. Settings for this, along with a density multiplier setting, are to be found in a newly added "Smoke Display Settings" panel in the smoke domain properties tab. Reviewers: plasmasolutions, gottfried Differential Revision: https://developer.blender.org/D1733 --- source/blender/editors/space_view3d/drawvolume.c | 95 +++++++++++++++++++++++- 1 file changed, 92 insertions(+), 3 deletions(-) (limited to 'source/blender/editors/space_view3d/drawvolume.c') diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 06677ef4476..d743e7c09e7 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -113,6 +113,63 @@ typedef struct VolumeSlicer { float (*verts)[3]; } VolumeSlicer; +/* *************************** Axis Aligned Slicing ************************** */ + +static void create_single_slice(VolumeSlicer *slicer, const float depth, + const int axis, const int idx) +{ + const float vertices[3][4][3] = { + { + { depth, slicer->min[1], slicer->min[2] }, + { depth, slicer->max[1], slicer->min[2] }, + { depth, slicer->max[1], slicer->max[2] }, + { depth, slicer->min[1], slicer->max[2] } + }, + { + { slicer->min[0], depth, slicer->min[2] }, + { slicer->min[0], depth, slicer->max[2] }, + { slicer->max[0], depth, slicer->max[2] }, + { slicer->max[0], depth, slicer->min[2] } + }, + { + { slicer->min[0], slicer->min[1], depth }, + { slicer->min[0], slicer->max[1], depth }, + { slicer->max[0], slicer->max[1], depth }, + { slicer->max[0], slicer->min[1], depth } + } + }; + + copy_v3_v3(slicer->verts[idx + 0], vertices[axis][0]); + copy_v3_v3(slicer->verts[idx + 1], vertices[axis][1]); + copy_v3_v3(slicer->verts[idx + 2], vertices[axis][2]); + copy_v3_v3(slicer->verts[idx + 3], vertices[axis][0]); + copy_v3_v3(slicer->verts[idx + 4], vertices[axis][2]); + copy_v3_v3(slicer->verts[idx + 5], vertices[axis][3]); +} + +static void create_axis_aligned_slices(VolumeSlicer *slicer, const int num_slices, + const float view_dir[3], const int axis) +{ + float depth, slice_size = slicer->size[axis] / num_slices; + + /* always process slices in back to front order! */ + if (view_dir[axis] > 0.0f) { + depth = slicer->min[axis]; + } + else { + depth = slicer->max[axis]; + slice_size = -slice_size; + } + + int count = 0; + for (int slice = 0; slice < num_slices; slice++) { + create_single_slice(slicer, depth, axis, count); + + count += 6; + depth += slice_size; + } +} + /* *************************** View Aligned Slicing ************************** */ /* Code adapted from: @@ -433,8 +490,25 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, /* setup slicing information */ - const int max_slices = 256; - const int max_points = max_slices * 12; + const bool view_aligned = (sds->slice_method == MOD_SMOKE_SLICE_VIEW_ALIGNED); + int max_slices, max_points, axis = 0; + + if (view_aligned) { + max_slices = max_iii(sds->res[0], sds->res[1], sds->res[2]) * sds->slice_per_voxel; + max_points = max_slices * 12; + } + else { + if (sds->axis_slice_method == AXIS_SLICE_FULL) { + axis = axis_dominant_v3_single(viewnormal); + max_slices = sds->res[axis] * sds->slice_per_voxel; + } + else { + axis = (sds->slice_axis == SLICE_AXIS_AUTO) ? axis_dominant_v3_single(viewnormal) : sds->slice_axis - 1; + max_slices = 1; + } + + max_points = max_slices * 6; + } VolumeSlicer slicer; copy_v3_v3(slicer.min, min); @@ -442,7 +516,22 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, copy_v3_v3(slicer.size, size); slicer.verts = MEM_mallocN(sizeof(float) * 3 * max_points, "smoke_slice_vertices"); - const int num_points = create_view_aligned_slices(&slicer, max_slices, viewnormal); + int num_points; + + if (view_aligned) { + num_points = create_view_aligned_slices(&slicer, max_slices, viewnormal); + } + else { + num_points = max_points; + + if (sds->axis_slice_method == AXIS_SLICE_FULL) { + create_axis_aligned_slices(&slicer, max_slices, viewnormal, axis); + } + else { + const float depth = (sds->slice_depth - 0.5f) * size[axis]; + create_single_slice(&slicer, depth, axis, 0); + } + } /* setup buffer and draw */ -- cgit v1.2.3 From 14e825aa1fb57db85cecfda0cd69843b57cefd12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dietrich?= Date: Sat, 24 Sep 2016 22:36:54 +0200 Subject: Viewport smoke: add options to draw velocity vectors. This basically exposes to the UI a function that was only available through a debug macro ; the purpose is obviously to help debugging simulations. It adds ways to draw the vectors either as colored needles or as arrows showing the direction of the vectors. The colors are based on the magnitude of the underlying vectors. Reviewers: plasmasolutions, gottfried Differential Revision: https://developer.blender.org/D1733 --- source/blender/editors/space_view3d/drawvolume.c | 204 ++++++++++++++++++----- 1 file changed, 162 insertions(+), 42 deletions(-) (limited to 'source/blender/editors/space_view3d/drawvolume.c') diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index d743e7c09e7..ef4db7ed6b8 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -40,6 +40,7 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "BKE_DerivedMesh.h" #include "BKE_particle.h" #include "smoke_API.h" @@ -571,61 +572,180 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, } } -#ifdef SMOKE_DEBUG_VELOCITY -void draw_smoke_velocity(SmokeDomainSettings *domain, Object *ob) +static void add_tri(float (*verts)[3], float(*colors)[3], int *offset, + float p1[3], float p2[3], float p3[3], float rgb[3]) { - float x, y, z; - float x0, y0, z0; - int *base_res = domain->base_res; - int *res = domain->res; - int *res_min = domain->res_min; - int *res_max = domain->res_max; - float *vel_x = smoke_get_velocity_x(domain->fluid); - float *vel_y = smoke_get_velocity_y(domain->fluid); - float *vel_z = smoke_get_velocity_z(domain->fluid); + copy_v3_v3(verts[*offset + 0], p1); + copy_v3_v3(verts[*offset + 1], p2); + copy_v3_v3(verts[*offset + 2], p3); - float min[3]; - float *cell_size = domain->cell_size; - float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.f; - float vf = domain->scale / 16.f * 2.f; /* velocity factor */ + copy_v3_v3(colors[*offset + 0], rgb); + copy_v3_v3(colors[*offset + 1], rgb); + copy_v3_v3(colors[*offset + 2], rgb); - glLineWidth(1.0f); + *offset += 3; +} + +static void add_needle(float (*verts)[3], float (*colors)[3], float center[3], + float dir[3], float scale, float voxel_size, int *offset) +{ + float len = len_v3(dir); + + float rgb[3]; + weight_to_rgb(rgb, len); + + if (len != 0.0f) { + mul_v3_fl(dir, 1.0f / len); + len *= scale; + } + + len *= voxel_size; + + float corners[4][3] = { + { 0.0f, 0.2f, -0.5f }, + { -0.2f * 0.866f, -0.2f * 0.5f, -0.5f }, + { 0.2f * 0.866f, -0.2f * 0.5f, -0.5f }, + { 0.0f, 0.0f, 0.5f } + }; + + const float up[3] = { 0.0f, 0.0f, 1.0f }; + float rot[3][3]; + + rotation_between_vecs_to_mat3(rot, up, dir); + transpose_m3(rot); + + for (int i = 0; i < 4; i++) { + mul_m3_v3(rot, corners[i]); + mul_v3_fl(corners[i], len); + add_v3_v3(corners[i], center); + } + + add_tri(verts, colors, offset, corners[0], corners[1], corners[2], rgb); + add_tri(verts, colors, offset, corners[0], corners[1], corners[3], rgb); + add_tri(verts, colors, offset, corners[1], corners[2], corners[3], rgb); + add_tri(verts, colors, offset, corners[2], corners[0], corners[3], rgb); +} + +static void add_streamline(float (*verts)[3], float(*colors)[3], float center[3], + float dir[3], float scale, float voxel_size, int *offset) +{ + const float len = len_v3(dir); + + float rgb[3]; + weight_to_rgb(rgb, len); + + copy_v3_v3(colors[(*offset)], rgb); + copy_v3_v3(verts[(*offset)++], center); + + mul_v3_fl(dir, scale * voxel_size); + add_v3_v3(center, dir); + + copy_v3_v3(colors[(*offset)], rgb); + copy_v3_v3(verts[(*offset)++], center); +} + +typedef void (*vector_draw_func)(float(*)[3], float(*)[3], float*, float*, float, float, int*); + +void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3]) +{ + const int *base_res = domain->base_res; + const int *res = domain->res; + const int *res_min = domain->res_min; + + int res_max[3]; + copy_v3_v3_int(res_max, domain->res_max); + + const float *vel_x = smoke_get_velocity_x(domain->fluid); + const float *vel_y = smoke_get_velocity_y(domain->fluid); + const float *vel_z = smoke_get_velocity_z(domain->fluid); + + const float *cell_size = domain->cell_size; + const float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.0f; /* set first position so that it doesn't jump when domain moves */ - x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size); - y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size); - z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size); - if (x0 < res_min[0]) x0 += step_size; - if (y0 < res_min[1]) y0 += step_size; - if (z0 < res_min[2]) z0 += step_size; + float xyz[3] = { + res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size), + res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size), + res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size) + }; + + if (xyz[0] < res_min[0]) xyz[0] += step_size; + if (xyz[1] < res_min[1]) xyz[1] += step_size; + if (xyz[2] < res_min[2]) xyz[2] += step_size; + + float min[3]; add_v3_v3v3(min, domain->p0, domain->obj_shift_f); - for (x = floor(x0); x < res_max[0]; x += step_size) - for (y = floor(y0); y < res_max[1]; y += step_size) - for (z = floor(z0); z < res_max[2]; z += step_size) { + int num_points_v[3] = { + ((float)(res_max[0] - floor(xyz[0])) / step_size) + 0.5f, + ((float)(res_max[1] - floor(xyz[1])) / step_size) + 0.5f, + ((float)(res_max[2] - floor(xyz[2])) / step_size) + 0.5f + }; + + if (domain->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && + domain->axis_slice_method == AXIS_SLICE_SINGLE) + { + const int axis = (domain->slice_axis == SLICE_AXIS_AUTO) ? + axis_dominant_v3_single(viewnormal) : domain->slice_axis - 1; + + xyz[axis] = (float)res[axis] * domain->slice_depth; + num_points_v[axis] = 1; + res_max[axis] = xyz[axis] + 1; + } + + vector_draw_func func; + int max_points; + + if (domain->vector_draw_type == VECTOR_DRAW_NEEDLE) { + func = add_needle; + max_points = (num_points_v[0] * num_points_v[1] * num_points_v[2]) * 4 * 3; + } + else { + func = add_streamline; + max_points = (num_points_v[0] * num_points_v[1] * num_points_v[2]) * 2; + } + + float (*verts)[3] = MEM_mallocN(sizeof(float) * 3 * max_points, ""); + float (*colors)[3] = MEM_mallocN(sizeof(float) * 3 * max_points, ""); + + int num_points = 0; + + for (float x = floor(xyz[0]); x < res_max[0]; x += step_size) { + for (float y = floor(xyz[1]); y < res_max[1]; y += step_size) { + for (float z = floor(xyz[2]); z < res_max[2]; z += step_size) { int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1]; - float pos[3] = {min[0] + ((float)x + 0.5f) * cell_size[0], min[1] + ((float)y + 0.5f) * cell_size[1], min[2] + ((float)z + 0.5f) * cell_size[2]}; - float vel = sqrtf(vel_x[index] * vel_x[index] + vel_y[index] * vel_y[index] + vel_z[index] * vel_z[index]); + float pos[3] = { + min[0] + ((float)x + 0.5f) * cell_size[0], + min[1] + ((float)y + 0.5f) * cell_size[1], + min[2] + ((float)z + 0.5f) * cell_size[2] + }; - /* draw heat as scaled "arrows" */ - if (vel >= 0.01f) { - float col_g = 1.0f - vel; - CLAMP(col_g, 0.0f, 1.0f); - glColor3f(1.0f, col_g, 0.0f); - glPointSize(10.0f * vel); + float vel[3] = { + vel_x[index], vel_y[index], vel_z[index] + }; - glBegin(GL_LINES); - glVertex3f(pos[0], pos[1], pos[2]); - glVertex3f(pos[0] + vel_x[index] * vf, pos[1] + vel_y[index] * vf, pos[2] + vel_z[index] * vf); - glEnd(); - glBegin(GL_POINTS); - glVertex3f(pos[0] + vel_x[index] * vf, pos[1] + vel_y[index] * vf, pos[2] + vel_z[index] * vf); - glEnd(); - } + func(verts, colors, pos, vel, domain->vector_scale, cell_size[0], &num_points); } + } + } + + glLineWidth(1.0f); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, verts); + + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_FLOAT, 0, colors); + + glDrawArrays(GL_LINES, 0, num_points); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + MEM_freeN(verts); + MEM_freeN(colors); } -#endif #ifdef SMOKE_DEBUG_HEAT void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob) -- cgit v1.2.3 From d35bf3f421fe4166f5275067cc71e92465f1b954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dietrich?= Date: Sun, 25 Sep 2016 00:26:21 +0200 Subject: Fix compile error when building without smoke support. Also fixes possible NULL pointer dereference. Fixes T49445. --- source/blender/editors/space_view3d/drawvolume.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'source/blender/editors/space_view3d/drawvolume.c') diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index ef4db7ed6b8..79d51093734 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -648,6 +648,20 @@ typedef void (*vector_draw_func)(float(*)[3], float(*)[3], float*, float*, float void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3]) { +#ifdef WITH_SMOKE + const float *vel_x = smoke_get_velocity_x(domain->fluid); + const float *vel_y = smoke_get_velocity_y(domain->fluid); + const float *vel_z = smoke_get_velocity_z(domain->fluid); +#else + const float *vel_x = NULL; + const float *vel_y = NULL; + const float *vel_z = NULL; +#endif + + if (ELEM(NULL, vel_x, vel_y, vel_z)) { + return; + } + const int *base_res = domain->base_res; const int *res = domain->res; const int *res_min = domain->res_min; @@ -655,10 +669,6 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3]) int res_max[3]; copy_v3_v3_int(res_max, domain->res_max); - const float *vel_x = smoke_get_velocity_x(domain->fluid); - const float *vel_y = smoke_get_velocity_y(domain->fluid); - const float *vel_z = smoke_get_velocity_z(domain->fluid); - const float *cell_size = domain->cell_size; const float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.0f; -- cgit v1.2.3 From ae69986b70611f358491759f39fd91efd015dab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dietrich?= Date: Sun, 25 Sep 2016 17:02:46 +0200 Subject: Viewport smoke: fix a couple of issues in the new display settings. - WITH_SMOKE macro was not defined so some code was not compiled, though it was still accessible from the UI - some UI elements were disappearing due to bad indentation, also rework the UI code to not hide but rather disable/grey out button in the UI - Display thickness was not used due to bad manual merge of the code from the patch. --- source/blender/editors/space_view3d/drawvolume.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source/blender/editors/space_view3d/drawvolume.c') diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 79d51093734..d743ff9239a 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -382,7 +382,7 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture GPU_shader_uniform_texture(shader, spec_location, tex_spec); } else { - float density_scale = 10.0f; + float density_scale = 10.0f * sds->display_thickness; GPU_shader_uniform_vector(shader, stepsize_location, 1, 1, &sds->dx); GPU_shader_uniform_vector(shader, densityscale_location, 1, 1, &density_scale); @@ -572,6 +572,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, } } +#ifdef WITH_SMOKE static void add_tri(float (*verts)[3], float(*colors)[3], int *offset, float p1[3], float p2[3], float p3[3], float rgb[3]) { @@ -645,6 +646,7 @@ static void add_streamline(float (*verts)[3], float(*colors)[3], float center[3] } typedef void (*vector_draw_func)(float(*)[3], float(*)[3], float*, float*, float, float, int*); +#endif /* WITH_SMOKE */ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3]) { @@ -652,11 +654,6 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3]) const float *vel_x = smoke_get_velocity_x(domain->fluid); const float *vel_y = smoke_get_velocity_y(domain->fluid); const float *vel_z = smoke_get_velocity_z(domain->fluid); -#else - const float *vel_x = NULL; - const float *vel_y = NULL; - const float *vel_z = NULL; -#endif if (ELEM(NULL, vel_x, vel_y, vel_z)) { return; @@ -755,6 +752,9 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3]) MEM_freeN(verts); MEM_freeN(colors); +#else + UNUSED_VARS(domain, viewnormal); +#endif } #ifdef SMOKE_DEBUG_HEAT -- cgit v1.2.3 From 584288a97c2b1f28dc0e29b2bd986830df233947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dietrich?= Date: Sun, 25 Sep 2016 21:45:09 +0200 Subject: Smoke debug draw: take adaptive domain position into account. Eventually the various functions that deals with adaptive domain bounding box shall de-duplicated. --- source/blender/editors/space_view3d/drawvolume.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source/blender/editors/space_view3d/drawvolume.c') diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index d743ff9239a..b0e21601b9c 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -680,8 +680,11 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3]) if (xyz[1] < res_min[1]) xyz[1] += step_size; if (xyz[2] < res_min[2]) xyz[2] += step_size; - float min[3]; - add_v3_v3v3(min, domain->p0, domain->obj_shift_f); + float min[3] = { + domain->p0[0] - domain->cell_size[0] * domain->adapt_res, + domain->p0[1] - domain->cell_size[1] * domain->adapt_res, + domain->p0[2] - domain->cell_size[2] * domain->adapt_res, + }; int num_points_v[3] = { ((float)(res_max[0] - floor(xyz[0])) / step_size) + 0.5f, @@ -695,7 +698,7 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3]) const int axis = (domain->slice_axis == SLICE_AXIS_AUTO) ? axis_dominant_v3_single(viewnormal) : domain->slice_axis - 1; - xyz[axis] = (float)res[axis] * domain->slice_depth; + xyz[axis] = (float)base_res[axis] * domain->slice_depth; num_points_v[axis] = 1; res_max[axis] = xyz[axis] + 1; } -- cgit v1.2.3