|
Blender
V2.59
|
00001 /* 00002 * $Id: drawvolume.c 35242 2011-02-27 20:29:51Z jesterking $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * Contributor(s): Daniel Genrich 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00034 #include <string.h> 00035 #include <math.h> 00036 00037 #include "MEM_guardedalloc.h" 00038 00039 #include "DNA_scene_types.h" 00040 #include "DNA_screen_types.h" 00041 #include "DNA_view3d_types.h" 00042 00043 #include "BLI_blenlib.h" 00044 #include "BLI_math.h" 00045 #include "BLI_editVert.h" 00046 #include "BLI_edgehash.h" 00047 #include "BLI_rand.h" 00048 #include "BLI_utildefines.h" 00049 00050 #include "BKE_curve.h" 00051 #include "BKE_constraint.h" // for the get_constraint_target function 00052 #include "BKE_DerivedMesh.h" 00053 #include "BKE_deform.h" 00054 #include "BKE_displist.h" 00055 #include "BKE_effect.h" 00056 #include "BKE_font.h" 00057 #include "BKE_global.h" 00058 #include "BKE_image.h" 00059 #include "BKE_key.h" 00060 #include "BKE_lattice.h" 00061 #include "BKE_mesh.h" 00062 #include "BKE_material.h" 00063 #include "BKE_mball.h" 00064 #include "BKE_modifier.h" 00065 #include "BKE_object.h" 00066 #include "BKE_paint.h" 00067 #include "BKE_particle.h" 00068 #include "BKE_property.h" 00069 #include "BKE_smoke.h" 00070 00071 #include "smoke_API.h" 00072 00073 #include "BIF_gl.h" 00074 00075 #include "GPU_extensions.h" 00076 00077 #include "ED_mesh.h" 00078 00079 00080 #include "BLF_api.h" 00081 00082 00083 #include "view3d_intern.h" // own include 00084 00085 00086 #ifdef _WIN32 00087 #include <time.h> 00088 #include <stdio.h> 00089 #include <conio.h> 00090 #include <windows.h> 00091 00092 static LARGE_INTEGER liFrequency; 00093 static LARGE_INTEGER liStartTime; 00094 static LARGE_INTEGER liCurrentTime; 00095 00096 static void tstart ( void ) 00097 { 00098 QueryPerformanceFrequency ( &liFrequency ); 00099 QueryPerformanceCounter ( &liStartTime ); 00100 } 00101 static void tend ( void ) 00102 { 00103 QueryPerformanceCounter ( &liCurrentTime ); 00104 } 00105 static double tval( void ) 00106 { 00107 return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart)* (double)1000.0/(double)liFrequency.QuadPart )); 00108 } 00109 #else 00110 #include <sys/time.h> 00111 static struct timeval _tstart, _tend; 00112 static struct timezone tz; 00113 static void tstart ( void ) 00114 { 00115 gettimeofday ( &_tstart, &tz ); 00116 } 00117 static void tend ( void ) 00118 { 00119 gettimeofday ( &_tend,&tz ); 00120 } 00121 #if 0 00122 static double tval() 00123 { 00124 double t1, t2; 00125 t1 = ( double ) _tstart.tv_sec*1000 + ( double ) _tstart.tv_usec/ ( 1000 ); 00126 t2 = ( double ) _tend.tv_sec*1000 + ( double ) _tend.tv_usec/ ( 1000 ); 00127 return t2-t1; 00128 } 00129 #endif 00130 #endif 00131 00132 struct GPUTexture; 00133 00134 static int intersect_edges(float *points, float a, float b, float c, float d, float edges[12][2][3]) 00135 { 00136 int i; 00137 float t; 00138 int numpoints = 0; 00139 00140 for (i=0; i<12; i++) { 00141 t = -(a*edges[i][0][0] + b*edges[i][0][1] + c*edges[i][0][2] + d) 00142 / (a*edges[i][1][0] + b*edges[i][1][1] + c*edges[i][1][2]); 00143 if ((t>0)&&(t<1)) { 00144 points[numpoints * 3 + 0] = edges[i][0][0] + edges[i][1][0]*t; 00145 points[numpoints * 3 + 1] = edges[i][0][1] + edges[i][1][1]*t; 00146 points[numpoints * 3 + 2] = edges[i][0][2] + edges[i][1][2]*t; 00147 numpoints++; 00148 } 00149 } 00150 return numpoints; 00151 } 00152 00153 static int convex(float *p0, float *up, float *a, float *b) 00154 { 00155 // Vec3 va = a-p0, vb = b-p0; 00156 float va[3], vb[3], tmp[3]; 00157 VECSUB(va, a, p0); 00158 VECSUB(vb, b, p0); 00159 cross_v3_v3v3(tmp, va, vb); 00160 return INPR(up, tmp) >= 0; 00161 } 00162 00163 // copied from gpu_extension.c 00164 static int is_pow2(int n) 00165 { 00166 return ((n)&(n-1))==0; 00167 } 00168 00169 static int larger_pow2(int n) 00170 { 00171 if (is_pow2(n)) 00172 return n; 00173 00174 while(!is_pow2(n)) 00175 n= n&(n-1); 00176 00177 return n*2; 00178 } 00179 00180 void draw_volume(ARegion *ar, GPUTexture *tex, float *min, float *max, int res[3], float dx, GPUTexture *tex_shadow) 00181 { 00182 RegionView3D *rv3d= ar->regiondata; 00183 00184 float viewnormal[3]; 00185 int i, j, n, good_index; 00186 float d, d0, dd, ds; 00187 float *points = NULL; 00188 int numpoints = 0; 00189 float cor[3] = {1.,1.,1.}; 00190 int gl_depth = 0, gl_blend = 0; 00191 00192 /* draw slices of smoke is adapted from c++ code authored by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */ 00193 float cv[][3] = { 00194 {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f}, 00195 {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f} 00196 }; 00197 00198 // edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] 00199 float edges[12][2][3] = { 00200 {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, 00201 {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, 00202 {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, 00203 {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, 00204 00205 {{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}}, 00206 {{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}}, 00207 {{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}}, 00208 {{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}}, 00209 00210 {{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}}, 00211 {{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}}, 00212 {{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}, 00213 {{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}} 00214 }; 00215 00216 /* Fragment program to calculate the view3d of smoke */ 00217 /* using 2 textures, density and shadow */ 00218 const char *text = "!!ARBfp1.0\n" 00219 "PARAM dx = program.local[0];\n" 00220 "PARAM darkness = program.local[1];\n" 00221 "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n" 00222 "TEMP temp, shadow, value;\n" 00223 "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" 00224 "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" 00225 "MUL value, temp, darkness;\n" 00226 "MUL value, value, dx;\n" 00227 "MUL value, value, f;\n" 00228 "EX2 temp, -value.r;\n" 00229 "SUB temp.a, 1.0, temp.r;\n" 00230 "MUL temp.r, temp.r, shadow.r;\n" 00231 "MUL temp.g, temp.g, shadow.r;\n" 00232 "MUL temp.b, temp.b, shadow.r;\n" 00233 "MOV result.color, temp;\n" 00234 "END\n"; 00235 GLuint prog; 00236 00237 00238 float size[3]; 00239 00240 if(!tex) { 00241 printf("Could not allocate 3D texture for 3D View smoke drawing.\n"); 00242 return; 00243 } 00244 00245 tstart(); 00246 00247 VECSUB(size, max, min); 00248 00249 // maxx, maxy, maxz 00250 cv[0][0] = max[0]; 00251 cv[0][1] = max[1]; 00252 cv[0][2] = max[2]; 00253 // minx, maxy, maxz 00254 cv[1][0] = min[0]; 00255 cv[1][1] = max[1]; 00256 cv[1][2] = max[2]; 00257 // minx, miny, maxz 00258 cv[2][0] = min[0]; 00259 cv[2][1] = min[1]; 00260 cv[2][2] = max[2]; 00261 // maxx, miny, maxz 00262 cv[3][0] = max[0]; 00263 cv[3][1] = min[1]; 00264 cv[3][2] = max[2]; 00265 00266 // maxx, maxy, minz 00267 cv[4][0] = max[0]; 00268 cv[4][1] = max[1]; 00269 cv[4][2] = min[2]; 00270 // minx, maxy, minz 00271 cv[5][0] = min[0]; 00272 cv[5][1] = max[1]; 00273 cv[5][2] = min[2]; 00274 // minx, miny, minz 00275 cv[6][0] = min[0]; 00276 cv[6][1] = min[1]; 00277 cv[6][2] = min[2]; 00278 // maxx, miny, minz 00279 cv[7][0] = max[0]; 00280 cv[7][1] = min[1]; 00281 cv[7][2] = min[2]; 00282 00283 VECCOPY(edges[0][0], cv[4]); // maxx, maxy, minz 00284 VECCOPY(edges[1][0], cv[5]); // minx, maxy, minz 00285 VECCOPY(edges[2][0], cv[6]); // minx, miny, minz 00286 VECCOPY(edges[3][0], cv[7]); // maxx, miny, minz 00287 00288 VECCOPY(edges[4][0], cv[3]); // maxx, miny, maxz 00289 VECCOPY(edges[5][0], cv[2]); // minx, miny, maxz 00290 VECCOPY(edges[6][0], cv[6]); // minx, miny, minz 00291 VECCOPY(edges[7][0], cv[7]); // maxx, miny, minz 00292 00293 VECCOPY(edges[8][0], cv[1]); // minx, maxy, maxz 00294 VECCOPY(edges[9][0], cv[2]); // minx, miny, maxz 00295 VECCOPY(edges[10][0], cv[6]); // minx, miny, minz 00296 VECCOPY(edges[11][0], cv[5]); // minx, maxy, minz 00297 00298 // printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]); 00299 // printf("min[2]: %f, max[2]: %f\n", min[2], max[2]); 00300 00301 edges[0][1][2] = size[2]; 00302 edges[1][1][2] = size[2]; 00303 edges[2][1][2] = size[2]; 00304 edges[3][1][2] = size[2]; 00305 00306 edges[4][1][1] = size[1]; 00307 edges[5][1][1] = size[1]; 00308 edges[6][1][1] = size[1]; 00309 edges[7][1][1] = size[1]; 00310 00311 edges[8][1][0] = size[0]; 00312 edges[9][1][0] = size[0]; 00313 edges[10][1][0] = size[0]; 00314 edges[11][1][0] = size[0]; 00315 00316 glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend); 00317 glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth); 00318 00319 glLoadMatrixf(rv3d->viewmat); 00320 // glMultMatrixf(ob->obmat); 00321 00322 glDepthMask(GL_FALSE); 00323 glDisable(GL_DEPTH_TEST); 00324 glEnable(GL_BLEND); 00325 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00326 00327 /* 00328 printf("Viewinv:\n"); 00329 printf("%f, %f, %f\n", rv3d->viewinv[0][0], rv3d->viewinv[0][1], rv3d->viewinv[0][2]); 00330 printf("%f, %f, %f\n", rv3d->viewinv[1][0], rv3d->viewinv[1][1], rv3d->viewinv[1][2]); 00331 printf("%f, %f, %f\n", rv3d->viewinv[2][0], rv3d->viewinv[2][1], rv3d->viewinv[2][2]); 00332 */ 00333 00334 // get view vector 00335 VECCOPY(viewnormal, rv3d->viewinv[2]); 00336 normalize_v3(viewnormal); 00337 00338 // find cube vertex that is closest to the viewer 00339 for (i=0; i<8; i++) { 00340 float x,y,z; 00341 00342 x = cv[i][0] - viewnormal[0]; 00343 y = cv[i][1] - viewnormal[1]; 00344 z = cv[i][2] - viewnormal[2]; 00345 00346 if ((x>=min[0])&&(x<=max[0]) 00347 &&(y>=min[1])&&(y<=max[1]) 00348 &&(z>=min[2])&&(z<=max[2])) { 00349 break; 00350 } 00351 } 00352 00353 if(i >= 8) { 00354 /* fallback, avoid using buffer over-run */ 00355 i= 0; 00356 } 00357 00358 // printf("i: %d\n", i); 00359 // printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]); 00360 00361 if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) 00362 { 00363 glEnable(GL_FRAGMENT_PROGRAM_ARB); 00364 glGenProgramsARB(1, &prog); 00365 00366 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog); 00367 glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text); 00368 00369 // cell spacing 00370 glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0); 00371 // custom parameter for smoke style (higher = thicker) 00372 glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0); 00373 } 00374 else 00375 printf("Your gfx card does not support 3D View smoke drawing.\n"); 00376 00377 GPU_texture_bind(tex, 0); 00378 if(tex_shadow) 00379 GPU_texture_bind(tex_shadow, 1); 00380 else 00381 printf("No volume shadow\n"); 00382 00383 if (!GPU_non_power_of_two_support()) { 00384 cor[0] = (float)res[0]/(float)larger_pow2(res[0]); 00385 cor[1] = (float)res[1]/(float)larger_pow2(res[1]); 00386 cor[2] = (float)res[2]/(float)larger_pow2(res[2]); 00387 } 00388 00389 // our slices are defined by the plane equation a*x + b*y +c*z + d = 0 00390 // (a,b,c), the plane normal, are given by viewdir 00391 // d is the parameter along the view direction. the first d is given by 00392 // inserting previously found vertex into the plane equation 00393 d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); 00394 ds = (ABS(viewnormal[0])*size[0] + ABS(viewnormal[1])*size[1] + ABS(viewnormal[2])*size[2]); 00395 dd = 0.05; // ds/512.0f; 00396 n = 0; 00397 good_index = i; 00398 00399 // printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds); 00400 00401 points = MEM_callocN(sizeof(float)*12*3, "smoke_points_preview"); 00402 00403 while(1) { 00404 float p0[3]; 00405 float tmp_point[3], tmp_point2[3]; 00406 00407 if(dd*(float)n > ds) 00408 break; 00409 00410 VECCOPY(tmp_point, viewnormal); 00411 mul_v3_fl(tmp_point, -dd*((ds/dd)-(float)n)); 00412 VECADD(tmp_point2, cv[good_index], tmp_point); 00413 d = INPR(tmp_point2, viewnormal); 00414 00415 // printf("my d: %f\n", d); 00416 00417 // intersect_edges returns the intersection points of all cube edges with 00418 // the given plane that lie within the cube 00419 numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges); 00420 00421 // printf("points: %d\n", numpoints); 00422 00423 if (numpoints > 2) { 00424 VECCOPY(p0, points); 00425 00426 // sort points to get a convex polygon 00427 for(i = 1; i < numpoints - 1; i++) 00428 { 00429 for(j = i + 1; j < numpoints; j++) 00430 { 00431 if(!convex(p0, viewnormal, &points[j * 3], &points[i * 3])) 00432 { 00433 float tmp2[3]; 00434 VECCOPY(tmp2, &points[j * 3]); 00435 VECCOPY(&points[j * 3], &points[i * 3]); 00436 VECCOPY(&points[i * 3], tmp2); 00437 } 00438 } 00439 } 00440 00441 // printf("numpoints: %d\n", numpoints); 00442 glBegin(GL_POLYGON); 00443 glColor3f(1.0, 1.0, 1.0); 00444 for (i = 0; i < numpoints; i++) { 00445 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]); 00446 glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]); 00447 } 00448 glEnd(); 00449 } 00450 n++; 00451 } 00452 00453 tend(); 00454 // printf ( "Draw Time: %f\n",( float ) tval() ); 00455 00456 if(tex_shadow) 00457 GPU_texture_unbind(tex_shadow); 00458 GPU_texture_unbind(tex); 00459 00460 if(GLEW_ARB_fragment_program) 00461 { 00462 glDisable(GL_FRAGMENT_PROGRAM_ARB); 00463 glDeleteProgramsARB(1, &prog); 00464 } 00465 00466 00467 MEM_freeN(points); 00468 00469 if(!gl_blend) 00470 glDisable(GL_BLEND); 00471 if(gl_depth) 00472 { 00473 glEnable(GL_DEPTH_TEST); 00474 glDepthMask(GL_TRUE); 00475 } 00476 } 00477