Blender  V2.59
drawvolume.c
Go to the documentation of this file.
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