svn merge -r 22628:22753 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[blender.git] / source / blender / editors / space_view3d / drawvolume.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Daniel Genrich
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28
29 #include <string.h>
30 #include <math.h>
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include "MEM_guardedalloc.h"
37
38 #include "IMB_imbuf.h"
39
40
41 #include "MTC_matrixops.h"
42
43 #include "DNA_armature_types.h"
44 #include "DNA_boid_types.h"
45 #include "DNA_camera_types.h"
46 #include "DNA_curve_types.h"
47 #include "DNA_constraint_types.h" // for drawing constraint
48 #include "DNA_effect_types.h"
49 #include "DNA_lamp_types.h"
50 #include "DNA_lattice_types.h"
51 #include "DNA_material_types.h"
52 #include "DNA_mesh_types.h"
53 #include "DNA_meshdata_types.h"
54 #include "DNA_meta_types.h"
55 #include "DNA_modifier_types.h"
56 #include "DNA_object_types.h"
57 #include "DNA_object_force.h"
58 #include "DNA_object_fluidsim.h"
59 #include "DNA_particle_types.h"
60 #include "DNA_space_types.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_screen_types.h"
63 #include "DNA_smoke_types.h"
64 #include "DNA_userdef_types.h"
65 #include "DNA_view3d_types.h"
66 #include "DNA_world_types.h"
67
68 #include "BLI_blenlib.h"
69 #include "BLI_arithb.h"
70 #include "BLI_editVert.h"
71 #include "BLI_edgehash.h"
72 #include "BLI_rand.h"
73
74 #include "BKE_anim.h"                   //for the where_on_path function
75 #include "BKE_curve.h"
76 #include "BKE_constraint.h" // for the get_constraint_target function
77 #include "BKE_DerivedMesh.h"
78 #include "BKE_deform.h"
79 #include "BKE_displist.h"
80 #include "BKE_effect.h"
81 #include "BKE_font.h"
82 #include "BKE_global.h"
83 #include "BKE_image.h"
84 #include "BKE_key.h"
85 #include "BKE_lattice.h"
86 #include "BKE_mesh.h"
87 #include "BKE_material.h"
88 #include "BKE_mball.h"
89 #include "BKE_modifier.h"
90 #include "BKE_object.h"
91 #include "BKE_paint.h"
92 #include "BKE_particle.h"
93 #include "BKE_property.h"
94 #include "BKE_smoke.h"
95 #include "BKE_unit.h"
96 #include "BKE_utildefines.h"
97 #include "smoke_API.h"
98
99 #include "BIF_gl.h"
100 #include "BIF_glutil.h"
101
102 #include "GPU_draw.h"
103 #include "GPU_material.h"
104 #include "GPU_extensions.h"
105
106 #include "ED_mesh.h"
107 #include "ED_particle.h"
108 #include "ED_screen.h"
109 #include "ED_types.h"
110 #include "ED_util.h"
111
112 #include "UI_resources.h"
113 #include "UI_interface_icons.h"
114
115 #include "WM_api.h"
116 #include "BLF_api.h"
117
118 #include "GPU_extensions.h"
119
120 #include "view3d_intern.h"      // own include
121
122 struct GPUTexture;
123
124 /* draw slices of smoke is adapted from c++ code authored by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */
125 static float cv[][3] = {
126         {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
127         {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
128 };
129
130 // edges have the form edges[n][0][xyz] + t*edges[n][1][xyz]
131 static float edges[12][2][3] = {
132         {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
133         {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
134         {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
135         {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}},
136
137         {{1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}},
138         {{-1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}},
139         {{-1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}},
140         {{1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}},
141
142         {{-1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
143         {{-1.0f, -1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
144         {{-1.0f, -1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}},
145         {{-1.0f, 1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}}
146 };
147
148 int intersect_edges(float *points, float a, float b, float c, float d)
149 {
150         int i;
151         float t;
152         int numpoints = 0;
153         
154         for (i=0; i<12; i++) {
155                 t = -(a*edges[i][0][0] + b*edges[i][0][1] + c*edges[i][0][2] + d)
156                         / (a*edges[i][1][0] + b*edges[i][1][1] + c*edges[i][1][2]);
157                 if ((t>0)&&(t<2)) {
158                         points[numpoints * 3 + 0] = edges[i][0][0] + edges[i][1][0]*t;
159                         points[numpoints * 3 + 1] = edges[i][0][1] + edges[i][1][1]*t;
160                         points[numpoints * 3 + 2] = edges[i][0][2] + edges[i][1][2]*t;
161                         numpoints++;
162                 }
163         }
164         return numpoints;
165 }
166
167 static int convex(float *p0, float *up, float *a, float *b)
168 {
169         // Vec3 va = a-p0, vb = b-p0;
170         float va[3], vb[3], tmp[3];
171         VECSUB(va, a, p0);
172         VECSUB(vb, b, p0);
173         Crossf(tmp, va, vb);
174         return INPR(up, tmp) >= 0;
175 }
176
177 // copied from gpu_extension.c
178 static int is_pow2(int n)
179 {
180         return ((n)&(n-1))==0;
181 }
182
183 static int larger_pow2(int n)
184 {
185         if (is_pow2(n))
186                 return n;
187
188         while(!is_pow2(n))
189                 n= n&(n-1);
190
191         return n*2;
192 }
193
194 void draw_volume(Scene *scene, ARegion *ar, View3D *v3d, Base *base, GPUTexture *tex, int res[3])
195 {
196         Object *ob = base->object;
197         RegionView3D *rv3d= ar->regiondata;
198
199         float viewnormal[3];
200         int i, j, n;
201         float d, d0, dd;
202         float *points = NULL;
203         int numpoints = 0;
204         float cor[3] = {1.,1.,1.};
205         int gl_depth = 0, gl_blend = 0;
206
207         glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
208         glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
209
210         wmLoadMatrix(rv3d->viewmat);
211         wmMultMatrix(ob->obmat);        
212
213         glDepthMask(GL_FALSE);
214         glDisable(GL_DEPTH_TEST);
215         glEnable(GL_BLEND);
216         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
217
218         // get view vector
219         VECCOPY(viewnormal, rv3d->viewinv[2]);
220         Normalize(viewnormal);
221
222         // find cube vertex that is closest to the viewer
223         for (i=0; i<8; i++) {
224                 float x,y,z;
225
226                 x = cv[i][0] + viewnormal[0];
227                 y = cv[i][1] + viewnormal[1];
228                 z = cv[i][2] + viewnormal[2];
229
230                 if ((x>=-1.0f)&&(x<=1.0f)
231                         &&(y>=-1.0f)&&(y<=1.0f)
232                         &&(z>=-1.0f)&&(z<=1.0f)) {
233                         break;
234                 }
235         }
236
237         GPU_texture_bind(tex, 0);
238
239         if (!GLEW_ARB_texture_non_power_of_two) 
240         {
241         cor[0] = (float)res[0]/(float)larger_pow2(res[0]);
242         cor[1] = (float)res[1]/(float)larger_pow2(res[1]);
243         cor[2] = (float)res[2]/(float)larger_pow2(res[2]);
244         }
245
246         // our slices are defined by the plane equation a*x + b*y +c*z + d = 0
247         // (a,b,c), the plane normal, are given by viewdir
248         // d is the parameter along the view direction. the first d is given by
249         // inserting previously found vertex into the plane equation
250         d0 = -(viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]);
251         dd = 2.0*d0/64.0f;
252         n = 0;
253
254         // printf("d0: %f, dd: %f\n", d0, dd);
255
256         points = MEM_callocN(sizeof(float)*12*3, "smoke_points_preview");
257
258         for (d = d0; d > -d0; d -= dd) {
259                 float p0[3];
260                 // intersect_edges returns the intersection points of all cube edges with
261                 // the given plane that lie within the cube
262                 numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], d);
263
264                 if (numpoints > 2) {
265                         VECCOPY(p0, points);
266
267                         // sort points to get a convex polygon
268                         for(i = 1; i < numpoints - 1; i++)
269                         {
270                                 for(j = i + 1; j < numpoints; j++)
271                                 {
272                                         if(convex(p0, viewnormal, &points[j * 3], &points[i * 3]))
273                                         {
274                                                 float tmp2[3];
275                                                 VECCOPY(tmp2, &points[i * 3]);
276                                                 VECCOPY(&points[i * 3], &points[j * 3]);
277                                                 VECCOPY(&points[j * 3], tmp2);
278                                         }
279                                 }
280                         }
281
282                         glBegin(GL_POLYGON);
283                         for (i = 0; i < numpoints; i++) {
284                                 glColor3f(1.0, 1.0, 1.0);
285                                 glTexCoord3d((points[i * 3 + 0] + 1.0)*cor[0]/2.0, (points[i * 3 + 1] + 1)*cor[1]/2.0, (points[i * 3 + 2] + 1.0)*cor[2]/2.0);
286                                 glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]);
287                         }
288                         glEnd();
289                 }
290                 n++;
291         }
292
293         GPU_texture_unbind(tex);
294
295         MEM_freeN(points);
296
297         if(!gl_blend)
298                 glDisable(GL_BLEND);
299         if(gl_depth)
300         {
301                 glEnable(GL_DEPTH_TEST);
302                 glDepthMask(GL_TRUE);   
303         }
304 }
305