This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/editors/space_view3d/drawvolume.c
Campbell Barton 4124804b4e many functions in blender are not marked static but should be.
most local modifier,GPU,ImBuf and Interface functions are now static.

also fixed an error were the fluid modifier definition and the header didnt have the same number of args.
2011-02-13 14:16:36 +00:00

473 lines
12 KiB
C

/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* Contributor(s): Daniel Genrich
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <string.h>
#include <math.h>
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_editVert.h"
#include "BLI_edgehash.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
#include "BKE_curve.h"
#include "BKE_constraint.h" // for the get_constraint_target function
#include "BKE_DerivedMesh.h"
#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_mesh.h"
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_property.h"
#include "BKE_smoke.h"
#include "smoke_API.h"
#include "BIF_gl.h"
#include "GPU_extensions.h"
#include "ED_mesh.h"
#include "BLF_api.h"
#include "view3d_intern.h" // own include
#ifdef _WIN32
#include <time.h>
#include <stdio.h>
#include <conio.h>
#include <windows.h>
static LARGE_INTEGER liFrequency;
static LARGE_INTEGER liStartTime;
static LARGE_INTEGER liCurrentTime;
static void tstart ( void )
{
QueryPerformanceFrequency ( &liFrequency );
QueryPerformanceCounter ( &liStartTime );
}
static void tend ( void )
{
QueryPerformanceCounter ( &liCurrentTime );
}
static double tval( void )
{
return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart)* (double)1000.0/(double)liFrequency.QuadPart ));
}
#else
#include <sys/time.h>
static struct timeval _tstart, _tend;
static struct timezone tz;
static void tstart ( void )
{
gettimeofday ( &_tstart, &tz );
}
static void tend ( void )
{
gettimeofday ( &_tend,&tz );
}
#if 0
static double tval()
{
double t1, t2;
t1 = ( double ) _tstart.tv_sec*1000 + ( double ) _tstart.tv_usec/ ( 1000 );
t2 = ( double ) _tend.tv_sec*1000 + ( double ) _tend.tv_usec/ ( 1000 );
return t2-t1;
}
#endif
#endif
struct GPUTexture;
static int intersect_edges(float *points, float a, float b, float c, float d, float edges[12][2][3])
{
int i;
float t;
int numpoints = 0;
for (i=0; i<12; i++) {
t = -(a*edges[i][0][0] + b*edges[i][0][1] + c*edges[i][0][2] + d)
/ (a*edges[i][1][0] + b*edges[i][1][1] + c*edges[i][1][2]);
if ((t>0)&&(t<1)) {
points[numpoints * 3 + 0] = edges[i][0][0] + edges[i][1][0]*t;
points[numpoints * 3 + 1] = edges[i][0][1] + edges[i][1][1]*t;
points[numpoints * 3 + 2] = edges[i][0][2] + edges[i][1][2]*t;
numpoints++;
}
}
return numpoints;
}
static int convex(float *p0, float *up, float *a, float *b)
{
// Vec3 va = a-p0, vb = b-p0;
float va[3], vb[3], tmp[3];
VECSUB(va, a, p0);
VECSUB(vb, b, p0);
cross_v3_v3v3(tmp, va, vb);
return INPR(up, tmp) >= 0;
}
// copied from gpu_extension.c
static int is_pow2(int n)
{
return ((n)&(n-1))==0;
}
static int larger_pow2(int n)
{
if (is_pow2(n))
return n;
while(!is_pow2(n))
n= n&(n-1);
return n*2;
}
void draw_volume(ARegion *ar, GPUTexture *tex, float *min, float *max, int res[3], float dx, GPUTexture *tex_shadow)
{
RegionView3D *rv3d= ar->regiondata;
float viewnormal[3];
int i, j, n, good_index;
float d, d0, dd, ds;
float *points = NULL;
int numpoints = 0;
float cor[3] = {1.,1.,1.};
int gl_depth = 0, gl_blend = 0;
/* draw slices of smoke is adapted from c++ code authored by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */
float cv[][3] = {
{1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
{1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
};
// edges have the form edges[n][0][xyz] + t*edges[n][1][xyz]
float edges[12][2][3] = {
{{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
{{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
{{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
{{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
{{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
{{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
{{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
{{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
{{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
{{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
{{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}},
{{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
};
/* Fragment program to calculate the view3d of smoke */
/* using 2 textures, density and shadow */
const char *text = "!!ARBfp1.0\n"
"PARAM dx = program.local[0];\n"
"PARAM darkness = program.local[1];\n"
"PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
"TEMP temp, shadow, value;\n"
"TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
"TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
"MUL value, temp, darkness;\n"
"MUL value, value, dx;\n"
"MUL value, value, f;\n"
"EX2 temp, -value.r;\n"
"SUB temp.a, 1.0, temp.r;\n"
"MUL temp.r, temp.r, shadow.r;\n"
"MUL temp.g, temp.g, shadow.r;\n"
"MUL temp.b, temp.b, shadow.r;\n"
"MOV result.color, temp;\n"
"END\n";
GLuint prog;
float size[3];
if(!tex) {
printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
return;
}
tstart();
VECSUB(size, max, min);
// maxx, maxy, maxz
cv[0][0] = max[0];
cv[0][1] = max[1];
cv[0][2] = max[2];
// minx, maxy, maxz
cv[1][0] = min[0];
cv[1][1] = max[1];
cv[1][2] = max[2];
// minx, miny, maxz
cv[2][0] = min[0];
cv[2][1] = min[1];
cv[2][2] = max[2];
// maxx, miny, maxz
cv[3][0] = max[0];
cv[3][1] = min[1];
cv[3][2] = max[2];
// maxx, maxy, minz
cv[4][0] = max[0];
cv[4][1] = max[1];
cv[4][2] = min[2];
// minx, maxy, minz
cv[5][0] = min[0];
cv[5][1] = max[1];
cv[5][2] = min[2];
// minx, miny, minz
cv[6][0] = min[0];
cv[6][1] = min[1];
cv[6][2] = min[2];
// maxx, miny, minz
cv[7][0] = max[0];
cv[7][1] = min[1];
cv[7][2] = min[2];
VECCOPY(edges[0][0], cv[4]); // maxx, maxy, minz
VECCOPY(edges[1][0], cv[5]); // minx, maxy, minz
VECCOPY(edges[2][0], cv[6]); // minx, miny, minz
VECCOPY(edges[3][0], cv[7]); // maxx, miny, minz
VECCOPY(edges[4][0], cv[3]); // maxx, miny, maxz
VECCOPY(edges[5][0], cv[2]); // minx, miny, maxz
VECCOPY(edges[6][0], cv[6]); // minx, miny, minz
VECCOPY(edges[7][0], cv[7]); // maxx, miny, minz
VECCOPY(edges[8][0], cv[1]); // minx, maxy, maxz
VECCOPY(edges[9][0], cv[2]); // minx, miny, maxz
VECCOPY(edges[10][0], cv[6]); // minx, miny, minz
VECCOPY(edges[11][0], cv[5]); // minx, maxy, minz
// printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]);
// printf("min[2]: %f, max[2]: %f\n", min[2], max[2]);
edges[0][1][2] = size[2];
edges[1][1][2] = size[2];
edges[2][1][2] = size[2];
edges[3][1][2] = size[2];
edges[4][1][1] = size[1];
edges[5][1][1] = size[1];
edges[6][1][1] = size[1];
edges[7][1][1] = size[1];
edges[8][1][0] = size[0];
edges[9][1][0] = size[0];
edges[10][1][0] = size[0];
edges[11][1][0] = size[0];
glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
glLoadMatrixf(rv3d->viewmat);
// glMultMatrixf(ob->obmat);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/*
printf("Viewinv:\n");
printf("%f, %f, %f\n", rv3d->viewinv[0][0], rv3d->viewinv[0][1], rv3d->viewinv[0][2]);
printf("%f, %f, %f\n", rv3d->viewinv[1][0], rv3d->viewinv[1][1], rv3d->viewinv[1][2]);
printf("%f, %f, %f\n", rv3d->viewinv[2][0], rv3d->viewinv[2][1], rv3d->viewinv[2][2]);
*/
// get view vector
VECCOPY(viewnormal, rv3d->viewinv[2]);
normalize_v3(viewnormal);
// find cube vertex that is closest to the viewer
for (i=0; i<8; i++) {
float x,y,z;
x = cv[i][0] - viewnormal[0];
y = cv[i][1] - viewnormal[1];
z = cv[i][2] - viewnormal[2];
if ((x>=min[0])&&(x<=max[0])
&&(y>=min[1])&&(y<=max[1])
&&(z>=min[2])&&(z<=max[2])) {
break;
}
}
if(i >= 8) {
/* fallback, avoid using buffer over-run */
i= 0;
}
// printf("i: %d\n", i);
// printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);
if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program"))
{
glEnable(GL_FRAGMENT_PROGRAM_ARB);
glGenProgramsARB(1, &prog);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text);
// cell spacing
glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0);
// custom parameter for smoke style (higher = thicker)
glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0);
}
else
printf("Your gfx card does not support 3D View smoke drawing.\n");
GPU_texture_bind(tex, 0);
if(tex_shadow)
GPU_texture_bind(tex_shadow, 1);
else
printf("No volume shadow\n");
if (!GPU_non_power_of_two_support()) {
cor[0] = (float)res[0]/(float)larger_pow2(res[0]);
cor[1] = (float)res[1]/(float)larger_pow2(res[1]);
cor[2] = (float)res[2]/(float)larger_pow2(res[2]);
}
// our slices are defined by the plane equation a*x + b*y +c*z + d = 0
// (a,b,c), the plane normal, are given by viewdir
// d is the parameter along the view direction. the first d is given by
// inserting previously found vertex into the plane equation
d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]);
ds = (ABS(viewnormal[0])*size[0] + ABS(viewnormal[1])*size[1] + ABS(viewnormal[2])*size[2]);
dd = 0.05; // ds/512.0f;
n = 0;
good_index = i;
// printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds);
points = MEM_callocN(sizeof(float)*12*3, "smoke_points_preview");
while(1) {
float p0[3];
float tmp_point[3], tmp_point2[3];
if(dd*(float)n > ds)
break;
VECCOPY(tmp_point, viewnormal);
mul_v3_fl(tmp_point, -dd*((ds/dd)-(float)n));
VECADD(tmp_point2, cv[good_index], tmp_point);
d = INPR(tmp_point2, viewnormal);
// printf("my d: %f\n", d);
// intersect_edges returns the intersection points of all cube edges with
// the given plane that lie within the cube
numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges);
// printf("points: %d\n", numpoints);
if (numpoints > 2) {
VECCOPY(p0, points);
// sort points to get a convex polygon
for(i = 1; i < numpoints - 1; i++)
{
for(j = i + 1; j < numpoints; j++)
{
if(!convex(p0, viewnormal, &points[j * 3], &points[i * 3]))
{
float tmp2[3];
VECCOPY(tmp2, &points[j * 3]);
VECCOPY(&points[j * 3], &points[i * 3]);
VECCOPY(&points[i * 3], tmp2);
}
}
}
// printf("numpoints: %d\n", numpoints);
glBegin(GL_POLYGON);
glColor3f(1.0, 1.0, 1.0);
for (i = 0; i < numpoints; i++) {
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]);
glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]);
}
glEnd();
}
n++;
}
tend();
// printf ( "Draw Time: %f\n",( float ) tval() );
if(tex_shadow)
GPU_texture_unbind(tex_shadow);
GPU_texture_unbind(tex);
if(GLEW_ARB_fragment_program)
{
glDisable(GL_FRAGMENT_PROGRAM_ARB);
glDeleteProgramsARB(1, &prog);
}
MEM_freeN(points);
if(!gl_blend)
glDisable(GL_BLEND);
if(gl_depth)
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
}