Smoke drawing code cleanups (and little refactor)

This patch contains the following changes:

- the vertices and edges arrays would be assigned default values, and
then reassigned new ones right away. It appears that those arrays were
once global and then made local
(rB06a2ee4afed4237398b69ddf253e29a730b2f9f0), so it makes sense now to
initialize them with the right values.
- the flame spectrum texture was created whether it was needed or not,
so now it's only created if there's flame to be drawn, also split the
code in a separate function.
 - reduce the number of parameters to the main draw function, as most of
them are member of SmokeDomainSettings.
- some other minor cleanups: fold multiple operations into one to get
rid of one local variable, mark variables as `const` when necessary,
unecessary gl draw calls, reorder the code a bit...

Reviewers: campbellbarton, psy-fi

Differential Revision: https://developer.blender.org/D1368
This commit is contained in:
Kévin Dietrich 2015-11-22 18:17:09 +01:00
parent 8623d75b46
commit 3e1a9ee386
3 changed files with 105 additions and 168 deletions

View File

@ -8093,7 +8093,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
/* 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) {
if (sds->fluid && CFRA >= sds->point_cache[0]->startframe) {
float p0[3], p1[3];
/* get view vector */
@ -8112,21 +8112,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
p1[2] = (sds->p0[2] + sds->cell_size[2] * sds->res_max[2] + sds->obj_shift_f[2]) * fabsf(ob->size[2]);
if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
smd->domain->tex = NULL;
sds->tex = NULL;
GPU_create_smoke(smd, 0);
draw_smoke_volume(sds, ob, sds->tex,
p0, p1,
sds->res, sds->dx, sds->scale * sds->maxres,
viewnormal, sds->tex_shadow, sds->tex_flame);
draw_smoke_volume(sds, ob, p0, p1, sds->res, viewnormal);
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, sds->tex,
p0, p1,
sds->res_wt, sds->dx, sds->scale * sds->maxres,
viewnormal, sds->tex_shadow, sds->tex_flame);
draw_smoke_volume(sds, ob, p0, p1, sds->res_wt, viewnormal);
GPU_free_smoke(smd);
}

View File

