74
75
#include "ED_mesh.h"
77
77
#include "BLF_api.h"
80
79
#include "view3d_intern.h" // own include
89
static LARGE_INTEGER liFrequency;
90
static LARGE_INTEGER liStartTime;
91
static LARGE_INTEGER liCurrentTime;
93
static void tstart(void)
95
QueryPerformanceFrequency(&liFrequency);
96
QueryPerformanceCounter(&liStartTime);
98
static void tend(void)
100
QueryPerformanceCounter(&liCurrentTime);
102
static double tval(void)
104
return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart) * (double)1000.0 / (double)liFrequency.QuadPart));
107
#include <sys/time.h>
108
static struct timeval _tstart, _tend;
109
static struct timezone tz;
110
static void tstart(void)
112
gettimeofday(&_tstart, &tz);
114
static void tend(void)
116
gettimeofday(&_tend, &tz);
122
t1 = ( double ) _tstart.tv_sec * 1000 + ( double ) _tstart.tv_usec / (1000);
123
t2 = ( double ) _tend.tv_sec * 1000 + ( double ) _tend.tv_usec / (1000);
129
81
struct GPUTexture;
83
// #define DEBUG_DRAW_TIME
85
#ifdef DEBUG_DRAW_TIME
86
# include "PIL_time.h"
131
89
static int intersect_edges(float *points, float a, float b, float c, float d, float edges[12][2][3])
135
93
int numpoints = 0;
137
95
for (i = 0; i < 12; i++) {
138
96
t = -(a * edges[i][0][0] + b * edges[i][0][1] + c * edges[i][0][2] + d) /
139
97
(a * edges[i][1][0] + b * edges[i][1][1] + c * edges[i][1][2]);
194
152
{{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
155
unsigned char *spec_data;
157
GPUTexture *tex_spec;
197
159
/* Fragment program to calculate the view3d of smoke */
198
/* using 2 textures, density and shadow */
199
const char *text = "!!ARBfp1.0\n"
200
"PARAM dx = program.local[0];\n"
201
"PARAM darkness = program.local[1];\n"
202
"PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
203
"TEMP temp, shadow, value;\n"
204
"TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
205
"TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
206
"MUL value, temp, darkness;\n"
207
"MUL value, value, dx;\n"
208
"MUL value, value, f;\n"
209
"EX2 temp, -value.r;\n"
210
"SUB temp.a, 1.0, temp.r;\n"
211
"MUL temp.r, temp.r, shadow.r;\n"
212
"MUL temp.g, temp.g, shadow.r;\n"
213
"MUL temp.b, temp.b, shadow.r;\n"
214
"MOV result.color, temp;\n"
160
/* using 4 textures, density, shadow, flame and flame spectrum */
161
const char *shader_basic =
163
"PARAM dx = program.local[0];\n"
164
"PARAM darkness = program.local[1];\n"
165
"PARAM render = program.local[2];\n"
166
"PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
167
"TEMP temp, shadow, flame, spec, value;\n"
168
"TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
169
"TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
170
"TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
171
"TEX spec, flame.r, texture[3], 1D;\n"
172
/* calculate shading factor from density */
173
"MUL value.r, temp.a, darkness.a;\n"
174
"MUL value.r, value.r, dx.r;\n"
175
"MUL value.r, value.r, f.r;\n"
176
"EX2 temp, -value.r;\n"
178
"SUB temp.a, 1.0, temp.r;\n"
180
"MUL temp.r, temp.r, shadow.r;\n"
181
"MUL temp.g, temp.g, shadow.r;\n"
182
"MUL temp.b, temp.b, shadow.r;\n"
183
"MUL temp.r, temp.r, darkness.r;\n"
184
"MUL temp.g, temp.g, darkness.g;\n"
185
"MUL temp.b, temp.b, darkness.b;\n"
186
/* for now this just replace smoke shading if rendering fire */
187
"CMP result.color, render.r, temp, spec;\n"
191
const char *shader_color =
193
"PARAM dx = program.local[0];\n"
194
"PARAM darkness = program.local[1];\n"
195
"PARAM render = program.local[2];\n"
196
"PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n"
197
"TEMP temp, shadow, flame, spec, value;\n"
198
"TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
199
"TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
200
"TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
201
"TEX spec, flame.r, texture[3], 1D;\n"
202
/* unpremultiply volume texture */
203
"RCP value.r, temp.a;\n"
204
"MUL temp.r, temp.r, value.r;\n"
205
"MUL temp.g, temp.g, value.r;\n"
206
"MUL temp.b, temp.b, value.r;\n"
207
/* calculate shading factor from density */
208
"MUL value.r, temp.a, darkness.a;\n"
209
"MUL value.r, value.r, dx.r;\n"
210
"MUL value.r, value.r, f.r;\n"
211
"EX2 value.r, -value.r;\n"
213
"SUB temp.a, 1.0, value.r;\n"
215
"MUL temp.r, temp.r, shadow.r;\n"
216
"MUL temp.g, temp.g, shadow.r;\n"
217
"MUL temp.b, temp.b, shadow.r;\n"
218
"MUL temp.r, temp.r, value.r;\n"
219
"MUL temp.g, temp.g, value.r;\n"
220
"MUL temp.b, temp.b, value.r;\n"
221
/* for now this just replace smoke shading if rendering fire */
222
"CMP result.color, render.r, temp, spec;\n"
235
#ifdef DEBUG_DRAW_TIME
239
/* generate flame spectrum texture */
240
#define SPEC_WIDTH 256
241
#define FIRE_THRESH 7
242
#define MAX_FIRE_ALPHA 0.06f
243
#define FULL_ON_FIRE 100
244
spec_data = malloc(SPEC_WIDTH * 4 * sizeof(unsigned char));
245
flame_get_spectrum(spec_data, SPEC_WIDTH, 1500, 3000);
246
spec_pixels = malloc(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float));
247
for (i = 0; i < 16; i++) {
248
for (j = 0; j < 16; j++) {
249
for (k = 0; k < SPEC_WIDTH; k++) {
250
int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4;
251
if (k >= FIRE_THRESH) {
252
spec_pixels[index] = ((float)spec_data[k * 4]) / 255.0f;
253
spec_pixels[index + 1] = ((float)spec_data[k * 4 + 1]) / 255.0f;
254
spec_pixels[index + 2] = ((float)spec_data[k * 4 + 2]) / 255.0f;
255
spec_pixels[index + 3] = MAX_FIRE_ALPHA * (
256
(k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
259
spec_pixels[index] = spec_pixels[index + 1] = spec_pixels[index + 2] = spec_pixels[index + 3] = 0.0f;
265
tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);
228
267
sub_v3_v3v3(size, max, min);
269
/* maxx, maxy, maxz */
231
270
cv[0][0] = max[0];
232
271
cv[0][1] = max[1];
233
272
cv[0][2] = max[2];
273
/* minx, maxy, maxz */
235
274
cv[1][0] = min[0];
236
275
cv[1][1] = max[1];
237
276
cv[1][2] = max[2];
277
/* minx, miny, maxz */
239
278
cv[2][0] = min[0];
240
279
cv[2][1] = min[1];
241
280
cv[2][2] = max[2];
281
/* maxx, miny, maxz */
243
282
cv[3][0] = max[0];
244
283
cv[3][1] = min[1];
245
284
cv[3][2] = max[2];
286
/* maxx, maxy, minz */
248
287
cv[4][0] = max[0];
249
288
cv[4][1] = max[1];
250
289
cv[4][2] = min[2];
290
/* minx, maxy, minz */
252
291
cv[5][0] = min[0];
253
292
cv[5][1] = max[1];
254
293
cv[5][2] = min[2];
294
/* minx, miny, minz */
256
295
cv[6][0] = min[0];
257
296
cv[6][1] = min[1];
258
297
cv[6][2] = min[2];
298
/* maxx, miny, minz */
260
299
cv[7][0] = max[0];
261
300
cv[7][1] = min[1];
262
301
cv[7][2] = min[2];
264
copy_v3_v3(edges[0][0], cv[4]); // maxx, maxy, minz
265
copy_v3_v3(edges[1][0], cv[5]); // minx, maxy, minz
266
copy_v3_v3(edges[2][0], cv[6]); // minx, miny, minz
267
copy_v3_v3(edges[3][0], cv[7]); // maxx, miny, minz
269
copy_v3_v3(edges[4][0], cv[3]); // maxx, miny, maxz
270
copy_v3_v3(edges[5][0], cv[2]); // minx, miny, maxz
271
copy_v3_v3(edges[6][0], cv[6]); // minx, miny, minz
272
copy_v3_v3(edges[7][0], cv[7]); // maxx, miny, minz
274
copy_v3_v3(edges[8][0], cv[1]); // minx, maxy, maxz
275
copy_v3_v3(edges[9][0], cv[2]); // minx, miny, maxz
276
copy_v3_v3(edges[10][0], cv[6]); // minx, miny, minz
277
copy_v3_v3(edges[11][0], cv[5]); // minx, maxy, minz
303
copy_v3_v3(edges[0][0], cv[4]); /* maxx, maxy, minz */
304
copy_v3_v3(edges[1][0], cv[5]); /* minx, maxy, minz */
305
copy_v3_v3(edges[2][0], cv[6]); /* minx, miny, minz */
306
copy_v3_v3(edges[3][0], cv[7]); /* maxx, miny, minz */
308
copy_v3_v3(edges[4][0], cv[3]); /* maxx, miny, maxz */
309
copy_v3_v3(edges[5][0], cv[2]); /* minx, miny, maxz */
310
copy_v3_v3(edges[6][0], cv[6]); /* minx, miny, minz */
311
copy_v3_v3(edges[7][0], cv[7]); /* maxx, miny, minz */
313
copy_v3_v3(edges[8][0], cv[1]); /* minx, maxy, maxz */
314
copy_v3_v3(edges[9][0], cv[2]); /* minx, miny, maxz */
315
copy_v3_v3(edges[10][0], cv[6]); /* minx, miny, minz */
316
copy_v3_v3(edges[11][0], cv[5]); /* minx, maxy, minz */
279
318
// printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]);
280
319
// printf("min[2]: %f, max[2]: %f\n", min[2], max[2]);
297
336
glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
298
337
glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
300
glLoadMatrixf(rv3d->viewmat);
301
// glMultMatrixf(ob->obmat);
303
339
glDepthMask(GL_FALSE);
304
340
glDisable(GL_DEPTH_TEST);
305
341
glEnable(GL_BLEND);
306
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
309
printf("Viewinv:\n");
310
printf("%f, %f, %f\n", rv3d->viewinv[0][0], rv3d->viewinv[0][1], rv3d->viewinv[0][2]);
311
printf("%f, %f, %f\n", rv3d->viewinv[1][0], rv3d->viewinv[1][1], rv3d->viewinv[1][2]);
312
printf("%f, %f, %f\n", rv3d->viewinv[2][0], rv3d->viewinv[2][1], rv3d->viewinv[2][2]);
316
copy_v3_v3(viewnormal, rv3d->viewinv[2]);
317
normalize_v3(viewnormal);
319
// find cube vertex that is closest to the viewer
343
/* find cube vertex that is closest to the viewer */
320
344
for (i = 0; i < 8; i++) {
323
x = cv[i][0] - viewnormal[0];
324
y = cv[i][1] - viewnormal[1];
325
z = cv[i][2] - viewnormal[2];
347
x = cv[i][0] - viewnormal[0] * size[0] * 0.5f;
348
y = cv[i][1] - viewnormal[1] * size[1] * 0.5f;
349
z = cv[i][2] - viewnormal[2] * size[2] * 0.5f;
327
351
if ((x >= min[0]) && (x <= max[0]) &&
328
352
(y >= min[1]) && (y <= max[1]) &&
345
369
glGenProgramsARB(1, &prog);
347
371
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
348
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text);
373
if (sds->active_fields & SM_ACTIVE_COLORS)
374
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color);
376
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic);
351
379
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0);
352
// custom parameter for smoke style (higher = thicker)
353
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0);
380
/* custom parameter for smoke style (higher = thicker) */
381
if (sds->active_fields & SM_ACTIVE_COLORS)
382
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0);
384
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0);
356
387
printf("Your gfx card does not support 3D View smoke drawing.\n");
362
393
printf("No volume shadow\n");
396
GPU_texture_bind(tex_flame, 2);
397
GPU_texture_bind(tex_spec, 3);
364
400
if (!GPU_non_power_of_two_support()) {
365
401
cor[0] = (float)res[0] / (float)power_of_2_max_i(res[0]);
366
402
cor[1] = (float)res[1] / (float)power_of_2_max_i(res[1]);
367
403
cor[2] = (float)res[2] / (float)power_of_2_max_i(res[2]);
370
// our slices are defined by the plane equation a*x + b*y +c*z + d = 0
371
// (a,b,c), the plane normal, are given by viewdir
372
// d is the parameter along the view direction. the first d is given by
373
// inserting previously found vertex into the plane equation
406
/* our slices are defined by the plane equation a*x + b*y +c*z + d = 0
407
* (a,b,c), the plane normal, are given by viewdir
408
* d is the parameter along the view direction. the first d is given by
409
* inserting previously found vertex into the plane equation */
375
411
/* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */
376
ds = (ABS(viewnormal[0]) * size[0] + ABS(viewnormal[1]) * size[1] + ABS(viewnormal[2]) * size[2]);
377
dd = 0.05; // ds/512.0f;
412
ds = (fabsf(viewnormal[0]) * size[0] + fabsf(viewnormal[1]) * size[1] + fabsf(viewnormal[2]) * size[2]);
413
dd = max_fff(sds->global_size[0], sds->global_size[1], sds->global_size[2]) / 128.f;
420
// printf("numpoints: %d\n", numpoints);
422
glColor3f(1.0, 1.0, 1.0);
423
for (i = 0; i < numpoints; i++) {
424
glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
425
(points[i * 3 + 1] - min[1]) * cor[1] / size[1],
426
(points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
427
glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]);
456
/* render fire slice */
457
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
458
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0);
460
glColor3f(1.0, 1.0, 1.0);
461
for (i = 0; i < numpoints; i++) {
462
glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
463
(points[i * 3 + 1] - min[1]) * cor[1] / size[1],
464
(points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
465
glVertex3f(points[i * 3 + 0] / ob->size[0], points[i * 3 + 1] / ob->size[1], points[i * 3 + 2] / ob->size[2]);
469
/* render smoke slice */
470
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
471
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0);
473
glColor3f(1.0, 1.0, 1.0);
474
for (i = 0; i < numpoints; i++) {
475
glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
476
(points[i * 3 + 1] - min[1]) * cor[1] / size[1],
477
(points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
478
glVertex3f(points[i * 3 + 0] / ob->size[0], points[i * 3 + 1] / ob->size[1], points[i * 3 + 2] / ob->size[2]);
435
// printf ( "Draw Time: %f\n",( float ) tval() );
485
#ifdef DEBUG_DRAW_TIME
486
printf("Draw Time: %f\n", (float)TIMEIT_VALUE(draw));
438
491
GPU_texture_unbind(tex_shadow);
439
492
GPU_texture_unbind(tex);
494
GPU_texture_unbind(tex_flame);
495
GPU_texture_unbind(tex_spec);
497
GPU_texture_free(tex_spec);
441
502
if (GLEW_ARB_fragment_program) {
442
503
glDisable(GL_FRAGMENT_PROGRAM_ARB);
454
515
glEnable(GL_DEPTH_TEST);
455
glDepthMask(GL_TRUE);
516
glDepthMask(GL_TRUE);
520
#ifdef SMOKE_DEBUG_VELOCITY
521
void draw_smoke_velocity(SmokeDomainSettings *domain, Object *ob)
525
int *base_res = domain->base_res;
526
int *res = domain->res;
527
int *res_min = domain->res_min;
528
int *res_max = domain->res_max;
529
float *vel_x = smoke_get_velocity_x(domain->fluid);
530
float *vel_y = smoke_get_velocity_y(domain->fluid);
531
float *vel_z = smoke_get_velocity_z(domain->fluid);
534
float *cell_size = domain->cell_size;
535
float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.f;
536
float vf = domain->scale / 16.f * 2.f; /* velocity factor */
540
/* set first position so that it doesn't jump when domain moves */
541
x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size);
542
y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size);
543
z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size);
544
if (x0 < res_min[0]) x0 += step_size;
545
if (y0 < res_min[1]) y0 += step_size;
546
if (z0 < res_min[2]) z0 += step_size;
547
add_v3_v3v3(min, domain->p0, domain->obj_shift_f);
549
for (x = floor(x0); x < res_max[0]; x += step_size)
550
for (y = floor(y0); y < res_max[1]; y += step_size)
551
for (z = floor(z0); z < res_max[2]; z += step_size) {
552
int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1];
554
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]};
555
float vel = sqrtf(vel_x[index] * vel_x[index] + vel_y[index] * vel_y[index] + vel_z[index] * vel_z[index]);
557
/* draw heat as scaled "arrows" */
559
float col_g = 1.0f - vel;
560
CLAMP(col_g, 0.0f, 1.0f);
561
glColor3f(1.0f, col_g, 0.0f);
562
glPointSize(10.0f * vel);
565
glVertex3f(pos[0], pos[1], pos[2]);
566
glVertex3f(pos[0] + vel_x[index] * vf, pos[1] + vel_y[index] * vf, pos[2] + vel_z[index] * vf);
569
glVertex3f(pos[0] + vel_x[index] * vf, pos[1] + vel_y[index] * vf, pos[2] + vel_z[index] * vf);
576
#ifdef SMOKE_DEBUG_HEAT
577
void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob)
581
int *base_res = domain->base_res;
582
int *res = domain->res;
583
int *res_min = domain->res_min;
584
int *res_max = domain->res_max;
585
float *heat = smoke_get_heat(domain->fluid);
588
float *cell_size = domain->cell_size;
589
float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.f;
590
float vf = domain->scale / 16.f * 2.f; /* velocity factor */
592
/* set first position so that it doesn't jump when domain moves */
593
x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size);
594
y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size);
595
z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size);
596
if (x0 < res_min[0]) x0 += step_size;
597
if (y0 < res_min[1]) y0 += step_size;
598
if (z0 < res_min[2]) z0 += step_size;
599
add_v3_v3v3(min, domain->p0, domain->obj_shift_f);
601
for (x = floor(x0); x < res_max[0]; x += step_size)
602
for (y = floor(y0); y < res_max[1]; y += step_size)
603
for (z = floor(z0); z < res_max[2]; z += step_size) {
604
int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1];
606
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]};
608
/* draw heat as different sized points */
609
if (heat[index] >= 0.01f) {
610
float col_gb = 1.0f - heat[index];
611
CLAMP(col_gb, 0.0f, 1.0f);
612
glColor3f(1.0f, col_gb, col_gb);
613
glPointSize(24.0f * heat[index]);
616
glVertex3f(pos[0], pos[1], pos[2]);