diff options
author | Daniel Genrich <daniel.genrich@gmx.net> | 2012-10-10 17:18:07 +0400 |
---|---|---|
committer | Daniel Genrich <daniel.genrich@gmx.net> | 2012-10-10 17:18:07 +0400 |
commit | cb634b910010c04543cb3361f7a16a261e5b9f89 (patch) | |
tree | 348403dcbd33baf2e6e9a7a5ef0bb57dd2e1b09d /source/blender/editors | |
parent | f0a9b664694dacb0388a8e078d46753dc6a36352 (diff) |
Google Summer of Code project: "Smoke Simulator Improvements & Fire".
Documentation & Test blend files:
------------------
http://wiki.blender.org/index.php/User:MiikaH/GSoC-2012-Smoke-Simulator-Improvements
Credits:
------------------
Miika Hamalainen (MiikaH): Student / Main programmer
Daniel Genrich (Genscher): Mentor / Programmer of merged patches from Smoke2 branch
Google: For Google Summer of Code 2012
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/include/UI_icons.h | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_add.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 128 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawvolume.c | 263 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_intern.h | 11 |
5 files changed, 307 insertions, 100 deletions
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index ef7b8ed3a41..8f50edd1240 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -450,8 +450,8 @@ DEF_ICON(FORCE_CURVE) DEF_ICON(FORCE_BOID) DEF_ICON(FORCE_TURBULENCE) DEF_ICON(FORCE_DRAG) +DEF_ICON(FORCE_SMOKEFLOW) #ifndef DEF_ICON_BLANK_SKIP - DEF_ICON(BLANK672) DEF_ICON(BLANK673) DEF_ICON(BLANK674) DEF_ICON(BLANK675) diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 43a32cd662e..dc20e0d69cd 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -136,6 +136,7 @@ static EnumPropertyItem field_type_items[] = { {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""}, {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""}, {PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""}, + {PFIELD_SMOKEFLOW, "SMOKE", ICON_FORCE_SMOKEFLOW, "Smoke Flow", ""}, {0, NULL, 0, NULL, NULL} }; @@ -356,7 +357,7 @@ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const floa Scene *scene = CTX_data_scene(C); Object *ob; - /* For as long scene has editmode... */ + /* for as long scene has editmode... */ if (CTX_data_edit_object(C)) ED_object_exit_editmode(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */ diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index eb17aa2b8ce..dd3c7408511 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -6625,72 +6625,74 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } /* only draw domains */ - if (smd->domain && smd->domain->fluid) { - if (CFRA < smd->domain->point_cache[0]->startframe) { - /* don't show smoke before simulation starts, this could be made an option in the future */ - } - else if (!smd->domain->wt || !(smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { -// #if 0 - smd->domain->tex = NULL; - GPU_create_smoke(smd, 0); - draw_volume(ar, smd->domain->tex, - smd->domain->p0, smd->domain->p1, - smd->domain->res, smd->domain->dx, - smd->domain->tex_shadow); - GPU_free_smoke(smd); -// #endif -#if 0 - int x, y, z; - float *density = smoke_get_density(smd->domain->fluid); - - glLoadMatrixf(rv3d->viewmat); - // glMultMatrixf(ob->obmat); + if (smd->domain) { + SmokeDomainSettings *sds = smd->domain; + float p0[3], p1[3], viewnormal[3]; + BoundBox bb; - if (col || (ob->flag & SELECT)) cpack(0xFFFFFF); - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - - - // glPointSize(3.0); - bglBegin(GL_POINTS); - - for (x = 0; x < smd->domain->res[0]; x++) { - for (y = 0; y < smd->domain->res[1]; y++) { - for (z = 0; z < smd->domain->res[2]; z++) { - float tmp[3]; - int index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z); - - if (density[index] > FLT_EPSILON) { - float color[3]; - copy_v3_v3(tmp, smd->domain->p0); - tmp[0] += smd->domain->dx * x + smd->domain->dx * 0.5; - tmp[1] += smd->domain->dx * y + smd->domain->dx * 0.5; - tmp[2] += smd->domain->dx * z + smd->domain->dx * 0.5; - color[0] = color[1] = color[2] = density[index]; - glColor3fv(color); - bglVertex3fv(tmp); - } - } - } + glLoadMatrixf(rv3d->viewmat); + glMultMatrixf(ob->obmat); + + /* draw adaptive domain bounds */ + if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) { + /* draw domain max bounds */ + VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res); + VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res); + BKE_boundbox_init_from_minmax(&bb, p0, p1); + draw_box(bb.vec); + + /* draw base resolution bounds */ + /*BKE_boundbox_init_from_minmax(&bb, sds->p0, sds->p1); + draw_box(bb.vec);*/ + } + + /* don't show smoke before simulation starts, this could be made an option in the future */ + if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) { + + // get view vector + copy_v3_v3(viewnormal, rv3d->viewinv[2]); + mul_mat3_m4_v3(ob->imat, viewnormal); + normalize_v3(viewnormal); + + /* set dynamic boundaries to draw the volume */ + p0[0] = sds->p0[0] + sds->cell_size[0]*sds->res_min[0] + sds->obj_shift_f[0]; + p0[1] = sds->p0[1] + sds->cell_size[1]*sds->res_min[1] + sds->obj_shift_f[1]; + p0[2] = sds->p0[2] + sds->cell_size[2]*sds->res_min[2] + sds->obj_shift_f[2]; + p1[0] = sds->p0[0] + sds->cell_size[0]*sds->res_max[0] + sds->obj_shift_f[0]; + p1[1] = sds->p0[1] + sds->cell_size[1]*sds->res_max[1] + sds->obj_shift_f[1]; + p1[2] = sds->p0[2] + sds->cell_size[2]*sds->res_max[2] + sds->obj_shift_f[2]; + + /* scale cube to global space to equalize volume slicing on all axises + * (its scaled back before drawing) */ + mul_v3_v3(p0, ob->size); + mul_v3_v3(p1, ob->size); + + if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { + smd->domain->tex = NULL; + GPU_create_smoke(smd, 0); + draw_smoke_volume(sds, ob, ar, sds->tex, + p0, p1, + sds->res, sds->dx, sds->scale*sds->maxres, + viewnormal, sds->tex_shadow, sds->tex_flame); + GPU_free_smoke(smd); + } + else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { + sds->tex = NULL; + GPU_create_smoke(smd, 1); + draw_smoke_volume(sds, ob, ar, sds->tex, + p0, p1, + sds->res_wt, sds->dx, sds->scale*sds->maxres, + viewnormal, sds->tex_shadow, sds->tex_flame); + GPU_free_smoke(smd); } - bglEnd(); - glPointSize(1.0); - - glMultMatrixf(ob->obmat); - glDisable(GL_BLEND); - glDepthMask(GL_TRUE); - if (col) cpack(col); -#endif - } - else if (smd->domain->wt && (smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { - smd->domain->tex = NULL; - GPU_create_smoke(smd, 1); - draw_volume(ar, smd->domain->tex, - smd->domain->p0, smd->domain->p1, - smd->domain->res_wt, smd->domain->dx_wt, - smd->domain->tex_shadow); - GPU_free_smoke(smd); + /* smoke debug render */ + #ifdef SMOKE_DEBUG_VELOCITY + draw_smoke_velocity(smd->domain, ob); + #endif + #ifdef SMOKE_DEBUG_HEAT + draw_smoke_heat(smd->domain, ob); + #endif } } } diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 2c2d4039225..7215e8ec6b4 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -36,6 +36,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_smoke_types.h" #include "DNA_view3d_types.h" #include "BLI_utildefines.h" @@ -156,12 +157,9 @@ static int convex(const float p0[3], const float up[3], const float a[3], const return dot_v3v3(up, tmp) >= 0; } -void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int res[3], float dx, GPUTexture *tex_shadow) +void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, ARegion *ar, GPUTexture *tex, float min[3], float max[3], int res[3], float dx, float base_scale, float viewnormal[3], GPUTexture *tex_shadow, GPUTexture *tex_flame) { - RegionView3D *rv3d = ar->regiondata; - - float viewnormal[3]; - int i, j, n, good_index; + int i, j, k, n, good_index; float d /*, d0 */ /* UNUSED */, dd, ds; float *points = NULL; int numpoints = 0; @@ -193,24 +191,72 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r {{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}} }; + unsigned char *spec_data; + float *spec_pixels; + GPUTexture *tex_spec; + /* Fragment program to calculate the view3d of smoke */ - /* using 2 textures, density and shadow */ - const char *text = "!!ARBfp1.0\n" + /* using 4 textures, density, shadow, flame and flame spectrum */ + const char *shader_basic = "!!ARBfp1.0\n" "PARAM dx = program.local[0];\n" "PARAM darkness = program.local[1];\n" + "PARAM render = program.local[2];\n" "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n" - "TEMP temp, shadow, value;\n" + "TEMP temp, shadow, flame, spec, value;\n" "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" - "MUL value, temp, darkness;\n" - "MUL value, value, dx;\n" - "MUL value, value, f;\n" + "TEX flame, fragment.texcoord[0], texture[2], 3D;\n" + "TEX spec, flame.r, texture[3], 1D;\n" + /* calculate shading factor from density */ + "MUL value.r, temp.a, darkness.a;\n" + "MUL value.r, value.r, dx.r;\n" + "MUL value.r, value.r, f.r;\n" "EX2 temp, -value.r;\n" - "SUB temp.a, 1.0, temp.r;\n" + /* alpha */ + "SUB temp.a, 1.0, temp.r;\n" + /* shade colors */ + "MUL temp.r, temp.r, shadow.r;\n" + "MUL temp.g, temp.g, shadow.r;\n" + "MUL temp.b, temp.b, shadow.r;\n" + "MUL temp.r, temp.r, darkness.r;\n" + "MUL temp.g, temp.g, darkness.g;\n" + "MUL temp.b, temp.b, darkness.b;\n" + /* for now this just replace smoke shading if rendering fire */ + "CMP result.color, render.r, temp, spec;\n" + "END\n"; + + /* color shader */ + const char *shader_color = "!!ARBfp1.0\n" + "PARAM dx = program.local[0];\n" + "PARAM darkness = program.local[1];\n" + "PARAM render = program.local[2];\n" + "PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n" + "TEMP temp, shadow, flame, spec, value;\n" + "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" + "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" + "TEX flame, fragment.texcoord[0], texture[2], 3D;\n" + "TEX spec, flame.r, texture[3], 1D;\n" + /* unpremultiply volume texture */ + "RCP value.r, temp.a;\n" + "MUL temp.r, temp.r, value.r;\n" + "MUL temp.g, temp.g, value.r;\n" + "MUL temp.b, temp.b, value.r;\n" + /* calculate shading factor from density */ + "MUL value.r, temp.a, darkness.a;\n" + "MUL value.r, value.r, dx.r;\n" + "MUL value.r, value.r, f.r;\n" + "EX2 value.r, -value.r;\n" + /* alpha */ + "SUB temp.a, 1.0, value.r;\n" + /* shade colors */ "MUL temp.r, temp.r, shadow.r;\n" "MUL temp.g, temp.g, shadow.r;\n" "MUL temp.b, temp.b, shadow.r;\n" - "MOV result.color, temp;\n" + "MUL temp.r, temp.r, value.r;\n" + "MUL temp.g, temp.g, value.r;\n" + "MUL temp.b, temp.b, value.r;\n" + /* for now this just replace smoke shading if rendering fire */ + "CMP result.color, render.r, temp, spec;\n" "END\n"; GLuint prog; @@ -223,6 +269,32 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r } tstart(); + /* generate flame spectrum texture */ + #define SPEC_WIDTH 256 + #define FIRE_THRESH 7 + #define MAX_FIRE_ALPHA 0.06f + #define FULL_ON_FIRE 100 + spec_data = malloc(SPEC_WIDTH*4 * sizeof(unsigned char)); + flame_get_spectrum(spec_data, SPEC_WIDTH, 1500, 3000); + spec_pixels = malloc(SPEC_WIDTH*4*16*16 * sizeof(float)); + for (i=0;i<16;i++){ + for (j=0;j<16;j++) { + for (k=0;k<SPEC_WIDTH;k++) { + int index = (j*SPEC_WIDTH*16+i*SPEC_WIDTH+k)*4; + if (k>=FIRE_THRESH) { + spec_pixels[index] = ((float)spec_data[k*4])/255.0f; + spec_pixels[index+1] = ((float)spec_data[k*4+1])/255.0f; + spec_pixels[index+2] = ((float)spec_data[k*4+2])/255.0f; + spec_pixels[index+3] = MAX_FIRE_ALPHA*( + (k>FULL_ON_FIRE) ? 1.0f : (k-FIRE_THRESH)/((float)FULL_ON_FIRE-FIRE_THRESH)); + } else { + spec_pixels[index] = spec_pixels[index+1] = spec_pixels[index+2] = spec_pixels[index+3] = 0.0f; + } + } + } + } + + tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL); sub_v3_v3v3(size, max, min); @@ -294,26 +366,11 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r edges[11][1][0] = size[0]; glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend); - glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth); - - glLoadMatrixf(rv3d->viewmat); - // glMultMatrixf(ob->obmat); + glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - -#if 0 - printf("Viewinv:\n"); - printf("%f, %f, %f\n", rv3d->viewinv[0][0], rv3d->viewinv[0][1], rv3d->viewinv[0][2]); - printf("%f, %f, %f\n", rv3d->viewinv[1][0], rv3d->viewinv[1][1], rv3d->viewinv[1][2]); - printf("%f, %f, %f\n", rv3d->viewinv[2][0], rv3d->viewinv[2][1], rv3d->viewinv[2][2]); -#endif - - /* get view vector */ - copy_v3_v3(viewnormal, rv3d->viewinv[2]); - normalize_v3(viewnormal); /* find cube vertex that is closest to the viewer */ for (i = 0; i < 8; i++) { @@ -344,12 +401,19 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r glGenProgramsARB(1, &prog); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog); - glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text); + /* set shader */ + if (sds->active_fields & SM_ACTIVE_COLORS) + glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color); + else + glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic); /* cell spacing */ glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0); /* custom parameter for smoke style (higher = thicker) */ - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0); + if (sds->active_fields & SM_ACTIVE_COLORS) + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0); + else + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0); } else printf("Your gfx card does not support 3D View smoke drawing.\n"); @@ -360,6 +424,11 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r else printf("No volume shadow\n"); + if (tex_flame) { + GPU_texture_bind(tex_flame, 2); + GPU_texture_bind(tex_spec, 3); + } + if (!GPU_non_power_of_two_support()) { cor[0] = (float)res[0] / (float)power_of_2_max_i(res[0]); cor[1] = (float)res[1] / (float)power_of_2_max_i(res[1]); @@ -373,7 +442,7 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r /* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */ ds = (ABS(viewnormal[0]) * size[0] + ABS(viewnormal[1]) * size[1] + ABS(viewnormal[2]) * size[2]); - dd = ds / 96.f; + dd = MAX3(sds->global_size[0],sds->global_size[1],sds->global_size[2])/128.f; n = 0; good_index = i; @@ -416,14 +485,29 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r } } - // printf("numpoints: %d\n", numpoints); + /* render fire slice */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0); glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); for (i = 0; i < numpoints; i++) { glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0], (points[i * 3 + 1] - min[1]) * cor[1] / size[1], (points[i * 3 + 2] - min[2]) * cor[2] / size[2]); - glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]); + glVertex3f(points[i * 3 + 0]/ob->size[0], points[i * 3 + 1]/ob->size[1], points[i * 3 + 2]/ob->size[2]); + } + glEnd(); + + /* render smoke slice */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0); + glBegin(GL_POLYGON); + glColor3f(1.0, 1.0, 1.0); + for (i = 0; i < numpoints; i++) { + glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0], + (points[i * 3 + 1] - min[1]) * cor[1] / size[1], + (points[i * 3 + 2] - min[2]) * cor[2] / size[2]); + glVertex3f(points[i * 3 + 0]/ob->size[0], points[i * 3 + 1]/ob->size[1], points[i * 3 + 2]/ob->size[2]); } glEnd(); } @@ -436,6 +520,14 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r if (tex_shadow) GPU_texture_unbind(tex_shadow); GPU_texture_unbind(tex); + if (tex_flame) { + GPU_texture_unbind(tex_flame); + GPU_texture_unbind(tex_spec); + } + GPU_texture_free(tex_spec); + + free(spec_data); + free(spec_pixels); if (GLEW_ARB_fragment_program) { glDisable(GL_FRAGMENT_PROGRAM_ARB); @@ -454,3 +546,106 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r glDepthMask(GL_TRUE); } } + +#ifdef SMOKE_DEBUG_VELOCITY +void draw_smoke_velocity(SmokeDomainSettings *domain, Object *ob) +{ + 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); + + float min[3]; + float *cell_size = domain->cell_size; + float step_size = ((float)MAX3(base_res[0], base_res[1], base_res[2]))/16.f; + float vf = domain->scale / 16.f * 2.f; /* velocity factor */ + + glLineWidth(1.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; + 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 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]); + + /* 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); + + 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(); + } + } +} +#endif + +#ifdef SMOKE_DEBUG_HEAT +void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob) +{ + 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 *heat = smoke_get_heat(domain->fluid); + + float min[3]; + float *cell_size = domain->cell_size; + float step_size = ((float)MAX3(base_res[0], base_res[1], base_res[2]))/16.f; + float vf = domain->scale / 16.f * 2.f; /* velocity factor */ + + /* 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; + 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 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]}; + + /* draw heat as different sized points */ + if (heat[index] >= 0.01f) { + float col_gb = 1.0f - heat[index]; + CLAMP(col_gb, 0.0f, 1.0f); + glColor3f(1.0f, col_gb, col_gb); + glPointSize(24.0f * heat[index]); + + glBegin(GL_POINTS); + glVertex3f(pos[0], pos[1], pos[2]); + glEnd(); + } + } +} +#endif diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 5bfabf4fc4a..8d7a6421a34 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -212,7 +212,16 @@ ARegion *view3d_has_tools_region(ScrArea *sa); extern const char *view3d_context_dir[]; /* doc access */ /* draw_volume.c */ -void draw_volume(struct ARegion *ar, struct GPUTexture *tex, float min[3], float max[3], int res[3], float dx, struct GPUTexture *tex_shadow); +void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob, struct ARegion *ar, struct GPUTexture *tex, float min[3], float max[3], int res[3], float dx, float base_scale, float viewnormal[3], struct GPUTexture *tex_shadow, struct GPUTexture *tex_flame); +//#define SMOKE_DEBUG_VELOCITY +//#define SMOKE_DEBUG_HEAT + +#ifdef SMOKE_DEBUG_VELOCITY +void draw_smoke_velocity(struct SmokeDomainSettings *domain, struct Object *ob); +#endif +#ifdef SMOKE_DEBUG_HEAT +void draw_smoke_heat(struct SmokeDomainSettings *domain, struct Object *ob); +#endif /* workaround for trivial but noticeable camera bug caused by imprecision * between view border calculation in 2D/3D space, workaround for bug [#28037]. |