@ -59,7 +59,7 @@ struct GPUTexture;
# include "PIL_time_utildefines.h"
#endif
static int intersect_edges(float (*points)[3], float a, float b, float c, float d, float edges[12][2][3])
static int intersect_edges(float (*points)[3], float a, float b, float c, float d, const float edges[12][2][3])
{
int i;
float t;
@ -88,74 +88,20 @@ static bool convex(const float p0[3], const float up[3], const float a[3], const
return dot_v3v3(up, tmp) >= 0;
}
void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
GPUTexture *tex, const float min[3], const float max[3],
const int res[3], float dx, float UNUSED(base_scale), const float viewnormal[3],
GPUTexture *tex_shadow, GPUTexture *tex_flame)
static GPUTexture *create_flame_spectrum_texture(void)
{
const float ob_sizei[3] = {
1.0f / fabsf(ob->size[0]),
1.0f / fabsf(ob->size[1]),
1.0f / fabsf(ob->size[2])};
int i, j, k, n, good_index;
float d /*, d0 */ /* UNUSED */, dd, ds;
float (*points)[3] = NULL;
int numpoints = 0;
float cor[3] = {1.0f, 1.0f, 1.0f};
int gl_depth = 0, gl_blend = 0;
const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) != 0;
/* draw slices of smoke is adapted from c++ code authored
* by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */
float cv[][3] = {
{1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
{1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
};
/* edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] */
float edges[12][2][3] = {
{{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
{{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
{{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
{{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
{{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
{{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
{{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
{{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
{{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
{{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
{{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}},
{{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
};
unsigned char *spec_data;
float *spec_pixels;
GPUTexture *tex_spec;
GPUProgram *smoke_program;
int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED : GPU_PROGRAM_SMOKE;
float size[3];
if (!tex) {
printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
return;
}
#ifdef DEBUG_DRAW_TIME
TIMEIT_START(draw);
#endif
/* 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));
GPUTexture *tex;
int i, j, k;
unsigned char *spec_data = malloc(SPEC_WIDTH * 4 * sizeof(unsigned char));
float *spec_pixels = malloc(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float));
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++) {
@ -168,88 +114,94 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
(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;
zero_v4(&spec_pixels[index]);
}
}
}
}
tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);
tex = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);
free(spec_data);
free(spec_pixels);
#undef SPEC_WIDTH
#undef FIRE_THRESH
#undef MAX_FIRE_ALPHA
#undef FULL_ON_FIRE
sub_v3_v3v3(size, max, min);
return tex;
}
/* maxx, maxy, maxz */
cv[0][0] = max[0];
cv[0][1] = max[1];
cv[0][2] = max[2];
/* minx, maxy, maxz */
cv[1][0] = min[0];
cv[1][1] = max[1];
cv[1][2] = max[2];
/* minx, miny, maxz */
cv[2][0] = min[0];
cv[2][1] = min[1];
cv[2][2] = max[2];
/* maxx, miny, maxz */
cv[3][0] = max[0];
cv[3][1] = min[1];
cv[3][2] = max[2];
void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
const float min[3], const float max[3],
const int res[3], const float viewnormal[3])
{
GPUTexture *tex_spec;
GPUProgram *smoke_program;
const int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED
: GPU_PROGRAM_SMOKE;
/* maxx, maxy, minz */
cv[4][0] = max[0];
cv[4][1] = max[1];
cv[4][2] = min[2];
/* minx, maxy, minz */
cv[5][0] = min[0];
cv[5][1] = max[1];
cv[5][2] = min[2];
/* minx, miny, minz */
cv[6][0] = min[0];
cv[6][1] = min[1];
cv[6][2] = min[2];
/* maxx, miny, minz */
cv[7][0] = max[0];
cv[7][1] = min[1];
cv[7][2] = min[2];
const float ob_sizei[3] = {
1.0f / fabsf(ob->size[0]),
1.0f / fabsf(ob->size[1]),
1.0f / fabsf(ob->size[2])
};
copy_v3_v3(edges[0][0], cv[4]); /* maxx, maxy, minz */
copy_v3_v3(edges[1][0], cv[5]); /* minx, maxy, minz */
copy_v3_v3(edges[2][0], cv[6]); /* minx, miny, minz */
copy_v3_v3(edges[3][0], cv[7]); /* maxx, miny, minz */
int i, j, n, good_index;
float d /*, d0 */ /* UNUSED */, dd, ds;
float (*points)[3] = NULL;
int numpoints = 0;
float cor[3] = {1.0f, 1.0f, 1.0f};
int gl_depth = 0, gl_blend = 0;
copy_v3_v3(edges[4][0], cv[3]); /* maxx, miny, maxz */
copy_v3_v3(edges[5][0], cv[2]); /* minx, miny, maxz */
copy_v3_v3(edges[6][0], cv[6]); /* minx, miny, minz */
copy_v3_v3(edges[7][0], cv[7]); /* maxx, miny, minz */
const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) != 0;
copy_v3_v3(edges[8][0], cv[1]); /* minx, maxy, maxz */
copy_v3_v3(edges[9][0], cv[2]); /* minx, miny, maxz */
copy_v3_v3(edges[10][0], cv[6]); /* minx, miny, minz */
copy_v3_v3(edges[11][0], cv[5]); /* minx, maxy, minz */
/* draw slices of smoke is adapted from c++ code authored
* by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */
const float verts[8][3] = {
{ max[0], max[1], max[2] },
{ min[0], max[1], max[2] },
{ min[0], min[1], max[2] },
{ max[0], min[1], max[2] },
{ max[0], max[1], min[2] },
{ min[0], max[1], min[2] },
{ min[0], min[1], min[2] },
{ max[0], min[1], min[2] }
};
const float size[3] = { max[0] - min[0], max[1] - min[1], max[2] - min[2] };
/* edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] */
const float edges[12][2][3] = {
{{verts[4][0], verts[4][1], verts[4][2]}, {0.0f, 0.0f, size[2]}},
{{verts[5][0], verts[5][1], verts[5][2]}, {0.0f, 0.0f, size[2]}},
{{verts[6][0], verts[6][1], verts[6][2]}, {0.0f, 0.0f, size[2]}},
{{verts[7][0], verts[7][1], verts[7][2]}, {0.0f, 0.0f, size[2]}},
{{verts[3][0], verts[3][1], verts[3][2]}, {0.0f, size[1], 0.0f}},
{{verts[2][0], verts[2][1], verts[2][2]}, {0.0f, size[1], 0.0f}},
{{verts[6][0], verts[6][1], verts[6][2]}, {0.0f, size[1], 0.0f}},
{{verts[7][0], verts[7][1], verts[7][2]}, {0.0f, size[1], 0.0f}},
{{verts[1][0], verts[1][1], verts[1][2]}, {size[0], 0.0f, 0.0f}},
{{verts[2][0], verts[2][1], verts[2][2]}, {size[0], 0.0f, 0.0f}},
{{verts[6][0], verts[6][1], verts[6][2]}, {size[0], 0.0f, 0.0f}},
{{verts[5][0], verts[5][1], verts[5][2]}, {size[0], 0.0f, 0.0f}}
};
if (!sds->tex) {
printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
return;
}
#ifdef DEBUG_DRAW_TIME
TIMEIT_START(draw);
#endif
// printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]);
// printf("min[2]: %f, max[2]: %f\n", min[2], max[2]);
edges[0][1][2] = size[2];
edges[1][1][2] = size[2];
edges[2][1][2] = size[2];
edges[3][1][2] = size[2];
edges[4][1][1] = size[1];
edges[5][1][1] = size[1];
edges[6][1][1] = size[1];
edges[7][1][1] = size[1];
edges[8][1][0] = size[0];
edges[9][1][0] = size[0];
edges[10][1][0] = size[0];
edges[11][1][0] = size[0];
glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
@ -258,11 +210,9 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
/* find cube vertex that is closest to the viewer */
for (i = 0; i < 8; i++) {
float x, y, z;
x = cv[i][0] - viewnormal[0] * size[0] * 0.5f;
y = cv[i][1] - viewnormal[1] * size[1] * 0.5f;
z = cv[i][2] - viewnormal[2] * size[2] * 0.5f;
float x = verts[i][0] - viewnormal[0] * size[0] * 0.5f;
float y = verts[i][1] - viewnormal[1] * size[1] * 0.5f;
float z = verts[i][2] - viewnormal[2] * size[2] * 0.5f;
if ((x >= min[0]) && (x <= max[0]) &&
(y >= min[1]) && (y <= max[1]) &&
@ -285,7 +235,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
GPU_program_bind(smoke_program);
/* cell spacing */
GPU_program_parameter_4f(smoke_program, 0, dx, dx, dx, 1.0);
GPU_program_parameter_4f(smoke_program, 0, sds->dx, sds->dx, sds->dx, 1.0);
/* custom parameter for smoke style (higher = thicker) */
if (sds->active_fields & SM_ACTIVE_COLORS)
GPU_program_parameter_4f(smoke_program, 1, 1.0, 1.0, 1.0, 10.0);
@ -295,14 +245,15 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
else
printf("Your gfx card does not support 3D View smoke drawing.\n");
GPU_texture_bind(tex, 0);
if (tex_shadow)
GPU_texture_bind(tex_shadow, 1);
GPU_texture_bind(sds->tex, 0);
if (sds->tex_shadow)
GPU_texture_bind(sds->tex_shadow, 1);
else
printf("No volume shadow\n");
if (tex_flame) {
GPU_texture_bind(tex_flame, 2);
if (sds->tex_flame) {
GPU_texture_bind(sds->tex_flame, 2);
tex_spec = create_flame_spectrum_texture();
GPU_texture_bind(tex_spec, 3);
}
@ -332,16 +283,13 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
points = MEM_callocN(sizeof(*points) * 12, "smoke_points_preview");
while (1) {
float p0[3];
float tmp_point[3], tmp_point2[3];
float p0[3], tmp_point[3];
if (dd * (float)n > ds)
break;
copy_v3_v3(tmp_point, viewnormal);
mul_v3_fl(tmp_point, -dd * ((ds / dd) - (float)n));
add_v3_v3v3(tmp_point2, cv[good_index], tmp_point);
d = dot_v3v3(tmp_point2, viewnormal);
madd_v3_v3v3fl(tmp_point, verts[good_index], viewnormal, -dd * ((ds / dd) - (float)n));
d = dot_v3v3(tmp_point, viewnormal);
// printf("my d: %f\n", d);
@ -372,7 +320,6 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
GPU_program_parameter_4f(smoke_program, 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][0] - min[0]) * cor[0],
(points[i][1] - min[1]) * cor[1],
@ -392,7 +339,6 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
GPU_program_parameter_4f(smoke_program, 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][0] - min[0]) * cor[0],
(points[i][1] - min[1]) * cor[1],
@ -411,22 +357,20 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
TIMEIT_END(draw);
#endif
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);
GPU_texture_unbind(sds->tex);
free(spec_data);
free(spec_pixels);
if (sds->tex_shadow)
GPU_texture_unbind(sds->tex_shadow);
if (sds->tex_flame) {
GPU_texture_unbind(sds->tex_flame);
GPU_texture_unbind(tex_spec);
GPU_texture_free(tex_spec);
}
if (smoke_program)
GPU_program_unbind(smoke_program);
MEM_freeN(points);
if (!gl_blend) {

View File

@ -273,9 +273,8 @@ extern const char *view3d_context_dir[]; /* doc access */
/* draw_volume.c */
void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob,
struct GPUTexture *tex, const float min[3], const float max[3],
const int res[3], float dx, float base_scale, const float viewnormal[3],
struct GPUTexture *tex_shadow, struct GPUTexture *tex_flame);
const float min[3], const float max[3],
const int res[3], const float viewnormal[3]);
//#define SMOKE_DEBUG_VELOCITY
//#define SMOKE_DEBUG_HEAT