Blender V2.61 - r43446

drawvolume.c

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