2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-01-24 13:45:24 +00:00
|
|
|
* 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-01-24 13:45:24 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) Blender Foundation
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup edphys
|
2011-02-27 20:29:51 +00:00
|
|
|
*/
|
|
|
|
|
2009-01-24 13:45:24 +00:00
|
|
|
#include <math.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
/* types */
|
2010-03-25 06:27:25 +00:00
|
|
|
#include "DNA_action_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
2018-06-04 09:31:30 +02:00
|
|
|
#include "DNA_object_fluidsim_types.h"
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2009-01-24 13:45:24 +00:00
|
|
|
|
|
|
|
#include "BKE_context.h"
|
|
|
|
#include "BKE_customdata.h"
|
|
|
|
#include "BKE_fluidsim.h"
|
2009-07-02 19:41:31 +00:00
|
|
|
#include "BKE_modifier.h"
|
2009-01-24 13:45:24 +00:00
|
|
|
#include "BKE_object.h"
|
2009-07-02 19:41:31 +00:00
|
|
|
#include "BKE_report.h"
|
|
|
|
#include "BKE_scene.h"
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2017-07-21 11:53:13 +02:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
2009-01-24 13:45:24 +00:00
|
|
|
#include "LBM_fluidsim.h"
|
|
|
|
|
2.5
Smaller jobs, all in one commit!
- Moved object_do_update out of view3d drawing, into
the event system (currently after notifiers).
Depsgraph calls for setting update flags will have to
keep track of each Screen's needs, so a UI showing only
a Sequencer doesn't do objects.
- Added button in "Properties region" in 3D window to set
or disable 4-split, including the 3 options it has.
(lock, box, clip)
- Restored legacy code for UI, to make things work like
bone rename, autocomplete.
- Node editor now shows Curves widgets again
- Bugfix: composite job increased Viewer user id count
- Bugfix: Node editor, not "Enable nodes" still called
a Job, which didn't do anything
- Various code cleaning, unused vars and prototypes.
2009-02-11 16:54:55 +00:00
|
|
|
#include "ED_screen.h"
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
#include "WM_types.h"
|
2011-03-23 01:50:14 +00:00
|
|
|
#include "WM_api.h"
|
2009-07-02 19:41:31 +00:00
|
|
|
|
Sorry, three commits in one, became difficult to untangle..
Editors Modules
* render/ module added in editors, moved the preview render code there and
also shading related operators.
* physics/ module made more consistent with other modules. renaming files,
making a single physics_ops.c for operators and keymaps. Also move all
particle related operators here now.
* space_buttons/ now should have only operators relevant to the buttons
specificially.
Updates & Notifiers
* Material/Texture/World/Lamp can now be passed to DAG_id_flush_update,
which will go back to a callback in editors. Eventually these should
be in the depsgraph itself, but for now this gives a unified call for
doing updates.
* GLSL materials are now refreshed on changes. There's still various
cases missing,
* Preview icons now hook into this system, solving various update cases
that were missed before.
* Also fixes issue in my last commit, where some preview would not render,
problem is avoided in the new system.
Icon Rendering
* On systems with support for non-power of two textures, an OpenGL texture
is now used instead of glDrawPixels. This avoids problems with icons get
clipped on region borders. On my Linux desktop, this gives an 1.1x speedup,
and on my Mac laptop a 2.3x speedup overall in redrawing the full window,
with the default setup. The glDrawPixels implementation on Mac seems to
have a lot of overhread.
* Preview icons are now drawn using proper premul alpha, and never faded so
you can see them clearly.
* Also tried to fix issue with texture node preview rendering, globals can't
be used with threads reliably.
2009-09-29 19:12:12 +00:00
|
|
|
#include "physics_intern.h" // own include
|
|
|
|
|
2009-07-16 04:45:52 +00:00
|
|
|
/* enable/disable overall compilation */
|
2011-10-29 23:56:07 +00:00
|
|
|
#ifdef WITH_MOD_FLUID
|
2009-07-16 04:45:52 +00:00
|
|
|
|
2019-01-26 20:41:52 +11:00
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BLI_path_util.h"
|
|
|
|
#include "BLI_math.h"
|
|
|
|
|
2018-04-01 07:24:45 +02:00
|
|
|
#include "BKE_global.h"
|
2019-01-26 20:41:52 +11:00
|
|
|
#include "BKE_main.h"
|
2018-04-01 07:24:45 +02:00
|
|
|
|
2010-03-23 14:09:09 +00:00
|
|
|
#include "WM_api.h"
|
|
|
|
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
|
|
|
|
static float get_fluid_viscosity(FluidsimSettings *settings)
|
|
|
|
{
|
2012-04-15 21:02:08 +00:00
|
|
|
return (1.0f/powf(10.0f, settings->viscosityExponent)) * settings->viscosityValue;
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
|
|
|
|
2012-01-22 03:42:49 +00:00
|
|
|
static float get_fluid_rate(FluidsimSettings *settings)
|
|
|
|
{
|
|
|
|
float rate = 1.0f; /* default rate if not animated... */
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-01-22 03:42:49 +00:00
|
|
|
rate = settings->animRate;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-01-22 03:42:49 +00:00
|
|
|
if (rate < 0.0f)
|
|
|
|
rate = 0.0f;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-01-22 03:42:49 +00:00
|
|
|
return rate;
|
|
|
|
}
|
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
static void get_fluid_gravity(float *gravity, Scene *scene, FluidsimSettings *fss)
|
|
|
|
{
|
|
|
|
if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
|
|
|
|
copy_v3_v3(gravity, scene->physics_settings.gravity);
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-06-12 23:51:30 +00:00
|
|
|
copy_v3_v3(gravity, fss->grav);
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static float get_fluid_size_m(Scene *scene, Object *domainob, FluidsimSettings *fss)
|
|
|
|
{
|
|
|
|
if (!scene->unit.system) {
|
|
|
|
return fss->realsize;
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-03-25 06:27:25 +00:00
|
|
|
float dim[3];
|
|
|
|
float longest_axis;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
BKE_object_dimensions_get(domainob, dim);
|
2012-12-21 05:07:26 +00:00
|
|
|
longest_axis = max_fff(dim[0], dim[1], dim[2]);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
return longest_axis * scene->unit.scale_length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-05 22:36:15 +11:00
|
|
|
static bool fluid_is_animated_mesh(FluidsimSettings *fss)
|
2010-03-25 06:27:25 +00:00
|
|
|
{
|
|
|
|
return ((fss->type == OB_FLUIDSIM_CONTROL) || fss->domainNovecgen);
|
|
|
|
}
|
2009-01-24 13:45:24 +00:00
|
|
|
|
|
|
|
/* ********************** fluid sim settings struct functions ********************** */
|
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
#if 0
|
2009-01-24 13:45:24 +00:00
|
|
|
/* helper function */
|
2012-12-18 01:52:18 +00:00
|
|
|
void fluidsimGetGeometryObjFilename(Object *ob, char *dst) //, char *srcname)
|
2011-12-30 07:55:15 +00:00
|
|
|
{
|
2012-04-29 15:47:02 +00:00
|
|
|
//BLI_snprintf(dst, FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
|
|
|
|
BLI_snprintf(dst, FILE_MAXFILE, "fluidcfgdata_%s.bobj.gz", ob->id.name);
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
2010-03-25 06:27:25 +00:00
|
|
|
#endif
|
2009-01-24 13:45:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* ********************** fluid sim channel helper functions ********************** */
|
2010-03-25 06:27:25 +00:00
|
|
|
|
|
|
|
typedef struct FluidAnimChannels {
|
|
|
|
int length;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
double aniFrameTime;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
float *timeAtFrame;
|
|
|
|
float *DomainTime;
|
|
|
|
float *DomainGravity;
|
|
|
|
float *DomainViscosity;
|
|
|
|
} FluidAnimChannels;
|
|
|
|
|
|
|
|
typedef struct FluidObject {
|
|
|
|
struct FluidObject *next, *prev;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
struct Object *object;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
float *Translation;
|
|
|
|
float *Rotation;
|
|
|
|
float *Scale;
|
|
|
|
float *Active;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
float *InitialVelocity;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
float *AttractforceStrength;
|
|
|
|
float *AttractforceRadius;
|
|
|
|
float *VelocityforceStrength;
|
|
|
|
float *VelocityforceRadius;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
float *VertexCache;
|
|
|
|
int numVerts, numTris;
|
|
|
|
} FluidObject;
|
2009-01-24 13:45:24 +00:00
|
|
|
|
|
|
|
// no. of entries for the two channel sizes
|
|
|
|
#define CHANNEL_FLOAT 1
|
|
|
|
#define CHANNEL_VEC 3
|
|
|
|
|
|
|
|
// simplify channels before printing
|
|
|
|
// for API this is done anyway upon init
|
|
|
|
#if 0
|
2018-06-04 09:31:30 +02:00
|
|
|
static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries)
|
|
|
|
{
|
2012-04-29 15:47:02 +00:00
|
|
|
int i, j;
|
2018-06-04 09:31:30 +02:00
|
|
|
int channelSize = paramsize;
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2012-10-23 03:38:26 +00:00
|
|
|
if (entries == 3) {
|
2012-04-29 17:11:40 +00:00
|
|
|
elbeemSimplifyChannelVec3(channel, &channelSize);
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
2012-10-23 03:38:26 +00:00
|
|
|
else if (entries == 1) {
|
2012-04-29 17:11:40 +00:00
|
|
|
elbeemSimplifyChannelFloat(channel, &channelSize);
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-07-06 23:56:59 +00:00
|
|
|
/* invalid, cant happen? */
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
|
|
|
|
2012-03-31 00:59:17 +00:00
|
|
|
fprintf(file, " CHANNEL %s =\n", str);
|
2012-04-29 17:55:54 +00:00
|
|
|
for (i=0; i < channelSize; i++) {
|
2012-04-29 15:47:02 +00:00
|
|
|
fprintf(file, " ");
|
2012-04-29 17:55:54 +00:00
|
|
|
for (j=0;j <= entries;j++) { // also print time value
|
|
|
|
fprintf(file, " %f ", channel[i*(entries + 1) + j]);
|
2012-10-23 03:38:26 +00:00
|
|
|
if (j == entries-1) { fprintf(file, " "); }
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2012-04-29 15:47:02 +00:00
|
|
|
fprintf(file, "\n");
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2012-04-29 17:55:54 +00:00
|
|
|
fprintf(file, " ;\n");
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
|
|
|
|
/* Note: fluid anim channel data layout
|
|
|
|
* ------------------------------------
|
|
|
|
* CHANNEL_FLOAT:
|
|
|
|
* frame 1 |frame 2
|
|
|
|
* [dataF][time][dataF][time]
|
|
|
|
*
|
|
|
|
* CHANNEL_VEC:
|
|
|
|
* frame 1 |frame 2
|
|
|
|
* [dataX][dataY][dataZ][time][dataX][dataY][dataZ][time]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void init_time(FluidsimSettings *domainSettings, FluidAnimChannels *channels)
|
2009-01-24 13:45:24 +00:00
|
|
|
{
|
2010-03-25 06:27:25 +00:00
|
|
|
int i;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-01-07 03:24:22 +00:00
|
|
|
channels->timeAtFrame = MEM_callocN((channels->length + 1) * sizeof(float), "timeAtFrame channel");
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
channels->timeAtFrame[0] = channels->timeAtFrame[1] = domainSettings->animStart; // start at index 1
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-01-22 03:42:49 +00:00
|
|
|
for (i=2; i <= channels->length; i++) {
|
2012-11-04 07:18:29 +00:00
|
|
|
channels->timeAtFrame[i] = channels->timeAtFrame[i - 1] + (float)channels->aniFrameTime;
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if this is slow, can replace with faster, less readable code */
|
|
|
|
static void set_channel(float *channel, float time, float *value, int i, int size)
|
|
|
|
{
|
|
|
|
if (size == CHANNEL_FLOAT) {
|
|
|
|
channel[(i * 2) + 0] = value[0];
|
|
|
|
channel[(i * 2) + 1] = time;
|
|
|
|
}
|
|
|
|
else if (size == CHANNEL_VEC) {
|
|
|
|
channel[(i * 4) + 0] = value[0];
|
|
|
|
channel[(i * 4) + 1] = value[1];
|
|
|
|
channel[(i * 4) + 2] = value[2];
|
|
|
|
channel[(i * 4) + 3] = time;
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 07:52:44 +00:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
static void set_vertex_channel(Depsgraph *depsgraph, float *channel, float time, struct Scene *scene, struct FluidObject *fobj, int i)
|
2010-03-25 06:27:25 +00:00
|
|
|
{
|
|
|
|
Object *ob = fobj->object;
|
|
|
|
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
|
|
|
|
float *verts;
|
|
|
|
int *tris=NULL, numVerts=0, numTris=0;
|
2012-12-15 05:46:41 +00:00
|
|
|
int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
|
2010-03-25 06:27:25 +00:00
|
|
|
int framesize = (3*fobj->numVerts) + 1;
|
|
|
|
int j;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (channel == NULL)
|
|
|
|
return;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
initElbeemMesh(depsgraph, scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* don't allow mesh to change number of verts in anim sequence */
|
|
|
|
if (numVerts != fobj->numVerts) {
|
|
|
|
MEM_freeN(channel);
|
|
|
|
channel = NULL;
|
|
|
|
return;
|
2009-09-09 07:52:44 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* fill frame of channel with vertex locations */
|
2012-03-24 06:38:07 +00:00
|
|
|
for (j=0; j < (3*numVerts); j++) {
|
2010-03-25 06:27:25 +00:00
|
|
|
channel[i*framesize + j] = verts[j];
|
2009-09-09 07:52:44 +00:00
|
|
|
}
|
2010-03-25 06:27:25 +00:00
|
|
|
channel[i*framesize + framesize-1] = time;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
MEM_freeN(verts);
|
|
|
|
MEM_freeN(tris);
|
|
|
|
}
|
2009-09-09 07:52:44 +00:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
static void free_domain_channels(FluidAnimChannels *channels)
|
|
|
|
{
|
2010-06-03 07:28:47 +00:00
|
|
|
if (!channels->timeAtFrame)
|
|
|
|
return;
|
2010-03-25 06:27:25 +00:00
|
|
|
MEM_freeN(channels->timeAtFrame);
|
|
|
|
channels->timeAtFrame = NULL;
|
|
|
|
MEM_freeN(channels->DomainGravity);
|
|
|
|
channels->DomainGravity = NULL;
|
|
|
|
MEM_freeN(channels->DomainViscosity);
|
|
|
|
channels->DomainViscosity = NULL;
|
2012-01-22 03:42:49 +00:00
|
|
|
MEM_freeN(channels->DomainTime);
|
|
|
|
channels->DomainTime = NULL;
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
2009-09-09 07:52:44 +00:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
static void free_all_fluidobject_channels(ListBase *fobjects)
|
|
|
|
{
|
|
|
|
FluidObject *fobj;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
for (fobj=fobjects->first; fobj; fobj=fobj->next) {
|
|
|
|
if (fobj->Translation) {
|
|
|
|
MEM_freeN(fobj->Translation);
|
|
|
|
fobj->Translation = NULL;
|
|
|
|
MEM_freeN(fobj->Rotation);
|
|
|
|
fobj->Rotation = NULL;
|
|
|
|
MEM_freeN(fobj->Scale);
|
|
|
|
fobj->Scale = NULL;
|
|
|
|
MEM_freeN(fobj->Active);
|
|
|
|
fobj->Active = NULL;
|
|
|
|
MEM_freeN(fobj->InitialVelocity);
|
|
|
|
fobj->InitialVelocity = NULL;
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (fobj->AttractforceStrength) {
|
|
|
|
MEM_freeN(fobj->AttractforceStrength);
|
|
|
|
fobj->AttractforceStrength = NULL;
|
|
|
|
MEM_freeN(fobj->AttractforceRadius);
|
|
|
|
fobj->AttractforceRadius = NULL;
|
|
|
|
MEM_freeN(fobj->VelocityforceStrength);
|
|
|
|
fobj->VelocityforceStrength = NULL;
|
|
|
|
MEM_freeN(fobj->VelocityforceRadius);
|
|
|
|
fobj->VelocityforceRadius = NULL;
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (fobj->VertexCache) {
|
|
|
|
MEM_freeN(fobj->VertexCache);
|
|
|
|
fobj->VertexCache = NULL;
|
|
|
|
}
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2010-10-17 06:38:56 +00:00
|
|
|
static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects)
|
2010-03-25 06:27:25 +00:00
|
|
|
{
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2017-11-23 13:51:49 -02:00
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
2017-11-03 14:36:49 +01:00
|
|
|
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
2017-04-21 14:28:23 +02:00
|
|
|
Base *base;
|
2010-03-25 06:27:25 +00:00
|
|
|
int i;
|
|
|
|
int length = channels->length;
|
|
|
|
float eval_time;
|
2017-07-21 11:53:13 +02:00
|
|
|
|
2012-01-22 03:42:49 +00:00
|
|
|
/* init time values (assuming that time moves at a constant speed; may be overridden later) */
|
2010-03-25 06:27:25 +00:00
|
|
|
init_time(domainSettings, channels);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* allocate domain animation channels */
|
2012-04-29 17:11:40 +00:00
|
|
|
channels->DomainGravity = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "channel DomainGravity");
|
|
|
|
channels->DomainViscosity = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainViscosity");
|
|
|
|
channels->DomainTime = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime");
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* allocate fluid objects */
|
2017-11-23 13:51:49 -02:00
|
|
|
for (base = FIRSTBASE(view_layer); base; base = base->next) {
|
2010-03-25 06:27:25 +00:00
|
|
|
Object *ob = base->object;
|
|
|
|
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (fluidmd) {
|
|
|
|
FluidObject *fobj = MEM_callocN(sizeof(FluidObject), "Fluid Object");
|
|
|
|
fobj->object = ob;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) {
|
|
|
|
BLI_addtail(fobjects, fobj);
|
|
|
|
continue;
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
fobj->Translation = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Translation");
|
|
|
|
fobj->Rotation = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Rotation");
|
|
|
|
fobj->Scale = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Scale");
|
|
|
|
fobj->Active = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject Active");
|
|
|
|
fobj->InitialVelocity = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject InitialVelocity");
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
|
2012-04-29 17:11:40 +00:00
|
|
|
fobj->AttractforceStrength = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceStrength");
|
|
|
|
fobj->AttractforceRadius = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceRadius");
|
|
|
|
fobj->VelocityforceStrength = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceStrength");
|
|
|
|
fobj->VelocityforceRadius = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceRadius");
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (fluid_is_animated_mesh(fluidmd->fss)) {
|
|
|
|
float *verts=NULL;
|
2012-12-15 05:46:41 +00:00
|
|
|
int *tris=NULL, modifierIndex = BLI_findindex(&ob->modifiers, (ModifierData *)fluidmd);
|
2010-03-25 06:27:25 +00:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
initElbeemMesh(depsgraph, scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex);
|
2012-04-29 17:11:40 +00:00
|
|
|
fobj->VertexCache = MEM_callocN(length *((fobj->numVerts*CHANNEL_VEC)+1) * sizeof(float), "fluidobject VertexCache");
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
MEM_freeN(verts);
|
|
|
|
MEM_freeN(tris);
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
BLI_addtail(fobjects, fobj);
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* now we loop over the frames and fill the allocated channels with data */
|
2012-10-27 10:42:28 +00:00
|
|
|
for (i=0; i < channels->length; i++) {
|
2010-03-25 06:27:25 +00:00
|
|
|
FluidObject *fobj;
|
|
|
|
float viscosity, gravity[3];
|
2012-01-22 03:42:49 +00:00
|
|
|
float timeAtFrame, time;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
eval_time = domainSettings->bakeStart + i;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
|
|
|
/* Modifying the global scene isn't nice, but we can do it in
|
2010-03-25 06:27:25 +00:00
|
|
|
* this part of the process before a threaded job is created */
|
|
|
|
scene->r.cfra = (int)eval_time;
|
2018-04-06 11:21:20 +02:00
|
|
|
ED_update_for_newframe(CTX_data_main(C), depsgraph);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* now scene data should be current according to animation system, so we fill the channels */
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-01-22 03:42:49 +00:00
|
|
|
/* Domain time */
|
|
|
|
// TODO: have option for not running sim, time mangling, in which case second case comes in handy
|
|
|
|
if (channels->DomainTime) {
|
2012-11-04 07:18:29 +00:00
|
|
|
time = get_fluid_rate(domainSettings) * (float)channels->aniFrameTime;
|
2012-01-22 03:42:49 +00:00
|
|
|
timeAtFrame = channels->timeAtFrame[i] + time;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-01-22 03:42:49 +00:00
|
|
|
channels->timeAtFrame[i+1] = timeAtFrame;
|
|
|
|
set_channel(channels->DomainTime, i, &time, i, CHANNEL_FLOAT);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
timeAtFrame = channels->timeAtFrame[i+1];
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-01-22 03:42:49 +00:00
|
|
|
/* Domain properties - gravity/viscosity */
|
2010-03-25 06:27:25 +00:00
|
|
|
get_fluid_gravity(gravity, scene, domainSettings);
|
|
|
|
set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC);
|
|
|
|
viscosity = get_fluid_viscosity(domainSettings);
|
|
|
|
set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* object movement */
|
|
|
|
for (fobj=fobjects->first; fobj; fobj=fobj->next) {
|
|
|
|
Object *ob = fobj->object;
|
|
|
|
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
|
2018-07-05 22:49:42 +02:00
|
|
|
float active = (float) ((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) ? 1 : 0);
|
2011-06-12 23:51:30 +00:00
|
|
|
float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f};
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
|
|
|
|
continue;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* init euler rotation values and convert to elbeem format */
|
2011-03-24 14:19:12 +00:00
|
|
|
/* get the rotation from ob->obmat rather than ob->rot to account for parent animations */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (i) {
|
2011-03-25 08:47:41 +00:00
|
|
|
copy_v3_v3(old_rot, fobj->Rotation + 4*(i-1));
|
2012-11-04 07:18:29 +00:00
|
|
|
mul_v3_fl(old_rot, (float)-M_PI / 180.f);
|
2011-03-24 17:15:43 +00:00
|
|
|
}
|
2011-03-25 08:47:41 +00:00
|
|
|
|
|
|
|
mat4_to_compatible_eulO(rot_d, old_rot, 0, ob->obmat);
|
2012-11-04 07:18:29 +00:00
|
|
|
mul_v3_fl(rot_d, -180.0f / (float)M_PI);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
set_channel(fobj->Translation, timeAtFrame, ob->loc, i, CHANNEL_VEC);
|
|
|
|
set_channel(fobj->Rotation, timeAtFrame, rot_d, i, CHANNEL_VEC);
|
2019-02-18 15:43:06 +11:00
|
|
|
set_channel(fobj->Scale, timeAtFrame, ob->scale, i, CHANNEL_VEC);
|
2010-03-25 06:27:25 +00:00
|
|
|
set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT);
|
|
|
|
set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC);
|
2012-11-23 05:00:07 +00:00
|
|
|
|
|
|
|
// printf("Active: %f, Frame: %f\n", active, timeAtFrame);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
|
|
|
|
set_channel(fobj->AttractforceStrength, timeAtFrame, &fluidmd->fss->attractforceStrength, i, CHANNEL_FLOAT);
|
|
|
|
set_channel(fobj->AttractforceRadius, timeAtFrame, &fluidmd->fss->attractforceRadius, i, CHANNEL_FLOAT);
|
|
|
|
set_channel(fobj->VelocityforceStrength, timeAtFrame, &fluidmd->fss->velocityforceStrength, i, CHANNEL_FLOAT);
|
|
|
|
set_channel(fobj->VelocityforceRadius, timeAtFrame, &fluidmd->fss->velocityforceRadius, i, CHANNEL_FLOAT);
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (fluid_is_animated_mesh(fluidmd->fss)) {
|
2018-04-06 12:07:27 +02:00
|
|
|
set_vertex_channel(depsgraph, fobj->VertexCache, timeAtFrame, scene, fobj, i);
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
|
|
|
}
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-21 11:53:13 +02:00
|
|
|
static void export_fluid_objects(const bContext *C, ListBase *fobjects, Scene *scene, int length)
|
2009-01-24 13:45:24 +00:00
|
|
|
{
|
2018-04-06 12:07:27 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
2010-03-25 06:27:25 +00:00
|
|
|
FluidObject *fobj;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
for (fobj=fobjects->first; fobj; fobj=fobj->next) {
|
|
|
|
Object *ob = fobj->object;
|
|
|
|
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
|
2012-12-15 05:46:41 +00:00
|
|
|
int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-01-24 13:45:24 +00:00
|
|
|
float *verts=NULL;
|
|
|
|
int *tris=NULL;
|
2010-03-25 06:27:25 +00:00
|
|
|
int numVerts=0, numTris=0;
|
2014-02-05 22:36:15 +11:00
|
|
|
bool deform = fluid_is_animated_mesh(fluidmd->fss);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
elbeemMesh fsmesh;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
|
|
|
|
continue;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-04-29 17:11:40 +00:00
|
|
|
elbeemResetMesh(&fsmesh);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.type = fluidmd->fss->type;
|
|
|
|
fsmesh.name = ob->id.name;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
initElbeemMesh(depsgraph, scene, ob, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.numVertices = numVerts;
|
|
|
|
fsmesh.numTriangles = numTris;
|
|
|
|
fsmesh.vertices = verts;
|
|
|
|
fsmesh.triangles = tris;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
|
|
|
fsmesh.channelSizeTranslation =
|
|
|
|
fsmesh.channelSizeRotation =
|
|
|
|
fsmesh.channelSizeScale =
|
|
|
|
fsmesh.channelSizeInitialVel =
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.channelSizeActive = length;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.channelTranslation = fobj->Translation;
|
|
|
|
fsmesh.channelRotation = fobj->Rotation;
|
|
|
|
fsmesh.channelScale = fobj->Scale;
|
|
|
|
fsmesh.channelActive = fobj->Active;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ( ELEM(fsmesh.type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) {
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.channelInitialVel = fobj->InitialVelocity;
|
2013-03-31 03:28:46 +00:00
|
|
|
fsmesh.localInivelCoords = ((fluidmd->fss->typeFlags & OB_FSINFLOW_LOCALCOORD) ? 1 : 0);
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (fluidmd->fss->typeFlags & OB_FSBND_NOSLIP)
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (fluidmd->fss->typeFlags & OB_FSBND_PARTSLIP)
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (fluidmd->fss->typeFlags & OB_FSBND_FREESLIP)
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.obstaclePartslip = fluidmd->fss->partSlipValue;
|
|
|
|
fsmesh.volumeInitType = fluidmd->fss->volumeInitType;
|
|
|
|
fsmesh.obstacleImpactFactor = fluidmd->fss->surfaceSmoothing; // misused value
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-05-19 13:55:54 +00:00
|
|
|
if (fsmesh.type == OB_FLUIDSIM_CONTROL) {
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.cpsTimeStart = fluidmd->fss->cpsTimeStart;
|
|
|
|
fsmesh.cpsTimeEnd = fluidmd->fss->cpsTimeEnd;
|
|
|
|
fsmesh.cpsQuality = fluidmd->fss->cpsQuality;
|
|
|
|
fsmesh.obstacleType = (fluidmd->fss->flag & OB_FLUIDSIM_REVERSE);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
|
|
|
fsmesh.channelSizeAttractforceRadius =
|
|
|
|
fsmesh.channelSizeVelocityforceStrength =
|
|
|
|
fsmesh.channelSizeVelocityforceRadius =
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.channelSizeAttractforceStrength = length;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.channelAttractforceStrength = fobj->AttractforceStrength;
|
|
|
|
fsmesh.channelAttractforceRadius = fobj->AttractforceRadius;
|
|
|
|
fsmesh.channelVelocityforceStrength = fobj->VelocityforceStrength;
|
|
|
|
fsmesh.channelVelocityforceRadius = fobj->VelocityforceRadius;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fsmesh.channelAttractforceStrength =
|
2018-06-04 09:31:30 +02:00
|
|
|
fsmesh.channelAttractforceRadius =
|
|
|
|
fsmesh.channelVelocityforceStrength =
|
|
|
|
fsmesh.channelVelocityforceRadius = NULL;
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* animated meshes */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (deform) {
|
2010-03-25 06:27:25 +00:00
|
|
|
fsmesh.channelSizeVertices = length;
|
|
|
|
fsmesh.channelVertices = fobj->VertexCache;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-07-03 12:40:19 +00:00
|
|
|
/* remove channels */
|
2018-06-04 09:31:30 +02:00
|
|
|
fsmesh.channelTranslation =
|
|
|
|
fsmesh.channelRotation =
|
2012-07-03 12:40:19 +00:00
|
|
|
fsmesh.channelScale = NULL;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-07-03 12:40:19 +00:00
|
|
|
/* Override user settings, only noslip is supported here! */
|
2012-11-07 18:11:13 +00:00
|
|
|
if (fsmesh.type != OB_FLUIDSIM_CONTROL)
|
|
|
|
fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
elbeemAddMesh(&fsmesh);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (verts) MEM_freeN(verts);
|
|
|
|
if (tris) MEM_freeN(tris);
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-23 13:51:49 -02:00
|
|
|
static int fluid_validate_scene(ReportList *reports, ViewLayer *view_layer, Object *fsDomain)
|
2010-03-25 06:27:25 +00:00
|
|
|
{
|
2017-04-21 14:28:23 +02:00
|
|
|
Base *base;
|
2010-03-25 06:27:25 +00:00
|
|
|
Object *newdomain = NULL;
|
|
|
|
int channelObjCount = 0;
|
|
|
|
int fluidInputCount = 0;
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2017-11-23 13:51:49 -02:00
|
|
|
for (base = FIRSTBASE(view_layer); base; base = base->next) {
|
2010-03-25 06:27:25 +00:00
|
|
|
Object *ob = base->object;
|
2012-10-21 05:46:41 +00:00
|
|
|
FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
|
2010-03-25 06:27:25 +00:00
|
|
|
|
|
|
|
/* only find objects with fluid modifiers */
|
|
|
|
if (!fluidmdtmp || ob->type != OB_MESH) continue;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) {
|
2010-03-25 06:27:25 +00:00
|
|
|
/* if no initial domain object given, find another potential domain */
|
|
|
|
if (!fsDomain) {
|
|
|
|
newdomain = ob;
|
|
|
|
}
|
|
|
|
/* if there's more than one domain, cancel */
|
|
|
|
else if (fsDomain && ob != fsDomain) {
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "There should be only one domain object");
|
2010-03-25 06:27:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* count number of objects needed for animation channels */
|
|
|
|
if ( !ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE) )
|
|
|
|
channelObjCount++;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* count number of fluid input objects */
|
|
|
|
if (ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW))
|
|
|
|
fluidInputCount++;
|
|
|
|
}
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (newdomain)
|
|
|
|
fsDomain = newdomain;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (!fsDomain) {
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "No domain object found");
|
2010-03-25 06:27:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-10-23 03:38:26 +00:00
|
|
|
if (channelObjCount >= 255) {
|
2013-04-07 15:09:06 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "Cannot bake with more than 256 objects");
|
2010-03-25 06:27:25 +00:00
|
|
|
return 0;
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
if (fluidInputCount == 0) {
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "No fluid input objects in the scene");
|
2010-03-25 06:27:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
return 1;
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
#define FLUID_SUFFIX_CONFIG "fluidsim.cfg"
|
2012-03-17 22:14:52 +00:00
|
|
|
#define FLUID_SUFFIX_CONFIG_TMP (FLUID_SUFFIX_CONFIG ".tmp")
|
2010-03-25 06:27:25 +00:00
|
|
|
#define FLUID_SUFFIX_SURFACE "fluidsurface"
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2017-04-17 17:26:18 +02:00
|
|
|
static bool fluid_init_filepaths(
|
2018-05-31 15:24:30 +02:00
|
|
|
Main *bmain, ReportList *reports, FluidsimSettings *domainSettings, Object *fsDomain,
|
2017-04-17 17:26:18 +02:00
|
|
|
char *targetDir, char *targetFile)
|
2010-03-25 06:27:25 +00:00
|
|
|
{
|
2012-03-17 22:14:52 +00:00
|
|
|
const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
|
2011-11-20 14:38:11 +00:00
|
|
|
|
2012-07-06 23:56:59 +00:00
|
|
|
/* prepare names... */
|
2018-05-31 15:24:30 +02:00
|
|
|
const char *relbase = modifier_path_relbase(bmain, fsDomain);
|
2017-04-17 17:26:18 +02:00
|
|
|
|
|
|
|
/* We do not accept empty paths, they can end in random places silently, see T51176. */
|
|
|
|
if (domainSettings->surfdataPath[0] == '\0') {
|
|
|
|
modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath),
|
|
|
|
OB_FLUIDSIM_SURF_DIR_DEFAULT);
|
|
|
|
BKE_reportf(reports, RPT_WARNING, "Fluidsim: empty cache path, reset to default '%s'",
|
|
|
|
domainSettings->surfdataPath);
|
|
|
|
}
|
2011-11-20 14:38:11 +00:00
|
|
|
|
|
|
|
BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
|
2017-04-17 17:26:18 +02:00
|
|
|
BLI_path_abs(targetDir, relbase);
|
2011-02-13 03:21:27 +00:00
|
|
|
|
2012-03-18 07:38:51 +00:00
|
|
|
/* .tmp: don't overwrite/delete original file */
|
2012-03-17 22:14:52 +00:00
|
|
|
BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
|
2011-02-13 03:21:27 +00:00
|
|
|
|
2017-04-17 17:26:18 +02:00
|
|
|
/* Ensure whole path exists and is wirtable. */
|
|
|
|
const bool dir_exists = BLI_dir_create_recursive(targetDir);
|
|
|
|
const bool is_writable = BLI_file_is_writable(targetFile);
|
|
|
|
|
|
|
|
/* We change path to some presumably valid default value, but do not allow bake process to continue,
|
|
|
|
* this gives user chance to set manually another path. */
|
|
|
|
if (!dir_exists || !is_writable) {
|
|
|
|
modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath),
|
|
|
|
OB_FLUIDSIM_SURF_DIR_DEFAULT);
|
|
|
|
|
|
|
|
if (!dir_exists) {
|
|
|
|
BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not create cache directory '%s', reset to default '%s'",
|
|
|
|
targetDir, domainSettings->surfdataPath);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BKE_reportf(reports, RPT_ERROR, "Fluidsim: cache directory '%s' is not writable, reset to default '%s'",
|
|
|
|
targetDir, domainSettings->surfdataPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
|
|
|
|
BLI_path_abs(targetDir, relbase);
|
|
|
|
|
|
|
|
/* .tmp: don't overwrite/delete original file */
|
|
|
|
BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
|
|
|
|
|
|
|
|
/* Ensure whole path exists and is wirtable. */
|
|
|
|
if (!BLI_dir_create_recursive(targetDir) || !BLI_file_is_writable(targetFile)) {
|
|
|
|
BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not use default cache directory '%s', "
|
|
|
|
"please define a valid cache path manually", targetDir);
|
|
|
|
}
|
|
|
|
return false;
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
2017-04-17 17:26:18 +02:00
|
|
|
|
|
|
|
return true;
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ******************************************************************************** */
|
|
|
|
/* ********************** write fluidsim config to file ************************* */
|
|
|
|
/* ******************************************************************************** */
|
|
|
|
|
|
|
|
typedef struct FluidBakeJob {
|
|
|
|
/* from wmJob */
|
|
|
|
void *owner;
|
|
|
|
short *stop, *do_update;
|
2010-05-27 08:22:16 +00:00
|
|
|
float *progress;
|
2010-03-25 06:27:25 +00:00
|
|
|
int current_frame;
|
|
|
|
elbeemSimulationSettings *settings;
|
|
|
|
} FluidBakeJob;
|
|
|
|
|
|
|
|
static void fluidbake_free(void *customdata)
|
|
|
|
{
|
2011-07-15 00:39:49 +00:00
|
|
|
FluidBakeJob *fb= (FluidBakeJob *)customdata;
|
2010-03-25 06:27:25 +00:00
|
|
|
MEM_freeN(fb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* called by fluidbake, only to check job 'stop' value */
|
2011-07-15 00:39:49 +00:00
|
|
|
static int fluidbake_breakjob(void *customdata)
|
2010-03-25 06:27:25 +00:00
|
|
|
{
|
2011-07-15 00:39:49 +00:00
|
|
|
FluidBakeJob *fb= (FluidBakeJob *)customdata;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (fb->stop && *(fb->stop))
|
2011-07-15 00:39:49 +00:00
|
|
|
return 1;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
|
|
|
/* this is not nice yet, need to make the jobs list template better
|
2010-03-25 06:27:25 +00:00
|
|
|
* for identifying/acting upon various different jobs */
|
|
|
|
/* but for now we'll reuse the render break... */
|
2012-08-08 18:37:06 +00:00
|
|
|
return (G.is_break);
|
2010-03-25 06:27:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* called by fluidbake, wmJob sends notifier */
|
2010-05-27 08:22:16 +00:00
|
|
|
static void fluidbake_updatejob(void *customdata, float progress)
|
2010-03-25 06:27:25 +00:00
|
|
|
{
|
2011-07-15 00:39:49 +00:00
|
|
|
FluidBakeJob *fb= (FluidBakeJob *)customdata;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
*(fb->do_update) = true;
|
2012-05-19 13:28:19 +00:00
|
|
|
*(fb->progress) = progress;
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
|
|
|
|
2010-05-27 08:22:16 +00:00
|
|
|
static void fluidbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
|
2010-03-25 06:27:25 +00:00
|
|
|
{
|
2011-07-15 00:39:49 +00:00
|
|
|
FluidBakeJob *fb= (FluidBakeJob *)customdata;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
fb->stop= stop;
|
|
|
|
fb->do_update = do_update;
|
2010-05-27 08:22:16 +00:00
|
|
|
fb->progress = progress;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
elbeemSimulate();
|
2014-04-01 11:34:00 +11:00
|
|
|
*do_update = true;
|
2010-03-25 06:27:25 +00:00
|
|
|
*stop = 0;
|
|
|
|
}
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2010-05-27 08:22:16 +00:00
|
|
|
static void fluidbake_endjob(void *customdata)
|
|
|
|
{
|
2011-07-15 00:39:49 +00:00
|
|
|
FluidBakeJob *fb= (FluidBakeJob *)customdata;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-05-27 08:22:16 +00:00
|
|
|
if (fb->settings) {
|
|
|
|
MEM_freeN(fb->settings);
|
|
|
|
fb->settings = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-15 01:52:28 +00:00
|
|
|
static int runSimulationCallback(void *data, int status, int frame)
|
2011-12-30 07:55:15 +00:00
|
|
|
{
|
2010-03-25 06:27:25 +00:00
|
|
|
FluidBakeJob *fb = (FluidBakeJob *)data;
|
2010-05-27 08:22:16 +00:00
|
|
|
elbeemSimulationSettings *settings = fb->settings;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-05-27 08:22:16 +00:00
|
|
|
if (status == FLUIDSIM_CBSTATUS_NEWFRAME) {
|
|
|
|
fluidbake_updatejob(fb, frame / (float)settings->noOfFrames);
|
2012-04-29 15:47:02 +00:00
|
|
|
//printf("elbeem blender cb s%d, f%d, domainid:%d noOfFrames: %d\n", status, frame, settings->domainId, settings->noOfFrames ); // DEBUG
|
2010-05-27 08:22:16 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-02-27 10:35:39 +00:00
|
|
|
if (fluidbake_breakjob(fb)) {
|
2009-01-24 13:45:24 +00:00
|
|
|
return FLUIDSIM_CBRET_ABORT;
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-01-24 13:45:24 +00:00
|
|
|
return FLUIDSIM_CBRET_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2010-06-03 07:28:47 +00:00
|
|
|
static void fluidbake_free_data(FluidAnimChannels *channels, ListBase *fobjects, elbeemSimulationSettings *fsset, FluidBakeJob *fb)
|
|
|
|
{
|
|
|
|
free_domain_channels(channels);
|
|
|
|
MEM_freeN(channels);
|
|
|
|
channels = NULL;
|
|
|
|
|
|
|
|
free_all_fluidobject_channels(fobjects);
|
|
|
|
BLI_freelistN(fobjects);
|
|
|
|
MEM_freeN(fobjects);
|
|
|
|
fobjects = NULL;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-06-07 03:02:47 +00:00
|
|
|
if (fsset) {
|
|
|
|
MEM_freeN(fsset);
|
|
|
|
fsset = NULL;
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-06-03 07:28:47 +00:00
|
|
|
if (fb) {
|
|
|
|
MEM_freeN(fb);
|
|
|
|
fb = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-12 23:51:30 +00:00
|
|
|
/* copied from rna_fluidsim.c: fluidsim_find_lastframe() */
|
2011-11-20 14:38:11 +00:00
|
|
|
static void fluidsim_delete_until_lastframe(FluidsimSettings *fss, const char *relbase)
|
2011-06-12 23:51:30 +00:00
|
|
|
{
|
2011-11-26 04:07:38 +00:00
|
|
|
char targetDir[FILE_MAX], targetFile[FILE_MAX];
|
|
|
|
char targetDirVel[FILE_MAX], targetFileVel[FILE_MAX];
|
|
|
|
char previewDir[FILE_MAX], previewFile[FILE_MAX];
|
2011-06-12 23:51:30 +00:00
|
|
|
int curFrame = 1, exists = 0;
|
|
|
|
|
2011-11-20 14:38:11 +00:00
|
|
|
BLI_join_dirfile(targetDir, sizeof(targetDir), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME);
|
|
|
|
BLI_join_dirfile(targetDirVel, sizeof(targetDirVel), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_VEL_FNAME);
|
|
|
|
BLI_join_dirfile(previewDir, sizeof(previewDir), fss->surfdataPath, OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME);
|
2011-06-12 23:51:30 +00:00
|
|
|
|
2011-11-20 14:38:11 +00:00
|
|
|
BLI_path_abs(targetDir, relbase);
|
|
|
|
BLI_path_abs(targetDirVel, relbase);
|
|
|
|
BLI_path_abs(previewDir, relbase);
|
2011-06-12 23:51:30 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
BLI_strncpy(targetFile, targetDir, sizeof(targetFile));
|
|
|
|
BLI_strncpy(targetFileVel, targetDirVel, sizeof(targetFileVel));
|
|
|
|
BLI_strncpy(previewFile, previewDir, sizeof(previewFile));
|
|
|
|
|
|
|
|
BLI_path_frame(targetFile, curFrame, 0);
|
|
|
|
BLI_path_frame(targetFileVel, curFrame, 0);
|
|
|
|
BLI_path_frame(previewFile, curFrame, 0);
|
|
|
|
|
|
|
|
curFrame++;
|
|
|
|
|
2012-03-06 18:40:15 +00:00
|
|
|
if ((exists = BLI_exists(targetFile))) {
|
2013-03-05 03:53:22 +00:00
|
|
|
BLI_delete(targetFile, false, false);
|
|
|
|
BLI_delete(targetFileVel, false, false);
|
|
|
|
BLI_delete(previewFile, false, false);
|
2011-06-12 23:51:30 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
} while (exists);
|
2011-06-12 23:51:30 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-09-28 06:26:46 +00:00
|
|
|
static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, short do_job)
|
2009-01-24 13:45:24 +00:00
|
|
|
{
|
2018-05-31 15:24:30 +02:00
|
|
|
Main *bmain = CTX_data_main(C);
|
2017-04-21 14:28:23 +02:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2017-11-23 13:51:49 -02:00
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
2017-11-03 14:36:49 +01:00
|
|
|
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
2009-01-24 13:45:24 +00:00
|
|
|
int i;
|
|
|
|
FluidsimSettings *domainSettings;
|
2010-03-25 06:27:25 +00:00
|
|
|
|
2009-01-24 13:45:24 +00:00
|
|
|
char debugStrBuffer[256];
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-01-24 13:45:24 +00:00
|
|
|
int gridlevels = 0;
|
2018-05-31 15:24:30 +02:00
|
|
|
const char *relbase= modifier_path_relbase(bmain, fsDomain);
|
2009-01-24 13:45:24 +00:00
|
|
|
const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
|
2012-03-17 22:14:52 +00:00
|
|
|
const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
|
2010-12-03 17:05:21 +00:00
|
|
|
const char *suffixSurface = FLUID_SUFFIX_SURFACE;
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2011-11-26 04:07:38 +00:00
|
|
|
char targetDir[FILE_MAX]; // store & modify output settings
|
|
|
|
char targetFile[FILE_MAX]; // temp. store filename from targetDir for access
|
2009-01-24 13:45:24 +00:00
|
|
|
|
|
|
|
float domainMat[4][4];
|
|
|
|
float invDomMat[4][4];
|
2010-03-25 06:27:25 +00:00
|
|
|
|
|
|
|
int noFrames;
|
|
|
|
int origFrame = scene->r.cfra;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
FluidAnimChannels *channels = MEM_callocN(sizeof(FluidAnimChannels), "fluid domain animation channels");
|
|
|
|
ListBase *fobjects = MEM_callocN(sizeof(ListBase), "fluid objects");
|
2009-01-24 13:45:24 +00:00
|
|
|
FluidsimModifierData *fluidmd = NULL;
|
|
|
|
Mesh *mesh = NULL;
|
2011-09-28 06:26:46 +00:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
FluidBakeJob *fb;
|
2010-05-27 08:22:16 +00:00
|
|
|
elbeemSimulationSettings *fsset= MEM_callocN(sizeof(elbeemSimulationSettings), "Fluid sim settings");
|
2011-09-28 06:26:46 +00:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
fb= MEM_callocN(sizeof(FluidBakeJob), "fluid bake job");
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-09-05 14:31:10 +10:00
|
|
|
if (BLI_getenv(strEnvName)) {
|
|
|
|
int dlevel = atoi(BLI_getenv(strEnvName));
|
2009-01-24 13:45:24 +00:00
|
|
|
elbeemSetDebugLevel(dlevel);
|
2012-04-29 15:47:02 +00:00
|
|
|
BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Debug messages activated due to envvar '%s'\n", strEnvName);
|
2009-01-24 13:45:24 +00:00
|
|
|
elbeemDebugOut(debugStrBuffer);
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */;
|
2009-01-24 13:45:24 +00:00
|
|
|
noFrames = scene->r.efra - 0;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (noFrames<=0) {
|
2012-10-26 17:32:50 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "No frames to export (check your animation range settings)");
|
2010-06-03 07:28:47 +00:00
|
|
|
fluidbake_free_data(channels, fobjects, fsset, fb);
|
2009-07-02 19:41:31 +00:00
|
|
|
return 0;
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* check scene for sane object/modifier settings */
|
2017-11-23 13:51:49 -02:00
|
|
|
if (!fluid_validate_scene(reports, view_layer, fsDomain)) {
|
2010-06-03 07:28:47 +00:00
|
|
|
fluidbake_free_data(channels, fobjects, fsset, fb);
|
2009-07-02 19:41:31 +00:00
|
|
|
return 0;
|
2010-06-07 03:02:47 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-07-16 23:23:33 +00:00
|
|
|
/* these both have to be valid, otherwise we wouldn't be here */
|
2010-03-25 06:27:25 +00:00
|
|
|
fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
|
2009-01-24 13:45:24 +00:00
|
|
|
domainSettings = fluidmd->fss;
|
|
|
|
mesh = fsDomain->data;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
domainSettings->bakeStart = 1;
|
|
|
|
domainSettings->bakeEnd = scene->r.efra;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-01-24 13:45:24 +00:00
|
|
|
// calculate bounding box
|
|
|
|
fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-01-24 13:45:24 +00:00
|
|
|
// reset last valid frame
|
|
|
|
domainSettings->lastgoodframe = -1;
|
2011-06-12 23:51:30 +00:00
|
|
|
|
|
|
|
/* delete old baked files */
|
2011-11-20 14:38:11 +00:00
|
|
|
fluidsim_delete_until_lastframe(domainSettings, relbase);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-01-24 13:45:24 +00:00
|
|
|
/* rough check of settings... */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (domainSettings->previewresxyz > domainSettings->resolutionxyz) {
|
2012-04-29 15:47:02 +00:00
|
|
|
BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz, domainSettings->resolutionxyz);
|
2009-01-24 13:45:24 +00:00
|
|
|
elbeemDebugOut(debugStrBuffer);
|
|
|
|
domainSettings->previewresxyz = domainSettings->resolutionxyz;
|
|
|
|
}
|
|
|
|
// set adaptive coarsening according to resolutionxyz
|
|
|
|
// this should do as an approximation, with in/outflow
|
|
|
|
// doing this more accurate would be overkill
|
|
|
|
// perhaps add manual setting?
|
2012-03-24 06:38:07 +00:00
|
|
|
if (domainSettings->maxRefine <0) {
|
|
|
|
if (domainSettings->resolutionxyz>128) {
|
2009-01-24 13:45:24 +00:00
|
|
|
gridlevels = 2;
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
2012-10-31 10:09:06 +00:00
|
|
|
else if (domainSettings->resolutionxyz > 64) {
|
2009-01-24 13:45:24 +00:00
|
|
|
gridlevels = 1;
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-01-24 13:45:24 +00:00
|
|
|
gridlevels = 0;
|
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-01-24 13:45:24 +00:00
|
|
|
gridlevels = domainSettings->maxRefine;
|
|
|
|
}
|
2012-04-29 17:55:54 +00:00
|
|
|
BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name, gridlevels);
|
2009-01-24 13:45:24 +00:00
|
|
|
elbeemDebugOut(debugStrBuffer);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* ******** prepare output file paths ******** */
|
2018-05-31 15:24:30 +02:00
|
|
|
if (!fluid_init_filepaths(bmain, reports, domainSettings, fsDomain, targetDir, targetFile)) {
|
2017-04-17 17:26:18 +02:00
|
|
|
fluidbake_free_data(channels, fobjects, fsset, fb);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-11-23 05:00:07 +00:00
|
|
|
channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra)
|
|
|
|
channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-02 16:05:54 +00:00
|
|
|
/* ******** initialize and allocate animation channels ******** */
|
2010-03-25 06:27:25 +00:00
|
|
|
fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects);
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* reset to original current frame */
|
|
|
|
scene->r.cfra = origFrame;
|
2018-04-06 11:21:20 +02:00
|
|
|
ED_update_for_newframe(CTX_data_main(C), depsgraph);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* ******** init domain object's matrix ******** */
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_m4_m4(domainMat, fsDomain->obmat);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!invert_m4_m4(invDomMat, domainMat)) {
|
2012-04-29 15:47:02 +00:00
|
|
|
BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::error - Invalid obj matrix?\n");
|
2009-01-24 13:45:24 +00:00
|
|
|
elbeemDebugOut(debugStrBuffer);
|
2018-06-04 09:31:30 +02:00
|
|
|
BKE_report(reports, RPT_ERROR, "Invalid object matrix");
|
2010-03-25 06:27:25 +00:00
|
|
|
|
2010-06-03 07:28:47 +00:00
|
|
|
fluidbake_free_data(channels, fobjects, fsset, fb);
|
2009-07-02 19:41:31 +00:00
|
|
|
return 0;
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* ******** start writing / exporting ******** */
|
2012-03-18 07:38:51 +00:00
|
|
|
// use .tmp, don't overwrite/delete original file
|
2012-03-17 22:14:52 +00:00
|
|
|
BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp);
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* ******** export domain to elbeem ******** */
|
2010-05-27 08:22:16 +00:00
|
|
|
elbeemResetSettings(fsset);
|
|
|
|
fsset->version = 1;
|
2013-05-21 11:37:42 +00:00
|
|
|
fsset->threads = (domainSettings->threads == 0) ? BKE_scene_num_threads(scene) : domainSettings->threads;
|
2010-03-25 06:27:25 +00:00
|
|
|
// setup global settings
|
2010-05-27 08:22:16 +00:00
|
|
|
copy_v3_v3(fsset->geoStart, domainSettings->bbStart);
|
|
|
|
copy_v3_v3(fsset->geoSize, domainSettings->bbSize);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
// simulate with 50^3
|
2010-05-27 08:22:16 +00:00
|
|
|
fsset->resolutionxyz = (int)domainSettings->resolutionxyz;
|
|
|
|
fsset->previewresxyz = (int)domainSettings->previewresxyz;
|
2010-03-25 06:27:25 +00:00
|
|
|
|
2010-05-27 08:22:16 +00:00
|
|
|
fsset->realsize = get_fluid_size_m(scene, fsDomain, domainSettings);
|
|
|
|
fsset->viscosity = get_fluid_viscosity(domainSettings);
|
|
|
|
get_fluid_gravity(fsset->gravity, scene, domainSettings);
|
2010-03-25 06:27:25 +00:00
|
|
|
|
|
|
|
// simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
|
2010-05-27 08:22:16 +00:00
|
|
|
fsset->animStart = domainSettings->animStart;
|
|
|
|
fsset->aniFrameTime = channels->aniFrameTime;
|
|
|
|
fsset->noOfFrames = noFrames; // is otherwise subtracted in parser
|
|
|
|
|
2011-11-20 14:38:11 +00:00
|
|
|
BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixSurface);
|
2011-02-13 03:21:27 +00:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
// defaults for compressibility and adaptive grids
|
2010-05-27 08:22:16 +00:00
|
|
|
fsset->gstar = domainSettings->gstar;
|
|
|
|
fsset->maxRefine = domainSettings->maxRefine; // check <-> gridlevels
|
2018-06-04 09:31:30 +02:00
|
|
|
fsset->generateParticles = domainSettings->generateParticles;
|
|
|
|
fsset->numTracerParticles = domainSettings->generateTracers;
|
|
|
|
fsset->surfaceSmoothing = domainSettings->surfaceSmoothing;
|
|
|
|
fsset->surfaceSubdivs = domainSettings->surfaceSubdivs;
|
|
|
|
fsset->farFieldSize = domainSettings->farFieldSize;
|
2012-01-11 12:33:51 +00:00
|
|
|
BLI_strncpy(fsset->outputPath, targetFile, sizeof(fsset->outputPath));
|
2010-03-25 06:27:25 +00:00
|
|
|
|
|
|
|
// domain channels
|
2018-06-04 09:31:30 +02:00
|
|
|
fsset->channelSizeFrameTime =
|
|
|
|
fsset->channelSizeViscosity =
|
2010-05-27 08:22:16 +00:00
|
|
|
fsset->channelSizeGravity = channels->length;
|
|
|
|
fsset->channelFrameTime = channels->DomainTime;
|
|
|
|
fsset->channelViscosity = channels->DomainViscosity;
|
|
|
|
fsset->channelGravity = channels->DomainGravity;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-05-27 08:22:16 +00:00
|
|
|
fsset->runsimCallback = &runSimulationCallback;
|
|
|
|
fsset->runsimUserData = fb;
|
|
|
|
|
|
|
|
if (domainSettings->typeFlags & OB_FSBND_NOSLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_NOSLIP;
|
|
|
|
else if (domainSettings->typeFlags&OB_FSBND_PARTSLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP;
|
|
|
|
else if (domainSettings->typeFlags&OB_FSBND_FREESLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_FREESLIP;
|
|
|
|
fsset->domainobsPartslip = domainSettings->partSlipValue;
|
2011-06-12 23:51:30 +00:00
|
|
|
|
|
|
|
/* use domainobsType also for surface generation flag (bit: >=64) */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (domainSettings->typeFlags & OB_FSSG_NOOBS)
|
2011-06-12 23:51:30 +00:00
|
|
|
fsset->mFsSurfGenSetting = FLUIDSIM_FSSG_NOOBS;
|
|
|
|
else
|
|
|
|
fsset->mFsSurfGenSetting = 0; // "normal" mode
|
|
|
|
|
2010-05-27 08:22:16 +00:00
|
|
|
fsset->generateVertexVectors = (domainSettings->domainNovecgen==0);
|
2010-03-25 06:27:25 +00:00
|
|
|
|
|
|
|
// init blender domain transform matrix
|
2012-10-21 05:46:41 +00:00
|
|
|
{ int j;
|
2012-03-24 06:38:07 +00:00
|
|
|
for (i=0; i<4; i++) {
|
|
|
|
for (j=0; j<4; j++) {
|
2010-05-27 08:22:16 +00:00
|
|
|
fsset->surfaceTrafo[i*4+j] = invDomMat[j][i];
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
2010-03-25 06:27:25 +00:00
|
|
|
} }
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* ******** init solver with settings ******** */
|
|
|
|
elbeemInit();
|
2010-05-27 08:22:16 +00:00
|
|
|
elbeemAddDomain(fsset);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* ******** export all fluid objects to elbeem ******** */
|
2017-07-21 11:53:13 +02:00
|
|
|
export_fluid_objects(C, fobjects, scene, channels->length);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* custom data for fluid bake job */
|
2010-05-27 08:22:16 +00:00
|
|
|
fb->settings = fsset;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (do_job) {
|
2012-08-15 10:03:29 +00:00
|
|
|
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Fluid Simulation",
|
|
|
|
WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_FLUID);
|
2011-09-28 06:26:46 +00:00
|
|
|
|
|
|
|
/* setup job */
|
2012-08-15 10:03:29 +00:00
|
|
|
WM_jobs_customdata_set(wm_job, fb, fluidbake_free);
|
|
|
|
WM_jobs_timer(wm_job, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME);
|
|
|
|
WM_jobs_callbacks(wm_job, fluidbake_startjob, NULL, NULL, fluidbake_endjob);
|
2011-09-28 06:26:46 +00:00
|
|
|
|
2012-08-15 10:03:29 +00:00
|
|
|
WM_jobs_start(CTX_wm_manager(C), wm_job);
|
2011-09-28 06:26:46 +00:00
|
|
|
}
|
|
|
|
else {
|
2014-09-19 17:34:05 +06:00
|
|
|
short dummy_stop = 0, dummy_do_update = 0;
|
|
|
|
float dummy_progress = 0.0f;
|
2011-09-28 06:26:46 +00:00
|
|
|
|
|
|
|
/* blocking, use with exec() */
|
|
|
|
fluidbake_startjob((void *)fb, &dummy_stop, &dummy_do_update, &dummy_progress);
|
|
|
|
fluidbake_endjob((void *)fb);
|
|
|
|
fluidbake_free((void *)fb);
|
|
|
|
}
|
2009-07-02 19:41:31 +00:00
|
|
|
|
2010-03-25 06:27:25 +00:00
|
|
|
/* ******** free stored animation data ******** */
|
2010-06-07 03:02:47 +00:00
|
|
|
fluidbake_free_data(channels, fobjects, NULL, NULL);
|
2010-03-25 06:27:25 +00:00
|
|
|
|
2009-01-24 13:45:24 +00:00
|
|
|
// elbeemFree();
|
2009-07-02 19:41:31 +00:00
|
|
|
return 1;
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
|
|
|
|
2012-09-15 01:52:28 +00:00
|
|
|
static void UNUSED_FUNCTION(fluidsimFreeBake)(Object *UNUSED(ob))
|
2009-01-24 13:45:24 +00:00
|
|
|
{
|
|
|
|
/* not implemented yet */
|
|
|
|
}
|
|
|
|
|
2011-10-29 23:56:07 +00:00
|
|
|
#else /* WITH_MOD_FLUID */
|
2009-01-24 13:45:24 +00:00
|
|
|
|
|
|
|
/* only compile dummy functions */
|
2011-09-28 06:26:46 +00:00
|
|
|
static int fluidsimBake(bContext *UNUSED(C), ReportList *UNUSED(reports), Object *UNUSED(ob), short UNUSED(do_job))
|
2009-07-02 19:41:31 +00:00
|
|
|
{
|
|
|
|
return 0;
|
2009-01-24 13:45:24 +00:00
|
|
|
}
|
|
|
|
|
2011-10-29 23:56:07 +00:00
|
|
|
#endif /* WITH_MOD_FLUID */
|
2009-01-24 13:45:24 +00:00
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
/***************************** Operators ******************************/
|
|
|
|
|
2013-03-13 09:03:46 +00:00
|
|
|
static int fluid_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
2009-07-02 19:41:31 +00:00
|
|
|
{
|
2011-03-22 13:30:50 +00:00
|
|
|
/* only one bake job at a time */
|
2012-08-15 10:23:06 +00:00
|
|
|
if (WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_SIM_FLUID))
|
2011-09-28 08:31:02 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2009-07-02 19:41:31 +00:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
if (!fluidsimBake(C, op->reports, CTX_data_active_object(C), true))
|
2011-09-28 06:26:46 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int fluid_bake_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2014-04-01 11:34:00 +11:00
|
|
|
if (!fluidsimBake(C, op->reports, CTX_data_active_object(C), false))
|
2009-07-02 19:41:31 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FLUID_OT_bake(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Fluid Simulation Bake";
|
|
|
|
ot->description = "Bake fluid simulation";
|
|
|
|
ot->idname = "FLUID_OT_bake";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
/* api callbacks */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->invoke = fluid_bake_invoke;
|
|
|
|
ot->exec = fluid_bake_exec;
|
|
|
|
ot->poll = ED_operator_object_active_editable;
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|