Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Genrich <daniel.genrich@gmx.net>2009-07-30 19:00:26 +0400
committerDaniel Genrich <daniel.genrich@gmx.net>2009-07-30 19:00:26 +0400
commit58c88bcf7636abce291168af189284181f2f7033 (patch)
treef99c18e5601242113b0d3888331578d5b0966c59 /source/blender
parent1b26fe50c35afe5c83a0bf3a69fce55db00374d3 (diff)
BF2.5: First commit of smoke code.
Not working: a) rendering (since volumterics branch is not merged yet) b) moving collision objects of any kind c) saving of collision objects (because that's what I am working on) d) pointcache e) A bunch of other things I already know of So please do not report any bugs on this one yet :-)
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_smoke.h55
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/SConscript1
-rw-r--r--source/blender/blenkernel/intern/modifier.c106
-rw-r--r--source/blender/blenkernel/intern/smoke.c1342
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h2
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c183
-rw-r--r--source/blender/blenloader/intern/readfile.c65
-rw-r--r--source/blender/blenloader/intern/writefile.c13
-rw-r--r--source/blender/editors/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_view3d/SConscript1
-rw-r--r--source/blender/editors/space_view3d/drawobject.c331
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h18
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h112
-rw-r--r--source/blender/makesdna/intern/makesdna.c2
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/makesrna.c1
-rw-r--r--source/blender/makesrna/intern/rna_internal.h1
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c53
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c263
20 files changed, 2474 insertions, 80 deletions
diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h
new file mode 100644
index 00000000000..b37e1d08fcc
--- /dev/null
+++ b/source/blender/blenkernel/BKE_smoke.h
@@ -0,0 +1,55 @@
+/**
+ * BKE_cloth.h
+ *
+ * $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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Daniel Genrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BKE_SMOKE_H_
+#define BKE_SMOKE_H_
+
+void smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm);
+
+void smokeModifier_free (struct SmokeModifierData *smd);
+void smokeModifier_reset(struct SmokeModifierData *smd);
+void smokeModifier_createType(struct SmokeModifierData *smd);
+
+void smoke_set_tray(struct SmokeModifierData *smd, size_t index, float transparency);
+float smoke_get_tray(struct SmokeModifierData *smd, size_t index);
+float smoke_get_tvox(struct SmokeModifierData *smd, size_t index);
+void smoke_set_tvox(struct SmokeModifierData *smd, size_t index, float tvox);
+
+void smoke_set_bigtray(struct SmokeModifierData *smd, size_t index, float transparency);
+float smoke_get_bigtray(struct SmokeModifierData *smd, size_t index);
+float smoke_get_bigtvox(struct SmokeModifierData *smd, size_t index);
+void smoke_set_bigtvox(struct SmokeModifierData *smd, size_t index, float tvox);
+
+long long smoke_get_mem_req(int xres, int yres, int zres, int amplify);
+void smoke_prepare_View(struct SmokeModifierData *smd, float *light);
+void smoke_prepare_bigView(struct SmokeModifierData *smd, float *light);
+
+#endif /* BKE_SMOKE_H_ */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 92cc206667c..656a292da15 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -32,7 +32,7 @@ SET(INC
../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern
../../../intern/iksolver/extern ../blenloader ../quicktime
../../../extern/bullet2/src
- ../nodes ../../../extern/glew/include ../gpu ../makesrna
+ ../nodes ../../../extern/glew/include ../gpu ../makesrna ../../../intern/smoke/extern
../../../intern/bsp/extern
${ZLIB_INC}
)
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index dbc990d0613..7016d992f02 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -10,6 +10,7 @@ incs += ' #/intern/iksolver/extern ../blenloader'
incs += ' #/extern/bullet2/src'
incs += ' #/intern/opennl/extern #/intern/bsp/extern'
incs += ' ../gpu #/extern/glew/include'
+incs += ' #/intern/smoke/extern'
incs += ' ' + env['BF_OPENGL_INC']
incs += ' ' + env['BF_ZLIB_INC']
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index c129e8ed99b..8935d33b3bf 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -58,6 +58,7 @@
#include "DNA_cloth_types.h"
#include "DNA_curve_types.h"
#include "DNA_effect_types.h"
+#include "DNA_group_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -67,6 +68,7 @@
#include "DNA_object_force.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
+#include "DNA_smoke_types.h"
#include "DNA_texture_types.h"
#include "BLI_editVert.h"
@@ -96,6 +98,7 @@
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
+#include "BKE_smoke.h"
#include "BKE_softbody.h"
#include "BKE_subsurf.h"
#include "BKE_texture.h"
@@ -5787,6 +5790,100 @@ static int softbodyModifier_dependsOnTime(ModifierData *md)
return 1;
}
+/* Smoke */
+
+static void smokeModifier_initData(ModifierData *md)
+{
+ SmokeModifierData *smd = (SmokeModifierData*) md;
+
+ smd->domain = NULL;
+ smd->flow = NULL;
+ smd->coll = NULL;
+ smd->type = 0;
+ smd->time = -1;
+
+ /*
+ smd->fluid = NULL;
+ smd->maxres = 48;
+ smd->amplify = 4;
+ smd->omega = 0.5;
+ smd->time = 0;
+ smd->flags = 0;
+ smd->noise = MOD_SMOKE_NOISEWAVE;
+ smd->visibility = 1;
+
+ // init 3dview buffer
+ smd->tvox = NULL;
+ smd->tray = NULL;
+ smd->tvoxbig = NULL;
+ smd->traybig = NULL;
+ smd->viewsettings = 0;
+ smd->bind = NULL;
+ smd->max_textures = 0;
+ */
+}
+
+static void smokeModifier_freeData(ModifierData *md)
+{
+ SmokeModifierData *smd = (SmokeModifierData*) md;
+
+ smokeModifier_free (smd);
+}
+
+static void smokeModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
+{
+ SmokeModifierData *smd = (SmokeModifierData*) md;
+ DerivedMesh *dm = NULL;
+
+ if(derivedData) dm = derivedData;
+ else if(ob->type == OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
+ else return;
+
+ CDDM_apply_vert_coords(dm, vertexCos);
+ CDDM_calc_normals(dm);
+
+ smokeModifier_do(smd, md->scene, ob, dm);
+
+ if(dm != derivedData) dm->release(dm);
+}
+
+static int smokeModifier_dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+
+static void smokeModifier_updateDepgraph(
+ ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
+ DagNode *obNode)
+{
+ SmokeModifierData *smd = (SmokeModifierData *) md;
+ /*
+ if(smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
+ {
+ if(smd->domain->fluid_group)
+ {
+ GroupObject *go = NULL;
+
+ for(go = smd->domain->fluid_group->gobject.first; go; go = go->next)
+ {
+ if(go->ob)
+ {
+ SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke);
+
+ // check for initialized smoke object
+ if(smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)
+ {
+ DagNode *curNode = dag_get_node(forest, go->ob);
+ dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Smoke Flow");
+ }
+ }
+ }
+ }
+ }
+ */
+}
/* Cloth */
@@ -8477,6 +8574,15 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
| eModifierTypeFlag_Single;
mti->deformVerts = softbodyModifier_deformVerts;
mti->dependsOnTime = softbodyModifier_dependsOnTime;
+
+ mti = INIT_TYPE(Smoke);
+ mti->type = eModifierTypeType_OnlyDeform;
+ mti->initData = smokeModifier_initData;
+ mti->freeData = smokeModifier_freeData;
+ mti->flags = eModifierTypeFlag_AcceptsMesh;
+ mti->deformVerts = smokeModifier_deformVerts;
+ mti->dependsOnTime = smokeModifier_dependsOnTime;
+ mti->updateDepgraph = smokeModifier_updateDepgraph;
mti = INIT_TYPE(Cloth);
mti->type = eModifierTypeType_Nonconstructive;
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
new file mode 100644
index 00000000000..941381f04f3
--- /dev/null
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -0,0 +1,1342 @@
+/**
+ * BKE_cloth.h
+ *
+ * $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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Daniel Genrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <GL/glew.h>
+
+#include "MEM_guardedalloc.h"
+
+#include <float.h>
+#include <math.h>
+#include "stdio.h"
+
+#include "BLI_linklist.h"
+#include "BLI_rand.h"
+#include "BLI_jitter.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_edgehash.h"
+#include "BLI_kdtree.h"
+#include "BLI_kdopbvh.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_modifier.h"
+#include "BKE_particle.h"
+#include "BKE_utildefines.h"
+
+#include "DNA_customdata_types.h"
+#include "DNA_group_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_smoke_types.h"
+
+#include "smoke_API.h"
+
+#include "BKE_smoke.h"
+
+#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()
+{
+ 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 );
+}
+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
+
+struct Object;
+struct Scene;
+struct DerivedMesh;
+struct SmokeModifierData;
+
+// forward declerations
+static void get_cell(struct SmokeModifierData *smd, float *pos, int *cell, int correct);
+static void get_bigcell(struct SmokeModifierData *smd, float *pos, int *cell, int correct);
+void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *tris, int numfaces, int numtris, int **tridivs, float cell_len);
+
+#define TRI_UVOFFSET (1./4.)
+
+int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm)
+{
+ if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid)
+ {
+ size_t i;
+ float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
+ float size[3];
+ MVert *verts = dm->getVertArray(dm);
+ float scale = 0.0;
+ int res = smd->domain->maxres;
+
+ // get BB of domain
+ for(i = 0; i < dm->getNumVerts(dm); i++)
+ {
+ float tmp[3];
+
+ VECCOPY(tmp, verts[i].co);
+ Mat4MulVecfl(ob->obmat, tmp);
+
+ // min BB
+ min[0] = MIN2(min[0], tmp[0]);
+ min[1] = MIN2(min[1], tmp[1]);
+ min[2] = MIN2(min[2], tmp[2]);
+
+ // max BB
+ max[0] = MAX2(max[0], tmp[0]);
+ max[1] = MAX2(max[1], tmp[1]);
+ max[2] = MAX2(max[2], tmp[2]);
+ }
+
+ VECCOPY(smd->domain->p0, min);
+ VECCOPY(smd->domain->p1, max);
+
+ // calc other res with max_res provided
+ VECSUB(size, max, min);
+ if(size[0] > size[1])
+ {
+ if(size[0] > size[1])
+ {
+ scale = res / size[0];
+ smd->domain->dx = size[0] / res;
+ smd->domain->res[0] = res;
+ smd->domain->res[1] = (int)(size[1] * scale + 0.5);
+ smd->domain->res[2] = (int)(size[2] * scale + 0.5);
+ }
+ else
+ {
+ scale = res / size[1];
+ smd->domain->dx = size[1] / res;
+ smd->domain->res[1] = res;
+ smd->domain->res[0] = (int)(size[0] * scale + 0.5);
+ smd->domain->res[2] = (int)(size[2] * scale + 0.5);
+ }
+ }
+ else
+ {
+ if(size[1] > size[2])
+ {
+ scale = res / size[1];
+ smd->domain->dx = size[1] / res;
+ smd->domain->res[1] = res;
+ smd->domain->res[0] = (int)(size[0] * scale + 0.5);
+ smd->domain->res[2] = (int)(size[2] * scale + 0.5);
+ }
+ else
+ {
+ scale = res / size[2];
+ smd->domain->dx = size[2] / res;
+ smd->domain->res[2] = res;
+ smd->domain->res[0] = (int)(size[0] * scale + 0.5);
+ smd->domain->res[1] = (int)(size[1] * scale + 0.5);
+ }
+ }
+
+ printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
+
+ // dt max is 0.1
+ smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->amplify, smd->domain->p0, smd->domain->p1, 2.5 / FPS);
+ smd->time = scene->r.cfra;
+ smd->domain->firstframe = smd->time;
+
+ smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta));
+
+ return 1;
+ }
+ else if((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow)
+ {
+ // handle flow object here
+ // XXX TODO
+
+ smd->time = scene->r.cfra;
+
+ // update particle lifetime to be one frame
+ // smd->flow->psys->part->lifetime = scene->r.efra + 1;
+
+ return 1;
+ }
+ else if((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll)
+ {
+ smd->time = scene->r.cfra;
+
+ if(!smd->coll->points)
+ {
+ // init collision points
+ SmokeCollSettings *scs = smd->coll;
+ MVert *mvert = dm->getVertArray(dm);
+ MFace *mface = dm->getFaceArray(dm);
+ size_t i = 0, divs = 0;
+ int *tridivs = NULL;
+ float cell_len = 1.0 / 50.0; // for res = 50
+ size_t newdivs = 0;
+ size_t max_points = 0;
+ size_t quads = 0, facecounter = 0;
+
+ // count quads
+ for(i = 0; i < dm->getNumFaces(dm); i++)
+ {
+ if(mface[i].v4)
+ quads++;
+ }
+
+ calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumFaces(dm), dm->getNumFaces(dm) + quads, &tridivs, cell_len);
+
+ // count triangle divisions
+ for(i = 0; i < dm->getNumFaces(dm) + quads; i++)
+ {
+ divs += (tridivs[3 * i] + 1) * (tridivs[3 * i + 1] + 1) * (tridivs[3 * i + 2] + 1);
+ }
+
+ // printf("divs: %d\n", divs);
+
+ scs->points = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPoints");
+
+ for(i = 0; i < dm->getNumVerts(dm); i++)
+ {
+ float tmpvec[3];
+ VECCOPY(tmpvec, mvert[i].co);
+ Mat4MulVecfl (ob->obmat, tmpvec);
+ VECCOPY(&scs->points[i * 3], tmpvec);
+ }
+
+ for(i = 0, facecounter = 0; i < dm->getNumFaces(dm); i++)
+ {
+ int again = 0;
+ do
+ {
+ size_t j, k;
+ int divs1 = tridivs[3 * facecounter + 0];
+ int divs2 = tridivs[3 * facecounter + 1];
+ int divs3 = tridivs[3 * facecounter + 2];
+ float side1[3], side2[3], trinormorg[3], trinorm[3];
+
+ if(again == 1 && mface[i].v4)
+ {
+ VECSUB(side1, mvert[ mface[i].v3 ].co, mvert[ mface[i].v1 ].co);
+ VECSUB(side2, mvert[ mface[i].v4 ].co, mvert[ mface[i].v1 ].co);
+ }
+ else
+ {
+ VECSUB(side1, mvert[ mface[i].v2 ].co, mvert[ mface[i].v1 ].co);
+ VECSUB(side2, mvert[ mface[i].v3 ].co, mvert[ mface[i].v1 ].co);
+ }
+
+ Crossf(trinormorg, side1, side2);
+ Normalize(trinormorg);
+ VECCOPY(trinorm, trinormorg);
+ VecMulf(trinorm, 0.25 * cell_len);
+
+ for(j = 0; j <= divs1; j++)
+ {
+ for(k = 0; k <= divs2; k++)
+ {
+ float p1[3], p2[3], p3[3], p[3]={0,0,0};
+ const float uf = (float)(j + TRI_UVOFFSET) / (float)(divs1 + 0.0);
+ const float vf = (float)(k + TRI_UVOFFSET) / (float)(divs2 + 0.0);
+ float tmpvec[3];
+
+ if(uf+vf > 1.0)
+ {
+ // printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2);
+ continue;
+ }
+
+ VECCOPY(p1, mvert[ mface[i].v1 ].co);
+ if(again == 1 && mface[i].v4)
+ {
+ VECCOPY(p2, mvert[ mface[i].v3 ].co);
+ VECCOPY(p3, mvert[ mface[i].v4 ].co);
+ }
+ else
+ {
+ VECCOPY(p2, mvert[ mface[i].v2 ].co);
+ VECCOPY(p3, mvert[ mface[i].v3 ].co);
+ }
+
+ VecMulf(p1, (1.0-uf-vf));
+ VecMulf(p2, uf);
+ VecMulf(p3, vf);
+
+ VECADD(p, p1, p2);
+ VECADD(p, p, p3);
+
+ if(newdivs > divs)
+ printf("mem problem\n");
+
+ // mMovPoints.push_back(p + trinorm);
+ VECCOPY(tmpvec, p);
+ VECADD(tmpvec, tmpvec, trinorm);
+ Mat4MulVecfl (ob->obmat, tmpvec);
+ VECCOPY(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec);
+ newdivs++;
+
+ if(newdivs > divs)
+ printf("mem problem\n");
+
+ // mMovPoints.push_back(p - trinorm);
+ VECCOPY(tmpvec, p);
+ VECSUB(tmpvec, tmpvec, trinorm);
+ Mat4MulVecfl (ob->obmat, tmpvec);
+ VECCOPY(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec);
+ newdivs++;
+ }
+ }
+
+ if(again == 0 && mface[i].v4)
+ again++;
+ else
+ again = 0;
+
+ facecounter++;
+
+ } while(again!=0);
+ }
+
+ scs->numpoints = dm->getNumVerts(dm) + newdivs;
+
+ MEM_freeN(tridivs);
+ }
+
+ }
+
+ return 0;
+}
+
+/*! init triangle divisions */
+void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *faces, int numfaces, int numtris, int **tridivs, float cell_len)
+{
+ // mTriangleDivs1.resize( faces.size() );
+ // mTriangleDivs2.resize( faces.size() );
+ // mTriangleDivs3.resize( faces.size() );
+
+ size_t i = 0, facecounter = 0;
+ float maxscale[3] = {1,1,1}; // = channelFindMaxVf(mcScale);
+ float maxpart = ABS(maxscale[0]);
+ float scaleFac = 0;
+ float fsTri = 0;
+ if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
+ if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
+ scaleFac = 1.0 / maxpart;
+ // featureSize = mLevel[mMaxRefine].nodeSize
+ fsTri = cell_len * 0.5 * scaleFac;
+
+ if(*tridivs)
+ MEM_freeN(*tridivs);
+
+ *tridivs = MEM_callocN(sizeof(int) * numtris * 3, "Smoke_Tridivs");
+
+ for(i = 0, facecounter = 0; i < numfaces; i++)
+ {
+ float p0[3], p1[3], p2[3];
+ float side1[3];
+ float side2[3];
+ float side3[3];
+ int divs1=0, divs2=0, divs3=0;
+
+ VECCOPY(p0, verts[faces[i].v1].co);
+ Mat4MulVecfl (ob->obmat, p0);
+ VECCOPY(p1, verts[faces[i].v2].co);
+ Mat4MulVecfl (ob->obmat, p1);
+ VECCOPY(p2, verts[faces[i].v3].co);
+ Mat4MulVecfl (ob->obmat, p2);
+
+ VECSUB(side1, p1, p0);
+ VECSUB(side2, p2, p0);
+ VECSUB(side3, p1, p2);
+
+ if(INPR(side1, side1) > fsTri*fsTri)
+ {
+ float tmp = Normalize(side1);
+ divs1 = (int)(tmp/fsTri);
+ }
+ if(INPR(side2, side2) > fsTri*fsTri)
+ {
+ float tmp = Normalize(side2);
+ divs2 = (int)(tmp/fsTri);
+
+ /*
+ // debug
+ if(i==0)
+ printf("b tmp: %f, fsTri: %f, divs2: %d\n", tmp, fsTri, divs2);
+ */
+ }
+
+ (*tridivs)[3 * facecounter + 0] = divs1;
+ (*tridivs)[3 * facecounter + 1] = divs2;
+ (*tridivs)[3 * facecounter + 2] = divs3;
+
+ // TODO quad case
+ if(faces[i].v4)
+ {
+ divs1=0, divs2=0, divs3=0;
+
+ facecounter++;
+
+ VECCOPY(p1, verts[faces[i].v3].co);
+ Mat4MulVecfl (ob->obmat, p1);
+ VECCOPY(p2, verts[faces[i].v4].co);
+ Mat4MulVecfl (ob->obmat, p2);
+
+ VECSUB(side1, p1, p0);
+ VECSUB(side2, p2, p0);
+ VECSUB(side3, p1, p2);
+
+ if(INPR(side1, side1) > fsTri*fsTri)
+ {
+ float tmp = Normalize(side1);
+ divs1 = (int)(tmp/fsTri);
+ }
+ if(INPR(side2, side2) > fsTri*fsTri)
+ {
+ float tmp = Normalize(side2);
+ divs2 = (int)(tmp/fsTri);
+ }
+
+ (*tridivs)[3 * facecounter + 0] = divs1;
+ (*tridivs)[3 * facecounter + 1] = divs2;
+ (*tridivs)[3 * facecounter + 2] = divs3;
+ }
+ facecounter++;
+ }
+}
+
+void smokeModifier_freeDomain(SmokeModifierData *smd)
+{
+ if(smd->domain)
+ {
+ // free visualisation buffers
+ if(smd->domain->bind)
+ {
+ glDeleteTextures(smd->domain->max_textures, smd->domain->bind);
+ MEM_freeN(smd->domain->bind);
+ }
+ smd->domain->max_textures = 0; // unnecessary but let's be sure
+
+ if(smd->domain->tray)
+ MEM_freeN(smd->domain->tray);
+ if(smd->domain->tvox)
+ MEM_freeN(smd->domain->tvox);
+ if(smd->domain->traybig)
+ MEM_freeN(smd->domain->traybig);
+ if(smd->domain->tvoxbig)
+ MEM_freeN(smd->domain->tvoxbig);
+
+ if(smd->domain->fluid)
+ {
+ smoke_free(smd->domain->fluid);
+ }
+ MEM_freeN(smd->domain);
+ smd->domain = NULL;
+ }
+}
+
+void smokeModifier_freeFlow(SmokeModifierData *smd)
+{
+ if(smd->flow)
+ {
+ MEM_freeN(smd->flow);
+ smd->flow = NULL;
+ }
+}
+
+void smokeModifier_freeCollision(SmokeModifierData *smd)
+{
+ if(smd->coll)
+ {
+ if(smd->coll->points)
+ {
+ MEM_freeN(smd->coll->points);
+ smd->coll->points = NULL;
+ }
+
+ MEM_freeN(smd->coll);
+ smd->coll = NULL;
+ }
+}
+
+void smokeModifier_reset(struct SmokeModifierData *smd)
+{
+ if(smd)
+ {
+ if(smd->domain)
+ {
+ // free visualisation buffers
+ if(smd->domain->bind)
+ {
+ glDeleteTextures(smd->domain->max_textures, smd->domain->bind);
+ MEM_freeN(smd->domain->bind);
+ smd->domain->bind = NULL;
+ }
+ smd->domain->max_textures = 0;
+ smd->domain->viewsettings = 0; // reset view for new frame
+
+ if(smd->domain->tray)
+ MEM_freeN(smd->domain->tray);
+ if(smd->domain->tvox)
+ MEM_freeN(smd->domain->tvox);
+ if(smd->domain->traybig)
+ MEM_freeN(smd->domain->traybig);
+ if(smd->domain->tvoxbig)
+ MEM_freeN(smd->domain->tvoxbig);
+
+ smd->domain->tvox = NULL;
+ smd->domain->tray = NULL;
+ smd->domain->tvoxbig = NULL;
+ smd->domain->traybig = NULL;
+
+ if(smd->domain->fluid)
+ {
+ smoke_free(smd->domain->fluid);
+ smd->domain->fluid = NULL;
+ }
+ }
+ else if(smd->flow)
+ {
+
+ }
+ else if(smd->coll)
+ {
+ if(smd->coll->points)
+ {
+ MEM_freeN(smd->coll->points);
+ smd->coll->points = NULL;
+ }
+ }
+ }
+}
+
+void smokeModifier_free (SmokeModifierData *smd)
+{
+ if(smd)
+ {
+ smokeModifier_freeDomain(smd);
+ smokeModifier_freeFlow(smd);
+ smokeModifier_freeCollision(smd);
+ }
+}
+
+void smokeModifier_createType(struct SmokeModifierData *smd)
+{
+ if(smd)
+ {
+ if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
+ {
+ if(smd->domain)
+ smokeModifier_freeDomain(smd);
+
+ smd->domain = MEM_callocN(sizeof(SmokeDomainSettings), "SmokeDomain");
+
+ smd->domain->smd = smd;
+
+ /* set some standard values */
+ smd->domain->fluid = NULL;
+ smd->domain->eff_group = NULL;
+ smd->domain->fluid_group = NULL;
+ smd->domain->coll_group = NULL;
+ smd->domain->maxres = 48;
+ smd->domain->amplify = 4;
+ smd->domain->omega = 0.5;
+ smd->domain->alpha = -0.001;
+ smd->domain->beta = 0.1;
+ smd->domain->flags = 0;
+ smd->domain->noise = MOD_SMOKE_NOISEWAVE;
+ smd->domain->visibility = 1;
+
+ // init 3dview buffer
+ smd->domain->tvox = NULL;
+ smd->domain->tray = NULL;
+ smd->domain->tvoxbig = NULL;
+ smd->domain->traybig = NULL;
+ smd->domain->viewsettings = 0;
+ smd->domain->bind = NULL;
+ smd->domain->max_textures = 0;
+ }
+ else if(smd->type & MOD_SMOKE_TYPE_FLOW)
+ {
+ if(smd->flow)
+ smokeModifier_freeFlow(smd);
+
+ smd->flow = MEM_callocN(sizeof(SmokeFlowSettings), "SmokeFlow");
+
+ smd->flow->smd = smd;
+
+ /* set some standard values */
+ smd->flow->density = 1.0;
+ smd->flow->temp = 1.0;
+
+ smd->flow->psys = NULL;
+
+ }
+ else if(smd->type & MOD_SMOKE_TYPE_COLL)
+ {
+ if(smd->coll)
+ smokeModifier_freeCollision(smd);
+
+ smd->coll = MEM_callocN(sizeof(SmokeCollSettings), "SmokeColl");
+
+ smd->coll->smd = smd;
+ smd->coll->points = NULL;
+ smd->coll->numpoints = 0;
+ }
+ }
+}
+
+// forward declaration
+void smoke_calc_transparency(struct SmokeModifierData *smd, float *light, int big);
+
+void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
+{
+ int new = 0;
+
+ if(scene->r.cfra >= smd->time)
+ smokeModifier_init(smd, ob, scene, dm);
+
+ if((smd->type & MOD_SMOKE_TYPE_FLOW))
+ {
+ if(scene->r.cfra > smd->time)
+ {
+ // XXX TODO
+ }
+ else if(scene->r.cfra < smd->time)
+ {
+ smd->time = scene->r.cfra;
+ smokeModifier_reset(smd);
+ }
+ }
+ else if((smd->type & MOD_SMOKE_TYPE_DOMAIN))
+ {
+ SmokeDomainSettings *sds = smd->domain;
+
+ if(scene->r.cfra > smd->time)
+ {
+ GroupObject *go = NULL;
+ Base *base = NULL;
+ int cnt_domain = 0;
+
+ tstart();
+
+ sds->viewsettings = 0; // reset view for new frame
+
+ // check for 2nd domain, if not there -> no groups are necessary
+ for(base = scene->base.first; base; base= base->next)
+ {
+ Object *ob1= base->object;
+
+ if(ob1 && ob1 != ob)
+ {
+ ModifierData *tmd = modifiers_findByType(ob1, eModifierType_Smoke);
+
+ if(tmd && tmd->mode & (eModifierMode_Realtime | eModifierMode_Render))
+ {
+ SmokeModifierData *tsmd = (SmokeModifierData *)tmd;
+
+ if((tsmd->type & MOD_SMOKE_TYPE_DOMAIN))
+ {
+ cnt_domain++;
+ }
+ }
+ }
+ }
+
+ // do flows and fluids
+ if(sds->fluid_group || !cnt_domain)
+ {
+ Object *otherobj = NULL;
+ ModifierData *md = NULL;
+
+ if(cnt_domain && !sds->fluid_group) // we use groups since we have 2 domains
+ go = sds->fluid_group->gobject.first;
+ else
+ base = scene->base.first;
+
+ while(base || go)
+ {
+ otherobj = NULL;
+
+ if(cnt_domain && !sds->fluid_group)
+ {
+ if(go->ob)
+ otherobj = go->ob;
+ }
+ else
+ otherobj = base->object;
+
+ if(!otherobj)
+ {
+ if(cnt_domain && !sds->fluid_group)
+ go = go->next;
+ else
+ base= base->next;
+
+ continue;
+ }
+
+ md = modifiers_findByType(otherobj, eModifierType_Smoke);
+
+ // check for active smoke modifier
+ if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
+ {
+ SmokeModifierData *smd2 = (SmokeModifierData *)md;
+
+ // check for initialized smoke object
+ if((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)
+ {
+ // we got nice flow object
+ SmokeFlowSettings *sfs = smd2->flow;
+
+ if(sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected
+ {
+ ParticleSystem *psys = sfs->psys;
+ ParticleSettings *part=psys->part;
+ ParticleData *pa = NULL;
+ int p = 0;
+ float *density = smoke_get_density(sds->fluid);
+ float *bigdensity = smoke_get_bigdensity(sds->fluid);
+ float *heat = smoke_get_heat(sds->fluid);
+ float *velocity_x = smoke_get_velocity_x(sds->fluid);
+ float *velocity_y = smoke_get_velocity_y(sds->fluid);
+ float *velocity_z = smoke_get_velocity_z(sds->fluid);
+ int bigres[3];
+
+ smoke_get_bigres(smd->domain->fluid, bigres);
+
+ // mostly copied from particle code
+ for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++)
+ {
+ int cell[3];
+ int valid = 1;
+ size_t i = 0;
+ size_t index = 0;
+
+ if(pa->alive == PARS_KILLED) continue;
+ else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue;
+ else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue;
+ else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue;
+
+ // VECCOPY(pos, pa->state.co);
+ // Mat4MulVecfl (ob->imat, pos);
+
+ // 1. get corresponding cell
+ get_cell(smd, pa->state.co, cell, 0);
+
+ // check if cell is valid (in the domain boundary)
+ for(i = 0; i < 3; i++)
+ if((cell[i] > sds->res[i] - 1) || (cell[i] < 0))
+ valid = 0;
+
+ if(!valid)
+ continue;
+
+ // 2. set cell values (heat, density and velocity)
+ index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2], sds->res[2]);
+
+ heat[index] = sfs->temp;
+ density[index] = sfs->density;
+ velocity_x[index] = pa->state.vel[0];
+ velocity_y[index] = pa->state.vel[1];
+ velocity_z[index] = pa->state.vel[2];
+
+ // we need different handling for the high-res feature
+ if(bigdensity)
+ {
+ // init all surrounding cells according to amplification, too
+ int i, j, k;
+ for(i = 0; i < smd->domain->amplify; i++)
+ for(j = 0; j < smd->domain->amplify; j++)
+ for(k = 0; k < smd->domain->amplify; k++)
+ {
+ index = smoke_get_index(smd->domain->amplify * cell[0] + i, bigres[0], smd->domain->amplify * cell[1] + j, bigres[1], smd->domain->amplify * cell[2] + k, bigres[2]);
+ bigdensity[index] = sfs->density;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(cnt_domain && !sds->fluid_group)
+ go = go->next;
+ else
+ base= base->next;
+ }
+ }
+
+ // do effectors
+ /*
+ if(sds->eff_group)
+ {
+ for(go = sds->eff_group->gobject.first; go; go = go->next)
+ {
+ if(go->ob)
+ {
+ if(ob->pd)
+ {
+
+ }
+ }
+ }
+ }
+ */
+
+ // do collisions
+ if(sds->coll_group || !cnt_domain)
+ {
+ Object *otherobj = NULL;
+ ModifierData *md = NULL;
+
+ if(cnt_domain && !sds->coll_group) // we use groups since we have 2 domains
+ go = sds->coll_group->gobject.first;
+ else
+ base = scene->base.first;
+
+ while(base || go)
+ {
+ otherobj = NULL;
+
+ if(cnt_domain && !sds->coll_group)
+ {
+ if(go->ob)
+ otherobj = go->ob;
+ }
+ else
+ otherobj = base->object;
+
+ if(!otherobj)
+ {
+ if(cnt_domain && !sds->coll_group)
+ go = go->next;
+ else
+ base= base->next;
+
+ continue;
+ }
+
+ md = modifiers_findByType(otherobj, eModifierType_Smoke);
+
+ // check for active smoke modifier
+ if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
+ {
+ SmokeModifierData *smd2 = (SmokeModifierData *)md;
+
+ if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll)
+ {
+ // we got nice collision object
+ SmokeCollSettings *scs = smd2->coll;
+ int cell[3];
+ int valid = 1;
+ size_t index = 0;
+ size_t i, j;
+ unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid);
+
+ for(i = 0; i < scs->numpoints; i++)
+ {
+ // 1. get corresponding cell
+ get_cell(smd, &scs->points[3 * i], cell, 0);
+
+ // check if cell is valid (in the domain boundary)
+ for(j = 0; j < 3; j++)
+ if((cell[j] > sds->res[j] - 1) || (cell[j] < 0))
+ valid = 0;
+
+ if(!valid)
+ continue;
+
+ // 2. set cell values (heat, density and velocity)
+ index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2], sds->res[2]);
+
+ obstacles[index] = 1;
+
+ /*
+ const LbmFloat maxVelVal = 0.1666;
+ const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5;
+
+ LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); {
+ const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5;
+ USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz);
+ if(usqr>maxusqr) {
+ // cutoff at maxVelVal
+ for(int jj=0; jj<3; jj++) {
+ if(objvel[jj]>0.) objvel[jj] = maxVelVal;
+ if(objvel[jj]<0.) objvel[jj] = -maxVelVal;
+ }
+ } }
+
+ const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) );
+ const LbmVec oldov=objvel; // debug
+ objvel = vec2L((*pNormals)[n]) *dp;
+ */
+ }
+ }
+ }
+
+ if(cnt_domain && !sds->coll_group)
+ go = go->next;
+ else
+ base= base->next;
+ }
+ }
+
+ // set new time
+ smd->time = scene->r.cfra;
+
+ // simulate the actual smoke (c++ code in intern/smoke)
+ smoke_step(sds->fluid);
+
+ tend();
+ printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() );
+ }
+ else if(scene->r.cfra < smd->time)
+ {
+ // we got back in time, reset smoke in this case (TODO: use cache later)
+ smd->time = scene->r.cfra;
+ smokeModifier_reset(smd);
+ }
+ }
+}
+
+// update necessary information for 3dview
+void smoke_prepare_View(SmokeModifierData *smd, float *light)
+{
+ float *density = NULL;
+ size_t i = 0;
+ int x, y, z;
+
+ if(!smd->domain->tray)
+ {
+ // TRay is for self shadowing
+ smd->domain->tray = MEM_callocN(sizeof(float)*smd->domain->res[0]*smd->domain->res[1]*smd->domain->res[2], "Smoke_tRay");
+ }
+ if(!smd->domain->tvox)
+ {
+ // TVox is for tranaparency
+ smd->domain->tvox = MEM_callocN(sizeof(float)*smd->domain->res[0]*smd->domain->res[1]*smd->domain->res[2], "Smoke_tVox");
+ }
+
+ // update 3dview
+ density = smoke_get_density(smd->domain->fluid);
+ for(x = 0; x < smd->domain->res[0]; x++)
+ for(y = 0; y < smd->domain->res[1]; y++)
+ for(z = 0; z < smd->domain->res[2]; z++)
+ {
+ size_t index;
+
+ index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z, smd->domain->res[2]);
+ // Transparency computation
+ // formula taken from "Visual Simulation of Smoke" / Fedkiw et al. pg. 4
+ // T_vox = exp(-C_ext * h)
+ // C_ext/sigma_t = density * C_ext
+ smoke_set_tvox(smd, index, exp(-density[index] * smd->domain->dx));
+ }
+ smoke_calc_transparency(smd, light, 0);
+}
+
+// update necessary information for 3dview ("high res" option)
+void smoke_prepare_bigView(SmokeModifierData *smd, float *light)
+{
+ float *density = NULL;
+ size_t i = 0;
+ int bigres[3];
+
+ smoke_get_bigres(smd->domain->fluid, bigres);
+
+ if(!smd->domain->traybig)
+ {
+ // TRay is for self shadowing
+ smd->domain->traybig = MEM_callocN(sizeof(float)*bigres[0]*bigres[1]*bigres[2], "Smoke_tRayBig");
+ }
+ if(!smd->domain->tvoxbig)
+ {
+ // TVox is for tranaparency
+ smd->domain->tvoxbig = MEM_callocN(sizeof(float)*bigres[0]*bigres[1]*bigres[2], "Smoke_tVoxBig");
+ }
+
+ density = smoke_get_bigdensity(smd->domain->fluid);
+ for (i = 0; i < bigres[0] * bigres[1] * bigres[2]; i++)
+ {
+ // Transparency computation
+ // formula taken from "Visual Simulation of Smoke" / Fedkiw et al. pg. 4
+ // T_vox = exp(-C_ext * h)
+ // C_ext/sigma_t = density * C_ext
+ smoke_set_bigtvox(smd, i, exp(-density[i] * smd->domain->dx / smd->domain->amplify) );
+ }
+ smoke_calc_transparency(smd, light, 1);
+}
+
+
+float smoke_get_tvox(SmokeModifierData *smd, size_t index)
+{
+ return smd->domain->tvox[index];
+}
+
+void smoke_set_tvox(SmokeModifierData *smd, size_t index, float tvox)
+{
+ smd->domain->tvox[index] = tvox;
+}
+
+float smoke_get_tray(SmokeModifierData *smd, size_t index)
+{
+ return smd->domain->tray[index];
+}
+
+void smoke_set_tray(SmokeModifierData *smd, size_t index, float transparency)
+{
+ smd->domain->tray[index] = transparency;
+}
+
+float smoke_get_bigtvox(SmokeModifierData *smd, size_t index)
+{
+ return smd->domain->tvoxbig[index];
+}
+
+void smoke_set_bigtvox(SmokeModifierData *smd, size_t index, float tvox)
+{
+ smd->domain->tvoxbig[index] = tvox;
+}
+
+float smoke_get_bigtray(SmokeModifierData *smd, size_t index)
+{
+ return smd->domain->traybig[index];
+}
+
+void smoke_set_bigtray(SmokeModifierData *smd, size_t index, float transparency)
+{
+ smd->domain->traybig[index] = transparency;
+}
+
+long long smoke_get_mem_req(int xres, int yres, int zres, int amplify)
+{
+ int totalCells = xres * yres * zres;
+ int amplifiedCells = totalCells * amplify * amplify * amplify;
+
+ // print out memory requirements
+ long long int coarseSize = sizeof(float) * totalCells * 22 +
+ sizeof(unsigned char) * totalCells;
+
+ long long int fineSize = sizeof(float) * amplifiedCells * 7 + // big grids
+ sizeof(float) * totalCells * 8 + // small grids
+ sizeof(float) * 128 * 128 * 128; // noise tile
+
+ long long int totalMB = (coarseSize + fineSize) / (1024 * 1024);
+
+ return totalMB;
+}
+
+
+static void calc_voxel_transp(SmokeModifierData *smd, int *pixel, float *tRay)
+{
+ // printf("Pixel(%d, %d, %d)\n", pixel[0], pixel[1], pixel[2]);
+ const size_t index = smoke_get_index(pixel[0], smd->domain->res[0], pixel[1], smd->domain->res[1], pixel[2], smd->domain->res[2]);
+
+ // T_ray *= T_vox
+ *tRay *= smoke_get_tvox(smd, index);
+}
+
+static void calc_voxel_transp_big(SmokeModifierData *smd, int *pixel, float *tRay)
+{
+ int bigres[3];
+ size_t index;
+
+ smoke_get_bigres(smd->domain->fluid, bigres);
+ index = smoke_get_index(pixel[0], bigres[0], pixel[1], bigres[1], pixel[2], bigres[2]);
+
+ /*
+ if(index > bigres[0]*bigres[1]*bigres[2])
+ printf("pixel[0]: %d, [1]: %d, [2]: %d\n", pixel[0], pixel[1], pixel[2]);
+ */
+
+ // T_ray *= T_vox
+ *tRay *= smoke_get_bigtvox(smd, index);
+}
+
+static void bresenham_linie_3D(SmokeModifierData *smd, int x1, int y1, int z1, int x2, int y2, int z2, float *tRay, int big)
+{
+ int dx, dy, dz, i, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2;
+ int pixel[3];
+
+ pixel[0] = x1;
+ pixel[1] = y1;
+ pixel[2] = z1;
+
+ dx = x2 - x1;
+ dy = y2 - y1;
+ dz = z2 - z1;
+
+ x_inc = (dx < 0) ? -1 : 1;
+ l = abs(dx);
+ y_inc = (dy < 0) ? -1 : 1;
+ m = abs(dy);
+ z_inc = (dz < 0) ? -1 : 1;
+ n = abs(dz);
+ dx2 = l << 1;
+ dy2 = m << 1;
+ dz2 = n << 1;
+
+ if ((l >= m) && (l >= n)) {
+ err_1 = dy2 - l;
+ err_2 = dz2 - l;
+ for (i = 0; i < l; i++) {
+ if(!big)
+ calc_voxel_transp(smd, pixel, tRay);
+ else
+ calc_voxel_transp_big(smd, pixel, tRay);
+ if(tRay < 0)
+ return;
+ if (err_1 > 0) {
+ pixel[1] += y_inc;
+ err_1 -= dx2;
+ }
+ if (err_2 > 0) {
+ pixel[2] += z_inc;
+ err_2 -= dx2;
+ }
+ err_1 += dy2;
+ err_2 += dz2;
+ pixel[0] += x_inc;
+ }
+ } else if ((m >= l) && (m >= n)) {
+ err_1 = dx2 - m;
+ err_2 = dz2 - m;
+ for (i = 0; i < m; i++) {
+ if(!big)
+ calc_voxel_transp(smd, pixel, tRay);
+ else
+ calc_voxel_transp_big(smd, pixel, tRay);
+ if(tRay < 0)
+ return;
+ if (err_1 > 0) {
+ pixel[0] += x_inc;
+ err_1 -= dy2;
+ }
+ if (err_2 > 0) {
+ pixel[2] += z_inc;
+ err_2 -= dy2;
+ }
+ err_1 += dx2;
+ err_2 += dz2;
+ pixel[1] += y_inc;
+ }
+ } else {
+ err_1 = dy2 - n;
+ err_2 = dx2 - n;
+ for (i = 0; i < n; i++) {
+ if(!big)
+ calc_voxel_transp(smd, pixel, tRay);
+ else
+ calc_voxel_transp_big(smd, pixel, tRay);
+ if(tRay < 0)
+ return;
+ if (err_1 > 0) {
+ pixel[1] += y_inc;
+ err_1 -= dz2;
+ }
+ if (err_2 > 0) {
+ pixel[0] += x_inc;
+ err_2 -= dz2;
+ }
+ err_1 += dy2;
+ err_2 += dx2;
+ pixel[2] += z_inc;
+ }
+ }
+ if(!big)
+ calc_voxel_transp(smd, pixel, tRay);
+ else
+ calc_voxel_transp_big(smd, pixel, tRay);
+}
+
+static void get_cell(struct SmokeModifierData *smd, float *pos, int *cell, int correct)
+{
+ float tmp[3];
+
+ VECSUB(tmp, pos, smd->domain->p0);
+ VecMulf(tmp, 1.0 / smd->domain->dx);
+
+ if(correct)
+ {
+ cell[0] = MIN2(smd->domain->res[0] - 1, MAX2(0, (int)(tmp[0] + 0.5)));
+ cell[1] = MIN2(smd->domain->res[1] - 1, MAX2(0, (int)(tmp[1] + 0.5)));
+ cell[2] = MIN2(smd->domain->res[2] - 1, MAX2(0, (int)(tmp[2] + 0.5)));
+ }
+ else
+ {
+ cell[0] = (int)(tmp[0] + 0.5);
+ cell[1] = (int)(tmp[1] + 0.5);
+ cell[2] = (int)(tmp[2] + 0.5);
+ }
+}
+static void get_bigcell(struct SmokeModifierData *smd, float *pos, int *cell, int correct)
+{
+ float tmp[3];
+ int res[3];
+ smoke_get_bigres(smd->domain->fluid, res);
+
+ VECSUB(tmp, pos, smd->domain->p0);
+
+ VecMulf(tmp, smd->domain->amplify / smd->domain->dx );
+
+ if(correct)
+ {
+ cell[0] = MIN2(res[0] - 1, MAX2(0, (int)(tmp[0] + 0.5)));
+ cell[1] = MIN2(res[1] - 1, MAX2(0, (int)(tmp[1] + 0.5)));
+ cell[2] = MIN2(res[2] - 1, MAX2(0, (int)(tmp[2] + 0.5)));
+ }
+ else
+ {
+ cell[0] = (int)(tmp[0] + 0.5);
+ cell[1] = (int)(tmp[1] + 0.5);
+ cell[2] = (int)(tmp[2] + 0.5);
+ }
+}
+
+
+void smoke_calc_transparency(struct SmokeModifierData *smd, float *light, int big)
+{
+ int x, y, z;
+ float bv[6];
+ int res[3];
+ float bigfactor = 1.0;
+
+ // x
+ bv[0] = smd->domain->p0[0];
+ bv[1] = smd->domain->p1[0];
+ // y
+ bv[2] = smd->domain->p0[1];
+ bv[3] = smd->domain->p1[1];
+ // z
+ bv[4] = smd->domain->p0[2];
+ bv[5] = smd->domain->p1[2];
+/*
+ printf("bv[0]: %f, [1]: %f, [2]: %f, [3]: %f, [4]: %f, [5]: %f\n", bv[0], bv[1], bv[2], bv[3], bv[4], bv[5]);
+
+ printf("p0[0]: %f, p0[1]: %f, p0[2]: %f\n", smd->domain->p0[0], smd->domain->p0[1], smd->domain->p0[2]);
+ printf("p1[0]: %f, p1[1]: %f, p1[2]: %f\n", smd->domain->p1[0], smd->domain->p1[1], smd->domain->p1[2]);
+ printf("dx: %f, amp: %d\n", smd->domain->dx, smd->domain->amplify);
+*/
+ if(!big)
+ {
+ res[0] = smd->domain->res[0];
+ res[1] = smd->domain->res[1];
+ res[2] = smd->domain->res[2];
+ }
+ else
+ {
+ smoke_get_bigres(smd->domain->fluid, res);
+ bigfactor = 1.0 / smd->domain->amplify;
+ }
+
+#pragma omp parallel for schedule(static) private(y, z) shared(big, smd, light, res, bigfactor)
+ for(x = 0; x < res[0]; x++)
+ for(y = 0; y < res[1]; y++)
+ for(z = 0; z < res[2]; z++)
+ {
+ float voxelCenter[3];
+ size_t index;
+ float pos[3];
+ int cell[3];
+ float tRay = 1.0;
+
+ index = smoke_get_index(x, res[0], y, res[1], z, res[2]);
+
+ // voxelCenter = m_voxelarray[i].GetCenter();
+ voxelCenter[0] = smd->domain->p0[0] + smd->domain->dx * bigfactor * x + smd->domain->dx * bigfactor * 0.5;
+ voxelCenter[1] = smd->domain->p0[1] + smd->domain->dx * bigfactor * y + smd->domain->dx * bigfactor * 0.5;
+ voxelCenter[2] = smd->domain->p0[2] + smd->domain->dx * bigfactor * z + smd->domain->dx * bigfactor * 0.5;
+
+ // printf("vc[0]: %f, vc[1]: %f, vc[2]: %f\n", voxelCenter[0], voxelCenter[1], voxelCenter[2]);
+ // printf("light[0]: %f, light[1]: %f, light[2]: %f\n", light[0], light[1], light[2]);
+
+ // get starting position (in voxel coords)
+ if(BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON)
+ {
+ // we're ouside
+ // printf("out: pos[0]: %f, pos[1]: %f, pos[2]: %f\n", pos[0], pos[1], pos[2]);
+ if(!big)
+ get_cell(smd, pos, cell, 1);
+ else
+ get_bigcell(smd, pos, cell, 1);
+ }
+ else
+ {
+ // printf("in: pos[0]: %f, pos[1]: %f, pos[2]: %f\n", light[0], light[1], light[2]);
+ // we're inside
+ if(!big)
+ get_cell(smd, light, cell, 1);
+ else
+ get_bigcell(smd, light, cell, 1);
+ }
+
+ // printf("cell - [0]: %d, [1]: %d, [2]: %d\n", cell[0], cell[1], cell[2]);
+ bresenham_linie_3D(smd, cell[0], cell[1], cell[2], x, y, z, &tRay, big);
+
+ if(!big)
+ smoke_set_tray(smd, index, tRay);
+ else
+ smoke_set_bigtray(smd, index, tRay);
+ }
+}
+
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index e3591a84e98..50462d531ef 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -93,5 +93,7 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nea
int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata);
+float BLI_bvhtree_bb_raycast(float *bv, float *light_start, float *light_end, float *pos);
+
#endif // BLI_KDOPBVH_H
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 0f8194362c9..84de9f9d862 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -72,10 +72,10 @@ struct BVHTree
char start_axis, stop_axis; // KDOP_AXES array indices according to axis
};
-typedef struct BVHOverlapData
-{
- BVHTree *tree1, *tree2;
- BVHTreeOverlap *overlap;
+typedef struct BVHOverlapData
+{
+ BVHTree *tree1, *tree2;
+ BVHTreeOverlap *overlap;
int i, max_overlap; /* i is number of overlaps */
int start_axis, stop_axis;
} BVHOverlapData;
@@ -109,7 +109,7 @@ typedef struct BVHRayCastData
////////////////////////////////////////////////////////////////////////
// Bounding Volume Hierarchy Definition
-//
+//
// Notes: From OBB until 26-DOP --> all bounding volumes possible, just choose type below
// Notes: You have to choose the type at compile time ITM
// Notes: You can choose the tree type --> binary, quad, octree, choose below
@@ -188,10 +188,10 @@ int ADJUST_MEMORY(void *local_memblock, void **memblock, int new_size, int *max_
//////////////////////////////////////////////////////////////////////////////////////////////////////
-// Introsort
+// Introsort
// with permission deriven from the following Java code:
// http://ralphunden.net/content/tutorials/a-guide-to-introsort/
-// and he derived it from the SUN STL
+// and he derived it from the SUN STL
//////////////////////////////////////////////////////////////////////////////////////////////////////
static int size_threshold = 16;
/*
@@ -362,7 +362,7 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoi
float newminmax;
float *bv = node->bv;
int i, k;
-
+
// don't init boudings for the moving case
if(!moving)
{
@@ -372,7 +372,7 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoi
bv[2*i + 1] = -FLT_MAX;
}
}
-
+
for(k = 0; k < numpoints; k++)
{
// for all Axes.
@@ -394,7 +394,7 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end)
int i, j;
float *bv = node->bv;
-
+
for (i = tree->start_axis; i < tree->stop_axis; i++)
{
bv[2*i] = FLT_MAX;
@@ -406,10 +406,10 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end)
// for all Axes.
for (i = tree->start_axis; i < tree->stop_axis; i++)
{
- newmin = tree->nodes[j]->bv[(2 * i)];
+ newmin = tree->nodes[j]->bv[(2 * i)];
if ((newmin < bv[(2 * i)]))
bv[(2 * i)] = newmin;
-
+
newmax = tree->nodes[j]->bv[(2 * i) + 1];
if ((newmax > bv[(2 * i) + 1]))
bv[(2 * i) + 1] = newmax;
@@ -427,14 +427,14 @@ static char get_largest_axis(float *bv)
middle_point[0] = (bv[1]) - (bv[0]); // x axis
middle_point[1] = (bv[3]) - (bv[2]); // y axis
middle_point[2] = (bv[5]) - (bv[4]); // z axis
- if (middle_point[0] > middle_point[1])
+ if (middle_point[0] > middle_point[1])
{
if (middle_point[0] > middle_point[2])
return 1; // max x axis
else
return 5; // max z axis
}
- else
+ else
{
if (middle_point[1] > middle_point[2])
return 3; // max y axis
@@ -448,24 +448,24 @@ static char get_largest_axis(float *bv)
static void node_join(BVHTree *tree, BVHNode *node)
{
int i, j;
-
+
for (i = tree->start_axis; i < tree->stop_axis; i++)
{
node->bv[2*i] = FLT_MAX;
node->bv[2*i + 1] = -FLT_MAX;
}
-
+
for (i = 0; i < tree->tree_type; i++)
{
- if (node->children[i])
+ if (node->children[i])
{
for (j = tree->start_axis; j < tree->stop_axis; j++)
{
- // update minimum
- if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)])
+ // update minimum
+ if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)])
node->bv[(2 * j)] = node->children[i]->bv[(2 * j)];
-
- // update maximum
+
+ // update maximum
if (node->children[i]->bv[(2 * j) + 1] > node->bv[(2 * j) + 1])
node->bv[(2 * j) + 1] = node->children[i]->bv[(2 * j) + 1];
}
@@ -518,7 +518,7 @@ static void bvhtree_info(BVHTree *tree)
static void verify_tree(BVHTree *tree)
{
int i, j, check = 0;
-
+
// check the pointer list
for(i = 0; i < tree->totleaf; i++)
{
@@ -538,7 +538,7 @@ static void verify_tree(BVHTree *tree)
check = 0;
}
}
-
+
// check the leaf list
for(i = 0; i < tree->totleaf; i++)
{
@@ -558,7 +558,7 @@ static void verify_tree(BVHTree *tree)
check = 0;
}
}
-
+
printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf);
}
#endif
@@ -703,7 +703,7 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array,
BVHBuildHelper data;
int depth;
-
+
// set parent from root node to NULL
BVHNode *tmp = branches_array+0;
tmp->parent = NULL;
@@ -722,7 +722,7 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array,
}
branches_array--; //Implicit trees use 1-based indexs
-
+
build_implicit_tree_helper(tree, &data);
//Loop tree levels (log N) loops
@@ -806,11 +806,11 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
{
BVHTree *tree;
int numnodes, i;
-
+
// theres not support for trees below binary-trees :P
if(tree_type < 2)
return NULL;
-
+
if(tree_type > MAX_TREETYPE)
return NULL;
@@ -820,13 +820,13 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
//so that tangent rays can still hit a bounding volume..
//this bug would show up when casting a ray aligned with a kdop-axis and with an edge of 2 faces
epsilon = MAX2(FLT_EPSILON, epsilon);
-
+
if(tree)
{
tree->epsilon = epsilon;
- tree->tree_type = tree_type;
+ tree->tree_type = tree_type;
tree->axis = axis;
-
+
if(axis == 26)
{
tree->start_axis = 0;
@@ -863,13 +863,13 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type;
tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*numnodes, "BVHNodes");
-
+
if(!tree->nodes)
{
MEM_freeN(tree);
return NULL;
}
-
+
tree->nodebv = (float*)MEM_callocN(sizeof(float)* axis * numnodes, "BVHNodeBV");
if(!tree->nodebv)
{
@@ -886,7 +886,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
}
tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)* numnodes, "BVHNodeArray");
-
+
if(!tree->nodearray)
{
MEM_freeN(tree->nodechild);
@@ -902,14 +902,14 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
tree->nodearray[i].bv = tree->nodebv + i * axis;
tree->nodearray[i].children = tree->nodechild + i * tree_type;
}
-
+
}
return tree;
}
void BLI_bvhtree_free(BVHTree *tree)
-{
+{
if(tree)
{
MEM_freeN(tree->nodes);
@@ -946,27 +946,27 @@ int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints)
{
int i;
BVHNode *node = NULL;
-
+
// insert should only possible as long as tree->totbranch is 0
if(tree->totbranch > 0)
return 0;
-
+
if(tree->totleaf+1 >= MEM_allocN_len(tree->nodes)/sizeof(*(tree->nodes)))
return 0;
-
+
// TODO check if have enough nodes in array
-
+
node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]);
tree->totleaf++;
-
+
create_kdop_hull(tree, node, co, numpoints, 0);
node->index= index;
-
+
// inflate the bv with some epsilon
for (i = tree->start_axis; i < tree->stop_axis; i++)
{
- node->bv[(2 * i)] -= tree->epsilon; // minimum
- node->bv[(2 * i) + 1] += tree->epsilon; // maximum
+ node->bv[(2 * i)] -= tree->epsilon; // minimum
+ node->bv[(2 * i) + 1] += tree->epsilon; // maximum
}
return 1;
@@ -978,23 +978,23 @@ int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_movin
{
int i;
BVHNode *node= NULL;
-
+
// check if index exists
if(index > tree->totleaf)
return 0;
-
+
node = tree->nodearray + index;
-
+
create_kdop_hull(tree, node, co, numpoints, 0);
-
+
if(co_moving)
create_kdop_hull(tree, node, co_moving, numpoints, 1);
-
+
// inflate the bv with some epsilon
for (i = tree->start_axis; i < tree->stop_axis; i++)
{
- node->bv[(2 * i)] -= tree->epsilon; // minimum
- node->bv[(2 * i) + 1] += tree->epsilon; // maximum
+ node->bv[(2 * i)] -= tree->epsilon; // minimum
+ node->bv[(2 * i) + 1] += tree->epsilon; // maximum
}
return 1;
@@ -1030,24 +1030,24 @@ static int tree_overlap(BVHNode *node1, BVHNode *node2, int start_axis, int stop
float *bv2 = node2->bv;
float *bv1_end = bv1 + (stop_axis<<1);
-
+
bv1 += start_axis<<1;
bv2 += start_axis<<1;
-
+
// test all axis if min + max overlap
for (; bv1 != bv1_end; bv1+=2, bv2+=2)
{
- if ((*(bv1) > *(bv2 + 1)) || (*(bv2) > *(bv1 + 1)))
+ if ((*(bv1) > *(bv2 + 1)) || (*(bv2) > *(bv1 + 1)))
return 0;
}
-
+
return 1;
}
static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
{
int j;
-
+
if(tree_overlap(node1, node2, data->start_axis, data->stop_axis))
{
// check if node1 is a leaf
@@ -1056,17 +1056,17 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
// check if node2 is a leaf
if(!node2->totnode)
{
-
+
if(node1 == node2)
{
return;
}
-
+
if(data->i >= data->max_overlap)
- {
+ {
// try to make alloc'ed memory bigger
data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap)*data->max_overlap*2);
-
+
if(!data->overlap)
{
printf("Out of Memory in traverse\n");
@@ -1074,7 +1074,7 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
}
data->max_overlap *= 2;
}
-
+
// both leafs, insert overlap!
data->overlap[data->i].indexA = node1->index;
data->overlap[data->i].indexB = node2->index;
@@ -1092,7 +1092,7 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
}
else
{
-
+
for(j = 0; j < data->tree2->tree_type; j++)
{
if(node1->children[j])
@@ -1108,21 +1108,21 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result)
int j, total = 0;
BVHTreeOverlap *overlap = NULL, *to = NULL;
BVHOverlapData **data;
-
+
// check for compatibility of both trees (can't compare 14-DOP with 18-DOP)
if((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && (tree1->axis == 18 || tree2->axis == 18))
return 0;
-
+
// fast check root nodes for collision before doing big splitting + traversal
if(!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis)))
return 0;
data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star");
-
+
for(j = 0; j < tree1->tree_type; j++)
{
data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData");
-
+
// init BVHOverlapData
data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap)*MAX2(tree1->totleaf, tree2->totleaf));
data[j]->tree1 = tree1;
@@ -1138,25 +1138,25 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result)
{
traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]);
}
-
+
for(j = 0; j < tree1->tree_type; j++)
total += data[j]->i;
-
+
to = overlap = (BVHTreeOverlap *)MEM_callocN(sizeof(BVHTreeOverlap)*total, "BVHTreeOverlap");
-
+
for(j = 0; j < tree1->tree_type; j++)
{
memcpy(to, data[j]->overlap, data[j]->i*sizeof(BVHTreeOverlap));
to+=data[j]->i;
}
-
+
for(j = 0; j < tree1->tree_type; j++)
{
free(data[j]->overlap);
MEM_freeN(data[j]);
}
MEM_freeN(data);
-
+
(*result) = total;
return overlap;
}
@@ -1339,7 +1339,7 @@ static void bfs_find_nearest(BVHNearestData *data, BVHNode *node)
push_heaps++;
}
}
-
+
if(heap_size == 0) break;
current = heap[0];
@@ -1405,10 +1405,9 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nea
*/
//Determines the distance that the ray must travel to hit the bounding volume of the given node
-static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node)
+static float ray_nearest_hit(BVHRayCastData *data, float *bv)
{
int i;
- const float *bv = node->bv;
float low = 0, upper = data->hit.dist;
@@ -1436,7 +1435,7 @@ static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node)
if(lu > low) low = lu;
if(ll < upper) upper = ll;
}
-
+
if(low > upper) return FLT_MAX;
}
}
@@ -1449,7 +1448,7 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node)
//ray-bv is really fast.. and simple tests revealed its worth to test it
//before calling the ray-primitive functions
- float dist = ray_nearest_hit(data, node);
+ float dist = ray_nearest_hit(data, node->bv);
if(dist >= data->hit.dist) return;
if(node->totnode == 0)
@@ -1527,3 +1526,35 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float
return data.hit.index;
}
+float BLI_bvhtree_bb_raycast(float *bv, float *light_start, float *light_end, float *pos)
+{
+ BVHRayCastData data;
+ float dist = 0.0;
+ int i;
+
+ data.hit.dist = FLT_MAX;
+
+ // get light direction
+ data.ray.direction[0] = light_end[0] - light_start[0];
+ data.ray.direction[1] = light_end[1] - light_start[1];
+ data.ray.direction[2] = light_end[2] - light_start[2];
+
+ data.ray.radius = 0.0;
+
+ data.ray.origin[0] = light_start[0];
+ data.ray.origin[1] = light_start[1];
+ data.ray.origin[2] = light_start[2];
+
+ Normalize(data.ray.direction);
+ VECCOPY(data.ray_dot_axis, data.ray.direction);
+
+ dist = ray_nearest_hit(&data, bv);
+
+ if(dist > 0.0)
+ {
+ VECADDFAC(pos, light_start, data.ray.direction, dist);
+ }
+ return dist;
+
+}
+
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 3029e482312..8a376a0a170 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -94,6 +94,7 @@
#include "DNA_sdna_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_smoke_types.h"
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_texture_types.h"
@@ -3539,6 +3540,17 @@ static void lib_link_object(FileData *fd, Main *main)
if(fluidmd && fluidmd->fss)
fluidmd->fss->ipo = newlibadr_us(fd, ob->id.lib, fluidmd->fss->ipo);
}
+
+ {
+ SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+
+ if(smd && smd->type == MOD_SMOKE_TYPE_DOMAIN && smd->domain)
+ {
+ smd->domain->coll_group = newlibadr_us(fd, ob->id.lib, smd->domain->coll_group);
+ smd->domain->eff_group = newlibadr_us(fd, ob->id.lib, smd->domain->eff_group);
+ smd->domain->fluid_group = newlibadr_us(fd, ob->id.lib, smd->domain->fluid_group);
+ }
+ }
/* texture field */
if(ob->pd)
@@ -3630,6 +3642,44 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
fluidmd->fss= newdataadr(fd, fluidmd->fss);
fluidmd->fss->meshSurfNormals = 0;
}
+ else if (md->type==eModifierType_Smoke) {
+ SmokeModifierData *smd = (SmokeModifierData*) md;
+
+ if(smd->type==MOD_SMOKE_TYPE_DOMAIN)
+ {
+ smd->flow = NULL;
+ smd->coll = NULL;
+ if(smd->domain)
+ smd->domain = newdataadr(fd, smd->domain);
+
+ smd->domain->fluid = NULL;
+ smd->domain->tvox = NULL;
+ smd->domain->tray = NULL;
+ smd->domain->tvoxbig = NULL;
+ smd->domain->traybig = NULL;
+ smd->domain->bind = NULL;
+ smd->domain->max_textures = 0;
+ smd->domain->viewsettings = 0; // reset view for new frame
+ }
+ else if(smd->type==MOD_SMOKE_TYPE_FLOW)
+ {
+ smd->domain = NULL;
+ smd->coll = NULL;
+ smd->flow = newdataadr(fd, smd->flow);
+ smd->flow->psys = newdataadr(fd, smd->flow->psys);
+ }
+ else if(smd->type==MOD_SMOKE_TYPE_COLL)
+ {
+ smd->flow = NULL;
+ smd->domain = NULL;
+ smd->coll = NULL;
+ /*
+ smd->coll = newdataadr(fd, smd->coll);
+ smd->coll->points = NULL;
+ smd->coll->numpoints = 0;
+ */
+ }
+ }
else if (md->type==eModifierType_Collision) {
CollisionModifierData *collmd = (CollisionModifierData*) md;
@@ -4846,7 +4896,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
}
else if(sl->spacetype==SPACE_LOGIC) {
SpaceLogic *slogic= (SpaceLogic *)sl;
-
+
if(slogic->gpd) {
slogic->gpd= newdataadr(fd, slogic->gpd);
direct_link_gpencil(fd, slogic->gpd);
@@ -10130,6 +10180,19 @@ static void expand_modifier(FileData *fd, Main *mainvar, ModifierData *md)
expand_doit(fd, mainvar, dmd->map_object);
expand_doit(fd, mainvar, dmd->texture);
}
+ else if (md->type==eModifierType_Smoke) {
+ SmokeModifierData *smd = (SmokeModifierData*) md;
+
+ if(smd->type==MOD_SMOKE_TYPE_DOMAIN && smd->domain)
+ {
+ //if(smd->domain->coll_group)
+ expand_doit(fd, mainvar, smd->domain->coll_group);
+ //if(smd->domain->fluid_group)
+ expand_doit(fd, mainvar, smd->domain->fluid_group);
+ //if(smd->domain->eff_group)
+ expand_doit(fd, mainvar, smd->domain->eff_group);
+ }
+ }
}
static void expand_object(FileData *fd, Main *mainvar, Object *ob)
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 0f693b6de31..da68132700d 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -130,6 +130,7 @@ Any case: direct data is ALWAYS after the lib block
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sensor_types.h"
+#include "DNA_smoke_types.h"
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_sound_types.h"
@@ -1116,6 +1117,18 @@ static void write_modifiers(WriteData *wd, ListBase *modbase, int write_undo)
writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
write_pointcaches(wd, clmd->point_cache, PTCACHE_WRITE_CLOTH);
}
+ else if(md->type==eModifierType_Smoke) {
+ SmokeModifierData *smd = (SmokeModifierData*) md;
+
+ if(smd->type==MOD_SMOKE_TYPE_DOMAIN)
+ writestruct(wd, DATA, "SmokeDomainSettings", 1, smd->domain);
+ else if(smd->type==MOD_SMOKE_TYPE_FLOW)
+ writestruct(wd, DATA, "SmokeFlowSettings", 1, smd->flow);
+ /*
+ else if(smd->type==MOD_SMOKE_TYPE_COLL)
+ writestruct(wd, DATA, "SmokeCollSettings", 1, smd->coll);
+ */
+ }
else if(md->type==eModifierType_Fluidsim) {
FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index b7a868ad537..28cfcb3ff6e 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -35,7 +35,7 @@ SET(INC ../windowmanager
../../../intern/decimation/extern ../blenloader ../python
../../kernel/gen_system ../../../intern/SoundSystem ../readstreamglue
../quicktime ../../../intern/elbeem/extern
- ../../../intern/ghost ../../../intern/opennl/extern ../../../extern/glew/include
+ ../../../intern/ghost ../../../intern/opennl/extern ../../../extern/glew/include ../../../intern/smoke/extern
../nodes
../gpu
../blenfont
diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript
index 7d51d237ef0..4eb9f3f5ecb 100644
--- a/source/blender/editors/space_view3d/SConscript
+++ b/source/blender/editors/space_view3d/SConscript
@@ -8,6 +8,7 @@ incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../render/extern/include #/intern/guardedalloc'
incs += ' ../../gpu ../../makesrna ../../blenfont'
+incs += ' #/intern/smoke/extern'
if env['WITH_BF_GAMEENGINE']:
defs.append('GAMEBLENDER=1')
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 53630b2bee0..d0bee9c18f8 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -59,6 +59,7 @@
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_smoke_types.h"
#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
@@ -88,7 +89,9 @@
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_property.h"
+#include "BKE_smoke.h"
#include "BKE_utildefines.h"
+#include "smoke_API.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -4898,6 +4901,7 @@ void drawRBpivot(bRigidBodyJointConstraint *data)
void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
{
static int warning_recursive= 0;
+ ModifierData *md = NULL;
Object *ob;
Curve *cu;
RegionView3D *rv3d= ar->regiondata;
@@ -5293,6 +5297,333 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
if(col) cpack(col);
}
+ /* draw code for smoke */
+ if(md = modifiers_findByType(ob, eModifierType_Smoke))
+ {
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+
+ // draw collision objects
+ if((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll)
+ {
+ SmokeCollSettings *scs = smd->coll;
+ /*
+ if(scs->points)
+ {
+ size_t i;
+
+ wmLoadMatrix(rv3d->viewmat);
+
+ if(col || (ob->flag & SELECT)) cpack(0xFFFFFF);
+ glDepthMask(GL_FALSE);
+ glEnable(GL_BLEND);
+
+
+ // glPointSize(3.0);
+ bglBegin(GL_POINTS);
+
+ for(i = 0; i < scs->numpoints; i++)
+ {
+ bglVertex3fv(&scs->points[3*i]);
+ }
+
+ bglEnd();
+ glPointSize(1.0);
+
+ wmMultMatrix(ob->obmat);
+ glDisable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ if(col) cpack(col);
+
+ }
+ */
+ }
+
+ // only draw domains
+ if(smd->domain && smd->domain->fluid)
+ {
+ int x, y, z, i;
+ float *density = NULL;
+ float viewnormal[3];
+ int mainaxis[3] = {0,0,0};
+ float align = 0;
+ int max_textures = 0, counter_textures = 0;
+ int counter=0;
+ float *buffer = NULL;
+ int res[3];
+ float bigfactor = 1.0;
+ int big = smd->domain->flags & MOD_SMOKE_HIGHRES;
+ int new = 0;
+
+ // GUI sent redraw event
+ if(smd->domain->flags & MOD_SMOKE_VIEW_REDRAWNICE)
+ {
+ new = 1;
+ smd->domain->flags &= ~MOD_SMOKE_VIEW_REDRAWNICE;
+ }
+
+ if(!big)
+ {
+ res[0] = smd->domain->res[0];
+ res[1] = smd->domain->res[1];
+ res[2] = smd->domain->res[2];
+ }
+ else
+ {
+ smoke_get_bigres(smd->domain->fluid, res);
+ bigfactor = 1.0 / smd->domain->amplify;
+ }
+
+ wmLoadMatrix(rv3d->viewmat);
+
+ if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); /* for visibility, also while wpaint */
+ glDepthMask(GL_FALSE);
+ glEnable(GL_BLEND);
+
+ // get view vector
+ VECCOPY(viewnormal, rv3d->viewinv[2]);
+ Normalize(viewnormal);
+ for(i = 0; i < 3; i++)
+ {
+ if(ABS(viewnormal[i]) > align)
+ {
+ mainaxis[0] = i;
+ align = ABS(viewnormal[i]);
+ }
+ }
+ mainaxis[1] = (mainaxis[0] + 1) % 3;
+ mainaxis[2] = (mainaxis[0] + 2) % 3;
+
+ if(!smd->domain->bind)
+ {
+ smd->domain->bind = MEM_callocN(sizeof(GLuint)*256, "Smoke_bind");
+ if(big)
+ smd->domain->viewsettings |= MOD_SMOKE_VIEW_CHANGETOBIG;
+ new = 3;
+ }
+
+ // check if view axis / mode has been changed
+ if(smd->domain->viewsettings)
+ {
+ if(big)
+ {
+ if(!(smd->domain->viewsettings & MOD_SMOKE_VIEW_BIG))
+ new = 2;
+ else if(!(smd->domain->viewsettings & MOD_SMOKE_VIEW_CHANGETOBIG))
+ new = 1;
+
+ smd->domain->viewsettings |= MOD_SMOKE_VIEW_CHANGETOBIG;
+ }
+ else
+ {
+ if(!(smd->domain->viewsettings & MOD_SMOKE_VIEW_SMALL))
+ new = 2;
+ else if(smd->domain->viewsettings & MOD_SMOKE_VIEW_CHANGETOBIG)
+ new = 1;
+
+ smd->domain->viewsettings &= ~MOD_SMOKE_VIEW_CHANGETOBIG;
+ }
+
+ if(!new)
+ {
+ if((mainaxis[0] == 0) && !(smd->domain->viewsettings & MOD_SMOKE_VIEW_X))
+ new = 1;
+ else if((mainaxis[0] == 1) && !(smd->domain->viewsettings & MOD_SMOKE_VIEW_Y))
+ new = 1;
+ else if((mainaxis[0] == 2) && !(smd->domain->viewsettings & MOD_SMOKE_VIEW_Z))
+ new = 1;
+
+ // printf("check axis\n");
+ }
+ }
+ else
+ new = 3;
+
+ if(new > 1)
+ {
+ float light[3] = {0.0,0.0,2.0};
+
+ if(!big && !(smd->domain->viewsettings & MOD_SMOKE_VIEW_SMALL))
+ {
+ smoke_prepare_View(smd, light);
+ // printf("prepared View!\n");
+ }
+ else if(big && !(smd->domain->viewsettings & MOD_SMOKE_VIEW_BIG))
+ {
+ smoke_prepare_bigView(smd, light);
+ // printf("prepared bigView!\n");
+ }
+ }
+
+ // printf("big: %d, new: %d\n", big, new);
+
+ // only create buffer if we need to create new textures
+ if(new)
+ buffer = MEM_mallocN(sizeof(float)*res[mainaxis[1]]*res[mainaxis[2]]*4, "SmokeDrawBuffer");
+
+ if(buffer || smd->domain->viewsettings)
+ {
+ int mod_texture = 0;
+
+ // printf("if(buffer || smd->domain->viewsettings)\n");
+
+ max_textures = (res[mainaxis[0]] > 256) ? 256 : res[mainaxis[0]];
+
+ if(!smd->domain->viewsettings) // new frame or new start
+ {
+ smd->domain->max_textures = max_textures;
+ glGenTextures(smd->domain->max_textures, smd->domain->bind);
+ new = 1;
+ // printf("glGenTextures\n");
+ }
+ else
+ {
+ if(new)
+ {
+ // printf("glDeleteTextures\n");
+ glDeleteTextures(smd->domain->max_textures, smd->domain->bind);
+ smd->domain->max_textures = max_textures;
+ glGenTextures(smd->domain->max_textures, smd->domain->bind);
+ }
+ }
+
+ mod_texture = MAX3(1, smd->domain->visibility, (int)(res[mainaxis[0]] / smd->domain->max_textures ));
+
+ for (z = res[mainaxis[0]]-1; z >= 0; z--) // 2
+ {
+ float quad[4][3];
+
+ if(new)
+ {
+ for (y = 0; y < res[mainaxis[1]]; y++) // 1
+ {
+ for (x = 0; x < res[mainaxis[2]]; x++) // 0
+ {
+ size_t index;
+ size_t image_index;
+ float tray, tvox;
+
+ if(mainaxis[0] == 0)
+ {
+ // mainaxis[1] == 1, mainaxis[2] == 2
+ image_index = smoke_get_index2d(y, res[mainaxis[1]], x, res[mainaxis[2]], z, res[mainaxis[0]]);
+ index = smoke_get_index(z, res[mainaxis[0]], y, res[mainaxis[1]], x, res[mainaxis[2]]);
+ }
+ else if(mainaxis[0] == 1)
+ {
+ // mainaxis[1] == 2, mainaxis[2] == 0
+ image_index = smoke_get_index2d(y, res[mainaxis[1]], x, res[mainaxis[2]], z, res[mainaxis[0]]);
+ index = smoke_get_index(x, res[mainaxis[2]], z, res[mainaxis[0]], y, res[mainaxis[1]]);
+ }
+ else // mainaxis[0] == 2
+ {
+ // mainaxis[1] == 0, mainaxis[2] == 1
+ image_index = smoke_get_index2d(y, res[mainaxis[1]], x, res[mainaxis[2]], z, res[mainaxis[0]]);
+ index = smoke_get_index(y, res[mainaxis[1]], x, res[mainaxis[2]], z, res[mainaxis[0]]);
+ }
+
+ if(!big)
+ {
+ tvox = smoke_get_tvox(smd, index);
+ tray = smoke_get_tray(smd, index);
+ }
+ else
+ {
+ tvox = smoke_get_bigtvox(smd, index);
+ tray = smoke_get_bigtray(smd, index);
+ }
+
+ // fill buffer with luminance and alpha
+ // 1 - T_vox
+ buffer[image_index*4 + 3] = 1.0 - tvox; // 0 = transparent => d.h. tvox = 1
+
+ // L_vox = Omega * L_light * (1 - T_vox) * T_ray
+ buffer[image_index*4] = buffer[image_index*4 + 1] = buffer[image_index*4 + 2] = smd->domain->omega * 1.0 * tvox * tray;
+ }
+ }
+ }
+ glBindTexture(GL_TEXTURE_2D, smd->domain->bind[counter_textures]);
+ glEnable(GL_TEXTURE_2D);
+
+ if(new)
+ {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, res[mainaxis[1]], res[mainaxis[2]], 0, GL_RGBA, GL_FLOAT, buffer);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
+ }
+
+ if((z % mod_texture) == 0 )
+ {
+ // botttom left
+ quad[3][mainaxis[0]] = smd->domain->p0[mainaxis[0]] + z * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5;
+ quad[3][mainaxis[1]] = smd->domain->p0[mainaxis[1]] + smd->domain->dx * bigfactor * 0.5;
+ quad[3][mainaxis[2]] = smd->domain->p0[mainaxis[2]] + smd->domain->dx * bigfactor * 0.5;
+
+ // top right
+ quad[1][mainaxis[0]] = smd->domain->p0[mainaxis[0]] + z * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5;
+ quad[1][mainaxis[1]] = smd->domain->p0[mainaxis[1]] + (res[mainaxis[1]] - 1) * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5;
+ quad[1][mainaxis[2]] = smd->domain->p0[mainaxis[2]] + (res[mainaxis[2]] - 1) * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5;
+
+ // top left
+ quad[2][mainaxis[0]] = smd->domain->p0[mainaxis[0]] + z * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5;
+ quad[2][mainaxis[1]] = smd->domain->p0[mainaxis[1]] + smd->domain->dx * bigfactor * 0.5;
+ quad[2][mainaxis[2]] = smd->domain->p0[mainaxis[2]] + (res[mainaxis[2]] - 1) * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5;
+
+ // bottom right
+ quad[0][mainaxis[0]] = smd->domain->p0[mainaxis[0]] + z * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5;
+ quad[0][mainaxis[1]] = smd->domain->p0[mainaxis[1]] + (res[mainaxis[1]] - 1) * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5;
+ quad[0][mainaxis[2]] = smd->domain->p0[mainaxis[2]] + smd->domain->dx * bigfactor * 0.5;
+
+ glBegin(GL_QUADS); // Start Drawing Quads
+
+ glTexCoord2f(1.0f, 0.0f);
+ glVertex3fv(quad[0]); // Left And Up 1 Unit (Top Left)
+ glTexCoord2f(1.0f, 1.0f);
+ glVertex3fv(quad[1]); // Right And Up 1 Unit (Top Right)
+ glTexCoord2f(0.0f, 1.0f);
+ glVertex3fv(quad[2]); // Right And Down One Unit (Bottom Right)
+ glTexCoord2f(0.0f, 0.0f);
+ glVertex3fv(quad[3]); // Left And Down One Unit (Bottom Left)
+
+ glEnd();
+ }
+ counter_textures++;
+ }
+ }
+ if(buffer)
+ {
+ MEM_freeN(buffer);
+ buffer = NULL;
+ }
+
+ // set correct flag for viewsettings
+ if(1)
+ {
+ // do not clear BIG/SMALL flag
+ smd->domain->viewsettings &= ~MOD_SMOKE_VIEW_X;
+ smd->domain->viewsettings &= ~MOD_SMOKE_VIEW_Y;
+ smd->domain->viewsettings &= ~MOD_SMOKE_VIEW_Z;
+
+ // set what caches we have
+ if(big)
+ smd->domain->viewsettings |= MOD_SMOKE_VIEW_BIG;
+ else
+ smd->domain->viewsettings |= MOD_SMOKE_VIEW_SMALL;
+
+ if(mainaxis[0] == 0)
+ smd->domain->viewsettings |= MOD_SMOKE_VIEW_X;
+ else if(mainaxis[0] == 1)
+ smd->domain->viewsettings |= MOD_SMOKE_VIEW_Y;
+ else if(mainaxis[0] == 2)
+ smd->domain->viewsettings |= MOD_SMOKE_VIEW_Z;
+ }
+
+ wmMultMatrix(ob->obmat);
+ glDisable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ if(col) cpack(col);
+ }
+ }
+
{
bConstraint *con;
for(con=ob->constraints.first; con; con= con->next)
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index ab053c136ea..3f504848d77 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -41,6 +41,7 @@ typedef enum ModifierType {
eModifierType_SimpleDeform,
eModifierType_Multires,
eModifierType_Surface,
+ eModifierType_Smoke,
NUM_MODIFIER_TYPES
} ModifierType;
@@ -237,6 +238,23 @@ typedef struct BMeshModifierData {
int type;
} BMeshModifierData;
+
+/* Smoke modifier flags */
+#define MOD_SMOKE_TYPE_DOMAIN (1 << 0)
+#define MOD_SMOKE_TYPE_FLOW (1 << 1)
+#define MOD_SMOKE_TYPE_COLL (1 << 2)
+
+typedef struct SmokeModifierData {
+ ModifierData modifier;
+
+ struct SmokeDomainSettings *domain;
+ struct SmokeFlowSettings *flow; /* inflow, outflow, smoke objects */
+ struct SmokeCollSettings *coll; /* collision objects */
+ float time;
+ int type; /* domain, inflow, outflow, ... */
+ struct PointCache *point_cache; /* definition is in DNA_object_force.h */
+} SmokeModifierData;
+
typedef struct DisplaceModifierData {
ModifierData modifier;
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
new file mode 100644
index 00000000000..aac75309be2
--- /dev/null
+++ b/source/blender/makesdna/DNA_smoke_types.h
@@ -0,0 +1,112 @@
+/**
+* $Id: DNA_cloth_types.h 19820 2009-04-20 15:06:46Z blendix $
+*
+* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* The Original Code is Copyright (C) 2006 by NaN Holding BV.
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): Daniel Genrich (Genscher)
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+#ifndef DNA_SMOKE_TYPES_H
+#define DNA_SMOKE_TYPES_H
+
+/* flags */
+#define MOD_SMOKE_HIGHRES (1<<1)
+/* noise */
+#define MOD_SMOKE_NOISEWAVE (1<<0)
+#define MOD_SMOKE_NOISEFFT (1<<1)
+#define MOD_SMOKE_NOISECURL (1<<2)
+/* viewsettings */
+#define MOD_SMOKE_VIEW_X (1<<0)
+#define MOD_SMOKE_VIEW_Y (1<<1)
+#define MOD_SMOKE_VIEW_Z (1<<2)
+#define MOD_SMOKE_VIEW_SMALL (1<<3)
+#define MOD_SMOKE_VIEW_BIG (1<<4)
+#define MOD_SMOKE_VIEW_CHANGETOBIG (1<<5)
+#define MOD_SMOKE_VIEW_REDRAWNICE (1<<6)
+#define MOD_SMOKE_VIEW_REDRAWALL (1<<7)
+
+typedef struct SmokeDomainSettings {
+ struct SmokeModifierData *smd; /* for fast RNA access */
+ struct FLUID_3D *fluid;
+ struct Group *fluid_group;
+ struct Group *eff_group; // effector group for e.g. wind force
+ struct Group *coll_group; // collision objects group
+ unsigned int *bind;
+ float *tvox;
+ float *tray;
+ float *tvoxbig;
+ float *traybig;
+ float p0[3]; /* start point of BB */
+ float p1[3]; /* end point of BB */
+ float dx; /* edge length of one cell */
+ float firstframe;
+ float lastframe;
+ float omega; /* smoke color - from 0 to 1 */
+ float temp; /* fluid temperature */
+ float tempAmb; /* ambient temperature */
+ float alpha;
+ float beta;
+ int res[3]; /* domain resolution */
+ int amplify; /* wavelet amplification */
+ int maxres; /* longest axis on the BB gets this resolution assigned */
+ int flags; /* show up-res or low res, etc */
+ int visibility; /* how many billboards to show (every 2nd, 3rd, 4th,..) */
+ int viewsettings;
+ int max_textures;
+ short noise; /* noise type: wave, curl, anisotropic */
+ short pad2;
+ int pad3;
+ int pad4;
+} SmokeDomainSettings;
+
+/* inflow / outflow */
+typedef struct SmokeFlowSettings {
+ struct SmokeModifierData *smd; /* for fast RNA access */
+ struct ParticleSystem *psys;
+ float density;
+ float temp; /* delta temperature (temp - ambient temp) */
+ float velocity[3];
+ float vgrp_heat_scale[2]; /* min and max scaling for vgroup_heat */
+ short vgroup_flow; /* where inflow/outflow happens - red=1=action */
+ short vgroup_density;
+ short vgroup_heat;
+ short type; /* inflow =0 or outflow = 1 */
+ int pad;
+} SmokeFlowSettings;
+
+/* collision objects (filled with smoke) */
+typedef struct SmokeCollSettings {
+ struct SmokeModifierData *smd; /* for fast RNA access */
+ float *points;
+ float *points_old;
+ float *vel;
+ float mat[4][4];
+ float mat_old[4][4];
+ int numpoints;
+ int numverts; // check if mesh changed
+ short type; // static = 0, rigid = 1, dynamic = 2
+ short pad;
+ int pad2;
+} SmokeCollSettings;
+
+#endif
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 207d6fdd94a..87ceef36dfb 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -132,6 +132,7 @@ char *includefiles[] = {
"DNA_windowmanager_types.h",
"DNA_anim_types.h",
"DNA_boid_types.h",
+ "DNA_smoke_types.h",
// empty string to indicate end of includefiles
""
@@ -1154,4 +1155,5 @@ int main(int argc, char ** argv)
#include "DNA_windowmanager_types.h"
#include "DNA_anim_types.h"
#include "DNA_boid_types.h"
+#include "DNA_smoke_types.h"
/* end of list */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 64a4887701b..1b3175d7f55 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -378,6 +378,7 @@ extern StructRNA RNA_ShapeKeyPoint;
extern StructRNA RNA_ShrinkwrapConstraint;
extern StructRNA RNA_ShrinkwrapModifier;
extern StructRNA RNA_SimpleDeformModifier;
+extern StructRNA RNA_SmokeModifier;
extern StructRNA RNA_SmoothModifier;
extern StructRNA RNA_SoftBodyModifier;
extern StructRNA RNA_SoftBodySettings;
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 0b7fa0e4634..b5fc4d2e463 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -1941,6 +1941,7 @@ RNAProcessItem PROCESS_ITEMS[]= {
{"rna_sculpt_paint.c", NULL, RNA_def_sculpt_paint},
{"rna_sensor.c", NULL, RNA_def_sensor},
{"rna_sequence.c", NULL, RNA_def_sequence},
+ {"rna_smoke.c", NULL, RNA_def_smoke},
{"rna_space.c", NULL, RNA_def_space},
{"rna_text.c", NULL, RNA_def_text},
{"rna_timeline.c", NULL, RNA_def_timeline_marker},
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index ed0395ede23..99f527f8875 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -154,6 +154,7 @@ void RNA_def_screen(struct BlenderRNA *brna);
void RNA_def_sculpt_paint(struct BlenderRNA *brna);
void RNA_def_sensor(struct BlenderRNA *brna);
void RNA_def_sequence(struct BlenderRNA *brna);
+void RNA_def_smoke(struct BlenderRNA *brna);
void RNA_def_space(struct BlenderRNA *brna);
void RNA_def_text(struct BlenderRNA *brna);
void RNA_def_texture(struct BlenderRNA *brna);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index c89cc4ad63e..022ef56b53b 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -71,6 +71,7 @@ EnumPropertyItem modifier_type_items[] ={
{eModifierType_Surface, "SURFACE", ICON_MOD_PHYSICS, "Surface", ""},
{eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
{eModifierType_Wave, "WAVE", ICON_MOD_WAVE, "Wave", ""},
+ {eModifierType_Smoke, "SMOKE", 0, "Smoke", ""},
{0, NULL, 0, NULL, NULL}};
@@ -151,6 +152,8 @@ static StructRNA* rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_MultiresModifier;
case eModifierType_Surface:
return &RNA_SurfaceModifier;
+ case eModifierType_Smoke:
+ return &RNA_SmokeModifier;
default:
return &RNA_Modifier;
}
@@ -172,6 +175,19 @@ static void rna_Modifier_dependency_update(bContext *C, PointerRNA *ptr)
DAG_scene_sort(CTX_data_scene(C));
}
+static void rna_Smoke_set_type(bContext *C, PointerRNA *ptr)
+{
+ SmokeModifierData *smd= (SmokeModifierData *)ptr->data;
+
+ smokeModifier_free(smd); // XXX TODO: completely free all 3 pointers
+ smokeModifier_createType(smd); // create regarding of selected type
+ // particle_system_slot_add_exec(C, NULL);
+ // particle_system_slot_remove_exec(C, NULL);
+
+ // update dependancy since a domain - other type switch could have happened
+ rna_Modifier_dependency_update(C, ptr);
+}
+
static void rna_ExplodeModifier_vgroup_get(PointerRNA *ptr, char *value)
{
ExplodeModifierData *emd= (ExplodeModifierData*)ptr->data;
@@ -1466,6 +1482,41 @@ static void rna_def_modifier_cloth(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Point Cache", "");
}
+static void rna_def_modifier_smoke(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem prop_smoke_type_items[] = {
+ {0, "NONE", 0, "None", ""},
+ {MOD_SMOKE_TYPE_DOMAIN, "TYPE_DOMAIN", 0, "Domain", ""},
+ {MOD_SMOKE_TYPE_FLOW, "TYPE_FLOW", 0, "Flow", "Inflow/Outflow"},
+ {MOD_SMOKE_TYPE_COLL, "TYPE_COLL", 0, "Collision", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ srna= RNA_def_struct(brna, "SmokeModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "Smoke Modifier", "Smoke simulation modifier.");
+ RNA_def_struct_sdna(srna, "SmokeModifierData");
+
+ prop= RNA_def_property(srna, "domain_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "domain");
+ RNA_def_property_ui_text(prop, "Domain Settings", "");
+
+ prop= RNA_def_property(srna, "flow_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "flow");
+ RNA_def_property_ui_text(prop, "Flow Settings", "");
+
+ prop= RNA_def_property(srna, "coll_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "coll");
+ RNA_def_property_ui_text(prop, "Collision Settings", "");
+
+ prop= RNA_def_property(srna, "fluid_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, prop_smoke_type_items);
+ RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_set_type");
+}
+
static void rna_def_modifier_collision(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1763,7 +1814,6 @@ static void rna_def_modifier_surface(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SurfaceModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_PHYSICS);
}
-
void RNA_def_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1847,6 +1897,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_simpledeform(brna);
rna_def_modifier_multires(brna);
rna_def_modifier_surface(brna);
+ rna_def_modifier_smoke(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
new file mode 100644
index 00000000000..a4e2c39ecd8
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -0,0 +1,263 @@
+/**
+ * $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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Daniel Genrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "rna_internal.h"
+
+#include "BKE_modifier.h"
+#include "BKE_smoke.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_smoke_types.h"
+
+#include "WM_types.h"
+
+
+#ifdef RNA_RUNTIME
+
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_particle.h"
+
+#include "ED_object.h"
+
+static void rna_Smoke_update(bContext *C, PointerRNA *ptr)
+{
+ DAG_object_flush_update(CTX_data_scene(C), ptr->id.data, OB_RECALC_DATA);
+}
+
+static void rna_Smoke_dependency_update(bContext *C, PointerRNA *ptr)
+{
+ rna_Smoke_update(C, ptr);
+ DAG_scene_sort(CTX_data_scene(C));
+}
+
+static void rna_Smoke_reset(bContext *C, PointerRNA *ptr)
+{
+ SmokeDomainSettings *settings = (SmokeDomainSettings*)ptr->data;
+
+ smokeModifier_reset(settings->smd);
+
+ rna_Smoke_update(C, ptr);
+}
+
+static void rna_Smoke_reset_dependancy(bContext *C, PointerRNA *ptr)
+{
+ SmokeDomainSettings *settings = (SmokeDomainSettings*)ptr->data;
+
+ smokeModifier_reset(settings->smd);
+
+ rna_Smoke_dependency_update(C, ptr);
+}
+
+static void rna_Smoke_redraw(bContext *C, PointerRNA *ptr)
+{
+ SmokeDomainSettings *settings = (SmokeDomainSettings*)ptr->data;
+
+ settings->flags |= MOD_SMOKE_VIEW_REDRAWNICE;
+}
+
+static char *rna_SmokeDomainSettings_path(PointerRNA *ptr)
+{
+ SmokeDomainSettings *settings = (SmokeDomainSettings*)ptr->data;
+ ModifierData *md= (ModifierData *)settings->smd;
+
+ return BLI_sprintfN("modifiers[%s].domain_settings", md->name);
+}
+
+static char *rna_SmokeFlowSettings_path(PointerRNA *ptr)
+{
+ SmokeFlowSettings *settings = (SmokeFlowSettings*)ptr->data;
+ ModifierData *md= (ModifierData *)settings->smd;
+
+ return BLI_sprintfN("modifiers[%s].flow_settings", md->name);
+}
+
+static char *rna_SmokeCollSettings_path(PointerRNA *ptr)
+{
+ SmokeCollSettings *settings = (SmokeCollSettings*)ptr->data;
+ ModifierData *md= (ModifierData *)settings->smd;
+
+ return BLI_sprintfN("modifiers[%s].coll_settings", md->name);
+}
+
+#else
+
+static void rna_def_smoke_domain_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem prop_noise_type_items[] = {
+ {MOD_SMOKE_NOISEWAVE, "NOISEWAVE", 0, "Wavelet", ""},
+ {MOD_SMOKE_NOISEFFT, "NOISEFFT", 0, "FFT", ""},
+ {MOD_SMOKE_NOISECURL, "NOISECURL", 0, "Curl", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ srna = RNA_def_struct(brna, "SmokeDomainSettings", NULL);
+ RNA_def_struct_ui_text(srna, "Domain Settings", "Smoke domain settings.");
+ RNA_def_struct_sdna(srna, "SmokeDomainSettings");
+ RNA_def_struct_path_func(srna, "rna_SmokeDomainSettings_path");
+
+ prop= RNA_def_property(srna, "maxres", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "maxres");
+ RNA_def_property_range(prop, 32, 512);
+ RNA_def_property_ui_range(prop, 32, 512, 2, 0);
+ RNA_def_property_ui_text(prop, "Max Res", "Maximal resolution used in the fluid domain.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
+
+ prop= RNA_def_property(srna, "color", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "omega");
+ RNA_def_property_range(prop, 0.02, 1.0);
+ RNA_def_property_ui_range(prop, 0.02, 1.0, 0.02, 2);
+ RNA_def_property_ui_text(prop, "Color", "Smoke color (0 = black, 1 = white).");
+ RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Smoke_redraw");
+
+ prop= RNA_def_property(srna, "amplify", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "amplify");
+ RNA_def_property_range(prop, 1, 10);
+ RNA_def_property_ui_range(prop, 1, 10, 1, 0);
+ RNA_def_property_ui_text(prop, "Amplification", "Enhance the resolution of smoke by this factor using noise.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
+
+ prop= RNA_def_property(srna, "highres", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_HIGHRES);
+ RNA_def_property_ui_text(prop, "High res", "Show high resolution (using amplification).");
+ RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL);
+
+ prop= RNA_def_property(srna, "noise_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "noise");
+ RNA_def_property_enum_items(prop, prop_noise_type_items);
+ RNA_def_property_ui_text(prop, "Noise Method", "Noise method which is used for creating the high resolution");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
+
+ prop= RNA_def_property(srna, "visibility", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "visibility");
+ RNA_def_property_range(prop, 1, 15);
+ RNA_def_property_ui_range(prop, 1, 15, 1, 0);
+ RNA_def_property_ui_text(prop, "Display", "How much of the resolution should be shown during preview (every 2nd, 3rd, etc).");
+ RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Smoke_redraw");
+
+ prop= RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "alpha");
+ RNA_def_property_range(prop, -5.0, 5.0);
+ RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5);
+ RNA_def_property_ui_text(prop, "Gravity", "Higher value results in sinking smoke");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL);
+
+ prop= RNA_def_property(srna, "beta", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "beta");
+ RNA_def_property_range(prop, -5.0, 5.0);
+ RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5);
+ RNA_def_property_ui_text(prop, "Heat", "Higher value results in faster rising smoke.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL);
+
+ prop= RNA_def_property(srna, "coll_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "coll_group");
+ RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Collision Group", "Limit collisions to this group.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset_dependancy");
+
+ prop= RNA_def_property(srna, "fluid_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "fluid_group");
+ RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Fluid Group", "Limit fluid objects to this group.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset_dependancy");
+
+ prop= RNA_def_property(srna, "eff_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "eff_group");
+ RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Effector Group", "Limit effectors to this group.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset_dependancy");
+}
+
+static void rna_def_smoke_flow_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "SmokeFlowSettings", NULL);
+ RNA_def_struct_ui_text(srna, "Flow Settings", "Smoke flow settings.");
+ RNA_def_struct_sdna(srna, "SmokeFlowSettings");
+ RNA_def_struct_path_func(srna, "rna_SmokeFlowSettings_path");
+
+ prop= RNA_def_property(srna, "density", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "density");
+ RNA_def_property_range(prop, 0.001, 1);
+ RNA_def_property_ui_range(prop, 0.001, 1.0, 1.0, 4);
+ RNA_def_property_ui_text(prop, "Density", "");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL);
+
+ prop= RNA_def_property(srna, "temperature", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "temp");
+ RNA_def_property_range(prop, -10, 10);
+ RNA_def_property_ui_range(prop, -10, 10, 1, 1);
+ RNA_def_property_ui_text(prop, "Temp. Diff.", "Temperature difference to ambientt temperature.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL);
+
+ prop= RNA_def_property(srna, "psys", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "psys");
+ RNA_def_property_struct_type(prop, "ParticleSystem");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset_dependancy");
+
+ prop= RNA_def_property(srna, "velocity", PROP_FLOAT, PROP_VECTOR);
+ RNA_def_property_float_sdna(prop, NULL, "velocity");
+ RNA_def_property_range(prop, -10, 10);
+ RNA_def_property_ui_range(prop, -10, 10, 1, 1);
+ RNA_def_property_ui_text(prop, "Velocity", "");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL);
+
+}
+
+static void rna_def_smoke_coll_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "SmokeCollSettings", NULL);
+ RNA_def_struct_ui_text(srna, "Collision Settings", "Smoke collision settings.");
+ RNA_def_struct_sdna(srna, "SmokeCollSettings");
+ RNA_def_struct_path_func(srna, "rna_SmokeCollSettings_path");
+}
+
+void RNA_def_smoke(BlenderRNA *brna)
+{
+ rna_def_smoke_domain_settings(brna);
+ rna_def_smoke_flow_settings(brna);
+ rna_def_smoke_coll_settings(brna);
+}
+
+#endif
+