70690e2dce78292c98a61c73f8899fdd4e8cbd77
[blender-staging.git] / source / blender / editors / space_view3d / drawvolume.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Daniel Genrich
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawvolume.c
27  *  \ingroup spview3d
28  */
29
30
31
32 #include <string.h>
33 #include <math.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_scene_types.h"
38 #include "DNA_screen_types.h"
39 #include "DNA_smoke_types.h"
40 #include "DNA_view3d_types.h"
41 #include "DNA_property_types.h"
42
43 #include "BLI_utildefines.h"
44 #include "BLI_blenlib.h"
45 #include "BLI_math.h"
46 #include "BLI_edgehash.h"
47 #include "BLI_rand.h"
48
49 #include "BKE_curve.h"
50 #include "BKE_constraint.h"  /* for the get_constraint_target function */
51 #include "BKE_DerivedMesh.h"
52 #include "BKE_displist.h"
53 #include "BKE_effect.h"
54 #include "BKE_font.h"
55 #include "BKE_global.h"
56 #include "BKE_image.h"
57 #include "BKE_key.h"
58 #include "BKE_lattice.h"
59 #include "BKE_mesh.h"
60 #include "BKE_material.h"
61 #include "BKE_mball.h"
62 #include "BKE_modifier.h"
63 #include "BKE_object.h"
64 #include "BKE_paint.h"
65 #include "BKE_particle.h"
66 #include "BKE_property.h"
67 #include "BKE_smoke.h"
68
69 #include "smoke_API.h"
70
71 #include "BIF_gl.h"
72
73 #include "GPU_extensions.h"
74
75 #include "ED_mesh.h"
76
77
78 #include "BLF_api.h"
79
80
81 #include "view3d_intern.h"  // own include
82
83
84 #ifdef _WIN32
85 #include <time.h>
86 #include <stdio.h>
87 #include <conio.h>
88 #include <windows.h>
89
90 static LARGE_INTEGER liFrequency;
91 static LARGE_INTEGER liStartTime;
92 static LARGE_INTEGER liCurrentTime;
93
94 static void tstart(void)
95 {
96         QueryPerformanceFrequency(&liFrequency);
97         QueryPerformanceCounter(&liStartTime);
98 }
99 static void tend(void)
100 {
101         QueryPerformanceCounter(&liCurrentTime);
102 }
103 static double tval(void)
104 {
105         return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart) * (double)1000.0 / (double)liFrequency.QuadPart));
106 }
107 #else
108 #include <sys/time.h>
109 static struct timeval _tstart, _tend;
110 static struct timezone tz;
111 static void tstart(void)
112 {
113         gettimeofday(&_tstart, &tz);
114 }
115 static void tend(void)
116 {
117         gettimeofday(&_tend, &tz);
118 }
119   #if 0
120 static double tval()
121 {
122         double t1, t2;
123         t1 = ( double ) _tstart.tv_sec * 1000 + ( double ) _tstart.tv_usec / (1000);
124         t2 = ( double ) _tend.tv_sec * 1000 + ( double ) _tend.tv_usec / (1000);
125         return t2 - t1;
126 }
127   #endif
128 #endif
129
130 struct GPUTexture;
131
132 static int intersect_edges(float *points, float a, float b, float c, float d, float edges[12][2][3])
133 {
134         int i;
135         float t;
136         int numpoints = 0;
137
138         for (i = 0; i < 12; i++) {
139                 t = -(a * edges[i][0][0] + b * edges[i][0][1] + c * edges[i][0][2] + d) /
140                      (a * edges[i][1][0] + b * edges[i][1][1] + c * edges[i][1][2]);
141                 if ((t > 0) && (t < 1)) {
142                         points[numpoints * 3 + 0] = edges[i][0][0] + edges[i][1][0] * t;
143                         points[numpoints * 3 + 1] = edges[i][0][1] + edges[i][1][1] * t;
144                         points[numpoints * 3 + 2] = edges[i][0][2] + edges[i][1][2] * t;
145                         numpoints++;
146                 }
147         }
148         return numpoints;
149 }
150
151 static int convex(const float p0[3], const float up[3], const float a[3], const float b[3])
152 {
153         /* Vec3 va = a-p0, vb = b-p0; */
154         float va[3], vb[3], tmp[3];
155         sub_v3_v3v3(va, a, p0);
156         sub_v3_v3v3(vb, b, p0);
157         cross_v3_v3v3(tmp, va, vb);
158         return dot_v3v3(up, tmp) >= 0;
159 }
160
161 void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
162                        GPUTexture *tex, float min[3], float max[3],
163                        int res[3], float dx, float UNUSED(base_scale), float viewnormal[3],
164                        GPUTexture *tex_shadow, GPUTexture *tex_flame)
165 {
166         int i, j, k, n, good_index;
167         float d /*, d0 */ /* UNUSED */, dd, ds;
168         float *points = NULL;
169         int numpoints = 0;
170         float cor[3] = {1.0f, 1.0f, 1.0f};
171         int gl_depth = 0, gl_blend = 0;
172
173         /* draw slices of smoke is adapted from c++ code authored
174          * by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */
175         float cv[][3] = {
176                 {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
177                 {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
178         };
179
180         /* edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] */
181         float edges[12][2][3] = {
182                 {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
183                 {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
184                 {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
185                 {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
186
187                 {{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
188                 {{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
189                 {{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
190                 {{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
191
192                 {{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
193                 {{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
194                 {{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}},
195                 {{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
196         };
197
198         unsigned char *spec_data;
199         float *spec_pixels;
200         GPUTexture *tex_spec;
201
202         /* Fragment program to calculate the view3d of smoke */
203         /* using 4 textures, density, shadow, flame and flame spectrum */
204         const char *shader_basic =
205                 "!!ARBfp1.0\n"
206                 "PARAM dx = program.local[0];\n"
207                 "PARAM darkness = program.local[1];\n"
208                 "PARAM render = program.local[2];\n"
209                 "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
210                 "TEMP temp, shadow, flame, spec, value;\n"
211                 "TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
212                 "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
213                 "TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
214                 "TEX spec, flame.r, texture[3], 1D;\n"
215                 /* calculate shading factor from density */
216                 "MUL value.r, temp.a, darkness.a;\n"
217                 "MUL value.r, value.r, dx.r;\n"
218                 "MUL value.r, value.r, f.r;\n"
219                 "EX2 temp, -value.r;\n"
220                 /* alpha */
221                 "SUB temp.a, 1.0, temp.r;\n"
222                 /* shade colors */
223                 "MUL temp.r, temp.r, shadow.r;\n"
224                 "MUL temp.g, temp.g, shadow.r;\n"
225                 "MUL temp.b, temp.b, shadow.r;\n"
226                 "MUL temp.r, temp.r, darkness.r;\n"
227                 "MUL temp.g, temp.g, darkness.g;\n"
228                 "MUL temp.b, temp.b, darkness.b;\n"
229                 /* for now this just replace smoke shading if rendering fire */
230                 "CMP result.color, render.r, temp, spec;\n"
231                 "END\n";
232
233         /* color shader */
234         const char *shader_color =
235                 "!!ARBfp1.0\n"
236                 "PARAM dx = program.local[0];\n"
237                 "PARAM darkness = program.local[1];\n"
238                 "PARAM render = program.local[2];\n"
239                 "PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n"
240                 "TEMP temp, shadow, flame, spec, value;\n"
241                 "TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
242                 "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
243                 "TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
244                 "TEX spec, flame.r, texture[3], 1D;\n"
245                 /* unpremultiply volume texture */
246                 "RCP value.r, temp.a;\n"
247                 "MUL temp.r, temp.r, value.r;\n"
248                 "MUL temp.g, temp.g, value.r;\n"
249                 "MUL temp.b, temp.b, value.r;\n"
250                 /* calculate shading factor from density */
251                 "MUL value.r, temp.a, darkness.a;\n"
252                 "MUL value.r, value.r, dx.r;\n"
253                 "MUL value.r, value.r, f.r;\n"
254                 "EX2 value.r, -value.r;\n"
255                 /* alpha */
256                 "SUB temp.a, 1.0, value.r;\n"
257                 /* shade colors */
258                 "MUL temp.r, temp.r, shadow.r;\n"
259                 "MUL temp.g, temp.g, shadow.r;\n"
260                 "MUL temp.b, temp.b, shadow.r;\n"
261                 "MUL temp.r, temp.r, value.r;\n"
262                 "MUL temp.g, temp.g, value.r;\n"
263                 "MUL temp.b, temp.b, value.r;\n"
264                 /* for now this just replace smoke shading if rendering fire */
265                 "CMP result.color, render.r, temp, spec;\n"
266                 "END\n";
267
268         GLuint prog;
269
270         
271         float size[3];
272
273         if (!tex) {
274                 printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
275                 return;
276         }
277
278         tstart();
279         /* generate flame spectrum texture */
280         #define SPEC_WIDTH 256
281         #define FIRE_THRESH 7
282         #define MAX_FIRE_ALPHA 0.06f
283         #define FULL_ON_FIRE 100
284         spec_data = malloc(SPEC_WIDTH * 4 * sizeof(unsigned char));
285         flame_get_spectrum(spec_data, SPEC_WIDTH, 1500, 3000);
286         spec_pixels = malloc(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float));
287         for (i = 0; i < 16; i++) {
288                 for (j = 0; j < 16; j++) {
289                         for (k = 0; k < SPEC_WIDTH; k++) {
290                                 int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4;
291                                 if (k >= FIRE_THRESH) {
292                                         spec_pixels[index] = ((float)spec_data[k * 4]) / 255.0f;
293                                         spec_pixels[index + 1] = ((float)spec_data[k * 4 + 1]) / 255.0f;
294                                         spec_pixels[index + 2] = ((float)spec_data[k * 4 + 2]) / 255.0f;
295                                         spec_pixels[index + 3] = MAX_FIRE_ALPHA * (
296                                                 (k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
297                                 }
298                                 else {
299                                         spec_pixels[index] = spec_pixels[index + 1] = spec_pixels[index + 2] = spec_pixels[index + 3] = 0.0f;
300                                 }
301                         }
302                 }
303         }
304
305         tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);
306
307         sub_v3_v3v3(size, max, min);
308
309         /* maxx, maxy, maxz */
310         cv[0][0] = max[0];
311         cv[0][1] = max[1];
312         cv[0][2] = max[2];
313         /* minx, maxy, maxz */
314         cv[1][0] = min[0];
315         cv[1][1] = max[1];
316         cv[1][2] = max[2];
317         /* minx, miny, maxz */
318         cv[2][0] = min[0];
319         cv[2][1] = min[1];
320         cv[2][2] = max[2];
321         /* maxx, miny, maxz */
322         cv[3][0] = max[0];
323         cv[3][1] = min[1];
324         cv[3][2] = max[2];
325
326         /* maxx, maxy, minz */
327         cv[4][0] = max[0];
328         cv[4][1] = max[1];
329         cv[4][2] = min[2];
330         /* minx, maxy, minz */
331         cv[5][0] = min[0];
332         cv[5][1] = max[1];
333         cv[5][2] = min[2];
334         /* minx, miny, minz */
335         cv[6][0] = min[0];
336         cv[6][1] = min[1];
337         cv[6][2] = min[2];
338         /* maxx, miny, minz */
339         cv[7][0] = max[0];
340         cv[7][1] = min[1];
341         cv[7][2] = min[2];
342
343         copy_v3_v3(edges[0][0], cv[4]); /* maxx, maxy, minz */
344         copy_v3_v3(edges[1][0], cv[5]); /* minx, maxy, minz */
345         copy_v3_v3(edges[2][0], cv[6]); /* minx, miny, minz */
346         copy_v3_v3(edges[3][0], cv[7]); /* maxx, miny, minz */
347
348         copy_v3_v3(edges[4][0], cv[3]); /* maxx, miny, maxz */
349         copy_v3_v3(edges[5][0], cv[2]); /* minx, miny, maxz */
350         copy_v3_v3(edges[6][0], cv[6]); /* minx, miny, minz */
351         copy_v3_v3(edges[7][0], cv[7]); /* maxx, miny, minz */
352
353         copy_v3_v3(edges[8][0], cv[1]); /* minx, maxy, maxz */
354         copy_v3_v3(edges[9][0], cv[2]); /* minx, miny, maxz */
355         copy_v3_v3(edges[10][0], cv[6]); /* minx, miny, minz */
356         copy_v3_v3(edges[11][0], cv[5]); /* minx, maxy, minz */
357
358         // printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]);
359         // printf("min[2]: %f, max[2]: %f\n", min[2], max[2]);
360
361         edges[0][1][2] = size[2];
362         edges[1][1][2] = size[2];
363         edges[2][1][2] = size[2];
364         edges[3][1][2] = size[2];
365
366         edges[4][1][1] = size[1];
367         edges[5][1][1] = size[1];
368         edges[6][1][1] = size[1];
369         edges[7][1][1] = size[1];
370
371         edges[8][1][0] = size[0];
372         edges[9][1][0] = size[0];
373         edges[10][1][0] = size[0];
374         edges[11][1][0] = size[0];
375
376         glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
377         glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
378
379         glDepthMask(GL_FALSE);
380         glDisable(GL_DEPTH_TEST);
381         glEnable(GL_BLEND);
382
383         /* find cube vertex that is closest to the viewer */
384         for (i = 0; i < 8; i++) {
385                 float x, y, z;
386
387                 x = cv[i][0] - viewnormal[0] * size[0] * 0.5f;
388                 y = cv[i][1] - viewnormal[1] * size[1] * 0.5f;
389                 z = cv[i][2] - viewnormal[2] * size[2] * 0.5f;
390
391                 if ((x >= min[0]) && (x <= max[0]) &&
392                     (y >= min[1]) && (y <= max[1]) &&
393                     (z >= min[2]) && (z <= max[2]))
394                 {
395                         break;
396                 }
397         }
398
399         if (i >= 8) {
400                 /* fallback, avoid using buffer over-run */
401                 i = 0;
402         }
403
404         // printf("i: %d\n", i);
405         // printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);
406
407         if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) {
408                 glEnable(GL_FRAGMENT_PROGRAM_ARB);
409                 glGenProgramsARB(1, &prog);
410
411                 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
412                 /* set shader */
413                 if (sds->active_fields & SM_ACTIVE_COLORS)
414                         glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color);
415                 else
416                         glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic);
417
418                 /* cell spacing */
419                 glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0);
420                 /* custom parameter for smoke style (higher = thicker) */
421                 if (sds->active_fields & SM_ACTIVE_COLORS)
422                         glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0);
423                 else
424                         glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0);
425         }
426         else
427                 printf("Your gfx card does not support 3D View smoke drawing.\n");
428
429         GPU_texture_bind(tex, 0);
430         if (tex_shadow)
431                 GPU_texture_bind(tex_shadow, 1);
432         else
433                 printf("No volume shadow\n");
434
435         if (tex_flame) {
436                 GPU_texture_bind(tex_flame, 2);
437                 GPU_texture_bind(tex_spec, 3);
438         }
439
440         if (!GPU_non_power_of_two_support()) {
441                 cor[0] = (float)res[0] / (float)power_of_2_max_i(res[0]);
442                 cor[1] = (float)res[1] / (float)power_of_2_max_i(res[1]);
443                 cor[2] = (float)res[2] / (float)power_of_2_max_i(res[2]);
444         }
445
446         /* our slices are defined by the plane equation a*x + b*y +c*z + d = 0
447          * (a,b,c), the plane normal, are given by viewdir
448          * d is the parameter along the view direction. the first d is given by
449          * inserting previously found vertex into the plane equation */
450
451         /* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */
452         ds = (ABS(viewnormal[0]) * size[0] + ABS(viewnormal[1]) * size[1] + ABS(viewnormal[2]) * size[2]);
453         dd = MAX3(sds->global_size[0], sds->global_size[1], sds->global_size[2]) / 128.f;
454         n = 0;
455         good_index = i;
456
457         // printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds);
458
459         points = MEM_callocN(sizeof(float) * 12 * 3, "smoke_points_preview");
460
461         while (1) {
462                 float p0[3];
463                 float tmp_point[3], tmp_point2[3];
464
465                 if (dd * (float)n > ds)
466                         break;
467
468                 copy_v3_v3(tmp_point, viewnormal);
469                 mul_v3_fl(tmp_point, -dd * ((ds / dd) - (float)n));
470                 add_v3_v3v3(tmp_point2, cv[good_index], tmp_point);
471                 d = dot_v3v3(tmp_point2, viewnormal);
472
473                 // printf("my d: %f\n", d);
474
475                 /* intersect_edges returns the intersection points of all cube edges with
476                  * the given plane that lie within the cube */
477                 numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges);
478
479                 // printf("points: %d\n", numpoints);
480
481                 if (numpoints > 2) {
482                         copy_v3_v3(p0, points);
483
484                         /* sort points to get a convex polygon */
485                         for (i = 1; i < numpoints - 1; i++) {
486                                 for (j = i + 1; j < numpoints; j++) {
487                                         if (!convex(p0, viewnormal, &points[j * 3], &points[i * 3])) {
488                                                 float tmp2[3];
489                                                 copy_v3_v3(tmp2, &points[j * 3]);
490                                                 copy_v3_v3(&points[j * 3], &points[i * 3]);
491                                                 copy_v3_v3(&points[i * 3], tmp2);
492                                         }
493                                 }
494                         }
495
496                         /* render fire slice */
497                         glBlendFunc(GL_SRC_ALPHA, GL_ONE);
498                         glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0);
499                         glBegin(GL_POLYGON);
500                         glColor3f(1.0, 1.0, 1.0);
501                         for (i = 0; i < numpoints; i++) {
502                                 glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
503                                              (points[i * 3 + 1] - min[1]) * cor[1] / size[1],
504                                              (points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
505                                 glVertex3f(points[i * 3 + 0] / ob->size[0], points[i * 3 + 1] / ob->size[1], points[i * 3 + 2] / ob->size[2]);
506                         }
507                         glEnd();
508
509                         /* render smoke slice */
510                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
511                         glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0);
512                         glBegin(GL_POLYGON);
513                         glColor3f(1.0, 1.0, 1.0);
514                         for (i = 0; i < numpoints; i++) {
515                                 glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
516                                              (points[i * 3 + 1] - min[1]) * cor[1] / size[1],
517                                              (points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
518                                 glVertex3f(points[i * 3 + 0] / ob->size[0], points[i * 3 + 1] / ob->size[1], points[i * 3 + 2] / ob->size[2]);
519                         }
520                         glEnd();
521                 }
522                 n++;
523         }
524
525         tend();
526         // printf ( "Draw Time: %f\n",(float) tval() );
527
528         if (tex_shadow)
529                 GPU_texture_unbind(tex_shadow);
530         GPU_texture_unbind(tex);
531         if (tex_flame) {
532                 GPU_texture_unbind(tex_flame);
533                 GPU_texture_unbind(tex_spec);
534         }
535         GPU_texture_free(tex_spec);
536
537         free(spec_data);
538         free(spec_pixels);
539
540         if (GLEW_ARB_fragment_program) {
541                 glDisable(GL_FRAGMENT_PROGRAM_ARB);
542                 glDeleteProgramsARB(1, &prog);
543         }
544
545
546         MEM_freeN(points);
547
548         if (!gl_blend) {
549                 glDisable(GL_BLEND);
550         }
551
552         if (gl_depth) {
553                 glEnable(GL_DEPTH_TEST);
554                 glDepthMask(GL_TRUE);
555         }
556 }
557
558 #ifdef SMOKE_DEBUG_VELOCITY
559 void draw_smoke_velocity(SmokeDomainSettings *domain, Object *ob)
560 {
561         float x, y, z;
562         float x0, y0, z0;
563         int *base_res = domain->base_res;
564         int *res = domain->res;
565         int *res_min = domain->res_min;
566         int *res_max = domain->res_max;
567         float *vel_x = smoke_get_velocity_x(domain->fluid);
568         float *vel_y = smoke_get_velocity_y(domain->fluid);
569         float *vel_z = smoke_get_velocity_z(domain->fluid);
570
571         float min[3];
572         float *cell_size = domain->cell_size;
573         float step_size = ((float)MAX3(base_res[0], base_res[1], base_res[2])) / 16.f;
574         float vf = domain->scale / 16.f * 2.f; /* velocity factor */
575
576         glLineWidth(1.0f);
577
578         /* set first position so that it doesn't jump when domain moves */
579         x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size);
580         y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size);
581         z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size);
582         if (x0 < res_min[0]) x0 += step_size;
583         if (y0 < res_min[1]) y0 += step_size;
584         if (z0 < res_min[2]) z0 += step_size;
585         add_v3_v3v3(min, domain->p0, domain->obj_shift_f);
586
587         for (x = floor(x0); x < res_max[0]; x += step_size)
588                 for (y = floor(y0); y < res_max[1]; y += step_size)
589                         for (z = floor(z0); z < res_max[2]; z += step_size) {
590                                 int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1];
591
592                                 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]};
593                                 float vel = sqrtf(vel_x[index] * vel_x[index] + vel_y[index] * vel_y[index] + vel_z[index] * vel_z[index]);
594
595                                 /* draw heat as scaled "arrows" */
596                                 if (vel >= 0.01f) {
597                                         float col_g = 1.0f - vel;
598                                         CLAMP(col_g, 0.0f, 1.0f);
599                                         glColor3f(1.0f, col_g, 0.0f);
600                                         glPointSize(10.0f * vel);
601
602                                         glBegin(GL_LINES);
603                                         glVertex3f(pos[0], pos[1], pos[2]);
604                                         glVertex3f(pos[0] + vel_x[index] * vf, pos[1] + vel_y[index] * vf, pos[2] + vel_z[index] * vf);
605                                         glEnd();
606                                         glBegin(GL_POINTS);
607                                         glVertex3f(pos[0] + vel_x[index] * vf, pos[1] + vel_y[index] * vf, pos[2] + vel_z[index] * vf);
608                                         glEnd();
609                                 }
610                         }
611 }
612 #endif
613
614 #ifdef SMOKE_DEBUG_HEAT
615 void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob)
616 {
617         float x, y, z;
618         float x0, y0, z0;
619         int *base_res = domain->base_res;
620         int *res = domain->res;
621         int *res_min = domain->res_min;
622         int *res_max = domain->res_max;
623         float *heat = smoke_get_heat(domain->fluid);
624
625         float min[3];
626         float *cell_size = domain->cell_size;
627         float step_size = ((float)MAX3(base_res[0], base_res[1], base_res[2])) / 16.f;
628         float vf = domain->scale / 16.f * 2.f; /* velocity factor */
629
630         /* set first position so that it doesn't jump when domain moves */
631         x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size);
632         y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size);
633         z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size);
634         if (x0 < res_min[0]) x0 += step_size;
635         if (y0 < res_min[1]) y0 += step_size;
636         if (z0 < res_min[2]) z0 += step_size;
637         add_v3_v3v3(min, domain->p0, domain->obj_shift_f);
638
639         for (x = floor(x0); x < res_max[0]; x += step_size)
640                 for (y = floor(y0); y < res_max[1]; y += step_size)
641                         for (z = floor(z0); z < res_max[2]; z += step_size) {
642                                 int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1];
643
644                                 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]};
645
646                                 /* draw heat as different sized points */
647                                 if (heat[index] >= 0.01f) {
648                                         float col_gb = 1.0f - heat[index];
649                                         CLAMP(col_gb, 0.0f, 1.0f);
650                                         glColor3f(1.0f, col_gb, col_gb);
651                                         glPointSize(24.0f * heat[index]);
652
653                                         glBegin(GL_POINTS);
654                                         glVertex3f(pos[0], pos[1], pos[2]);
655                                         glEnd();
656                                 }
657                         }
658 }
659 #endif