This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/extern/mantaflow/preprocessed/plugin/surfaceturbulence.cpp
Sebastián Barschkis 4ff7c5eed6 Mantaflow [Part 1]: Added preprocessed Mantaflow source files
Includes preprocessed Mantaflow source files for both OpenMP and TBB (if OpenMP is not present, TBB files will be used instead).

These files come directly from the Mantaflow repository. Future updates to the core fluid solver will take place by updating the files.

Reviewed By: sergey, mont29

Maniphest Tasks: T59995

Differential Revision: https://developer.blender.org/D3850
2019-12-16 16:27:26 +01:00

2190 lines
72 KiB
C++

// DO NOT EDIT !
// This file is generated using the MantaFlow preprocessor (prep generate).
/******************************************************************************
*
* MantaFlow fluid solver framework
* Copyright 2016 Olivier Mercier, oli.mercier@gmail.com
*
* This program is free software, distributed under the terms of the
* Apache License, Version 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Surface Turbulence for Particle-Based Liquid Simulations
* Mercier et al., SIGGRAPH Asia 2015
*
* Possible speedups :
* - only initialize surface points around coarse particles near the surface. Use the flags in the
*fluid grid and only use cells with non-fluid neighbors.
*
******************************************************************************/
// use chrono stl for detailed timing only if available
#ifdef __GNUC__
# if __GNUC__ < 5
# define USE_CHRONO 0
# endif
#endif
#if MANTA_WITHCPP11 == 1
# ifndef USE_CHRONO
# define USE_CHRONO 1
# endif
#endif
#include <iomanip>
#if USE_CHRONO == 1
# include <chrono>
#endif
#include "particle.h"
using namespace std;
namespace Manta {
// own namespace for globals
namespace SurfaceTurbulence {
//
// **** surface turbulence parameters ****
//
struct SurfaceTurbulenceParameters {
int res;
Real outerRadius;
int surfaceDensity;
int nbSurfaceMaintenanceIterations;
Real dt;
Real waveSpeed;
Real waveDamping;
Real waveSeedFrequency;
Real waveMaxAmplitude;
Real waveMaxFrequency;
Real waveMaxSeedingAmplitude; // as ratio of max amp;
Real waveSeedingCurvatureThresholdRegionCenter;
Real waveSeedingCurvatureThresholdRegionRadius;
Real waveSeedStepSizeRatioOfMax;
Real innerRadius;
Real meanFineDistance;
Real constraintA;
Real normalRadius;
Real tangentRadius;
Real bndXm, bndXp, bndYm, bndYp, bndZm, bndZp;
};
SurfaceTurbulenceParameters params;
//
// **** acceleration grid for particle neighbor queries ****
//
struct ParticleAccelGrid {
int res;
vector<int> ***indices;
void init(int inRes)
{
res = inRes;
indices = new vector<int> **[res];
for (int i = 0; i < res; i++) {
indices[i] = new vector<int> *[res];
for (int j = 0; j < res; j++) {
indices[i][j] = new vector<int>[res];
}
}
}
void fillWith(const BasicParticleSystem &particles)
{
// clear
for (int i = 0; i < res; i++) {
for (int j = 0; j < res; j++) {
for (int k = 0; k < res; k++) {
indices[i][j][k].clear();
}
}
}
// fill
for (int id = 0; id < particles.size(); id++) {
Vec3 pos = particles.getPos(id);
int i = clamp<int>(floor(pos.x / params.res * res), 0, res - 1);
int j = clamp<int>(floor(pos.y / params.res * res), 0, res - 1);
int k = clamp<int>(floor(pos.z / params.res * res), 0, res - 1);
indices[i][j][k].push_back(id);
}
}
void fillWith(const ParticleDataImpl<Vec3> &particles)
{
// clear
for (int i = 0; i < res; i++) {
for (int j = 0; j < res; j++) {
for (int k = 0; k < res; k++) {
indices[i][j][k].clear();
}
}
}
// fill
for (int id = 0; id < particles.size(); id++) {
Vec3 pos = particles[id];
int i = clamp<int>(floor(pos.x / params.res * res), 0, res - 1);
int j = clamp<int>(floor(pos.y / params.res * res), 0, res - 1);
int k = clamp<int>(floor(pos.z / params.res * res), 0, res - 1);
indices[i][j][k].push_back(id);
}
}
};
#define LOOP_NEIGHBORS_BEGIN(points, center, radius) \
int minI = clamp<int>( \
floor((center.x - radius) / params.res * points.accel->res), 0, points.accel->res - 1); \
int maxI = clamp<int>( \
floor((center.x + radius) / params.res * points.accel->res), 0, points.accel->res - 1); \
int minJ = clamp<int>( \
floor((center.y - radius) / params.res * points.accel->res), 0, points.accel->res - 1); \
int maxJ = clamp<int>( \
floor((center.y + radius) / params.res * points.accel->res), 0, points.accel->res - 1); \
int minK = clamp<int>( \
floor((center.z - radius) / params.res * points.accel->res), 0, points.accel->res - 1); \
int maxK = clamp<int>( \
floor((center.z + radius) / params.res * points.accel->res), 0, points.accel->res - 1); \
for (int i = minI; i <= maxI; i++) { \
for (int j = minJ; j <= maxJ; j++) { \
for (int k = minK; k <= maxK; k++) { \
for (int idLOOPNEIGHBORS = 0; \
idLOOPNEIGHBORS < (int)points.accel->indices[i][j][k].size(); \
idLOOPNEIGHBORS++) { \
int idn = points.accel->indices[i][j][k][idLOOPNEIGHBORS]; \
if (points.isActive(idn)) {
#define LOOP_NEIGHBORS_END \
} \
} \
} \
} \
}
#define LOOP_GHOSTS_POS_BEGIN(pos, radius) \
int flagLOOPGHOSTS = -1; \
Vec3 gPos; \
while (flagLOOPGHOSTS < 6) { \
if (flagLOOPGHOSTS < 0 && pos.x - params.bndXm <= radius) { \
flagLOOPGHOSTS = 0; \
gPos = Vec3(2.f * params.bndXm - pos.x, pos.y, pos.z); \
} \
else if (flagLOOPGHOSTS < 1 && params.bndXp - pos.x <= radius) { \
flagLOOPGHOSTS = 1; \
gPos = Vec3(2.f * params.bndXp - pos.x, pos.y, pos.z); \
} \
else if (flagLOOPGHOSTS < 2 && pos.y - params.bndYm <= radius) { \
flagLOOPGHOSTS = 2; \
gPos = Vec3(pos.x, 2.f * params.bndYm - pos.y, pos.z); \
} \
else if (flagLOOPGHOSTS < 3 && params.bndYp - pos.y <= radius) { \
flagLOOPGHOSTS = 3; \
gPos = Vec3(pos.x, 2.f * params.bndYp - pos.y, pos.z); \
} \
else if (flagLOOPGHOSTS < 4 && pos.z - params.bndZm <= radius) { \
flagLOOPGHOSTS = 4; \
gPos = Vec3(pos.x, pos.y, 2.f * params.bndZm - pos.z); \
} \
else if (flagLOOPGHOSTS < 5 && params.bndZp - pos.Z <= radius) { \
flagLOOPGHOSTS = 5; \
gPos = Vec3(pos.x, pos.y, 2.f * params.bndZp - pos.z); \
} \
else { \
flagLOOPGHOSTS = 6; \
gPos = Vec3(pos.x, pos.y, pos.z); \
}
#define LOOP_GHOSTS_POS_NORMAL_BEGIN(pos, normal, radius) \
int flagLOOPGHOSTS = -1; \
Vec3 gPos, gNormal; \
while (flagLOOPGHOSTS < 6) { \
if (flagLOOPGHOSTS < 0 && pos.x - params.bndXm <= radius) { \
flagLOOPGHOSTS = 0; \
gPos = Vec3(2.f * params.bndXm - pos.x, pos.y, pos.z); \
gNormal = Vec3(-normal.x, normal.y, normal.z); \
} \
else if (flagLOOPGHOSTS < 1 && params.bndXp - pos.x <= radius) { \
flagLOOPGHOSTS = 1; \
gPos = Vec3(2.f * params.bndXp - pos.x, pos.y, pos.z); \
gNormal = Vec3(-normal.x, normal.y, normal.z); \
} \
else if (flagLOOPGHOSTS < 2 && pos.y - params.bndYm <= radius) { \
flagLOOPGHOSTS = 2; \
gPos = Vec3(pos.x, 2.f * params.bndYm - pos.y, pos.z); \
gNormal = Vec3(normal.x, -normal.y, normal.z); \
} \
else if (flagLOOPGHOSTS < 3 && params.bndYp - pos.y <= radius) { \
flagLOOPGHOSTS = 3; \
gPos = Vec3(pos.x, 2.f * params.bndYp - pos.y, pos.z); \
gNormal = Vec3(normal.x, -normal.y, normal.z); \
} \
else if (flagLOOPGHOSTS < 4 && pos.z - params.bndZm <= radius) { \
flagLOOPGHOSTS = 4; \
gPos = Vec3(pos.x, pos.y, 2.f * params.bndZm - pos.z); \
gNormal = Vec3(normal.x, normal.y, -normal.z); \
} \
else if (flagLOOPGHOSTS < 5 && params.bndZp - pos.Z <= radius) { \
flagLOOPGHOSTS = 5; \
gPos = Vec3(pos.x, pos.y, 2.f * params.bndZp - pos.z); \
gNormal = Vec3(normal.x, normal.y, -normal.z); \
} \
else { \
flagLOOPGHOSTS = 6; \
gPos = pos; \
gNormal = normal; \
}
#define LOOP_GHOSTS_END }
//
// **** Wrappers around point sets to attach it an acceleration grid ****
//
struct PointSetWrapper {
ParticleAccelGrid *accel;
PointSetWrapper(ParticleAccelGrid *inAccel)
{
accel = inAccel;
}
virtual void updateAccel() = 0;
};
struct BasicParticleSystemWrapper : PointSetWrapper {
BasicParticleSystem *points;
BasicParticleSystemWrapper(ParticleAccelGrid *inAccel) : PointSetWrapper(inAccel)
{
}
Vec3 getPos(int id) const
{
return points->getPos(id);
}
void setPos(int id, Vec3 pos)
{
points->setPos(id, pos);
}
void updateAccel()
{
accel->fillWith(*points);
}
void clear()
{
points->clear();
}
int size() const
{
return points->size();
}
bool isActive(int id) const
{
return points->isActive(id);
}
void addParticle(Vec3 pos)
{
points->addParticle(pos);
}
int getStatus(int id) const
{
return points->getStatus(id);
}
void addBuffered(Vec3 pos)
{
points->addBuffered(pos);
}
void doCompress()
{
points->doCompress();
}
void insertBufferedParticles()
{
points->insertBufferedParticles();
}
void kill(int id)
{
points->kill(id);
}
bool hasNeighbor(Vec3 pos, Real radius) const
{
bool answer = false;
int minI = clamp<int>(floor((pos.x - radius) / params.res * accel->res), 0, accel->res - 1);
int maxI = clamp<int>(floor((pos.x + radius) / params.res * accel->res), 0, accel->res - 1);
int minJ = clamp<int>(floor((pos.y - radius) / params.res * accel->res), 0, accel->res - 1);
int maxJ = clamp<int>(floor((pos.y + radius) / params.res * accel->res), 0, accel->res - 1);
int minK = clamp<int>(floor((pos.z - radius) / params.res * accel->res), 0, accel->res - 1);
int maxK = clamp<int>(floor((pos.z + radius) / params.res * accel->res), 0, accel->res - 1);
for (int i = minI; i <= maxI; i++) {
for (int j = minJ; j <= maxJ; j++) {
for (int k = minK; k <= maxK; k++) {
for (int id = 0; id < (int)accel->indices[i][j][k].size(); id++) {
if (points->isActive(accel->indices[i][j][k][id]) &&
norm(points->getPos(accel->indices[i][j][k][id]) - pos) <= radius) {
answer = true;
break;
}
}
if (answer)
break;
}
if (answer)
break;
}
if (answer)
break;
}
return answer;
}
bool hasNeighborOtherThanItself(int idx, Real radius) const
{
bool answer = false;
Vec3 pos = points->getPos(idx);
int minI = clamp<int>(floor((pos.x - radius) / params.res * accel->res), 0, accel->res - 1);
int maxI = clamp<int>(floor((pos.x + radius) / params.res * accel->res), 0, accel->res - 1);
int minJ = clamp<int>(floor((pos.y - radius) / params.res * accel->res), 0, accel->res - 1);
int maxJ = clamp<int>(floor((pos.y + radius) / params.res * accel->res), 0, accel->res - 1);
int minK = clamp<int>(floor((pos.z - radius) / params.res * accel->res), 0, accel->res - 1);
int maxK = clamp<int>(floor((pos.z + radius) / params.res * accel->res), 0, accel->res - 1);
for (int i = minI; i <= maxI; i++) {
for (int j = minJ; j <= maxJ; j++) {
for (int k = minK; k <= maxK; k++) {
for (int id = 0; id < (int)accel->indices[i][j][k].size(); id++) {
if (accel->indices[i][j][k][id] != idx &&
points->isActive(accel->indices[i][j][k][id]) &&
norm(points->getPos(accel->indices[i][j][k][id]) - pos) <= radius) {
answer = true;
break;
}
}
if (answer)
break;
}
if (answer)
break;
}
if (answer)
break;
}
return answer;
}
void removeInvalidIndices(vector<int> &indices)
{
vector<int> copy;
copy.resize(indices.size());
for (int i = 0; i < (int)indices.size(); i++) {
copy[i] = indices[i];
}
indices.clear();
for (int i = 0; i < (int)copy.size(); i++) {
if (points->isActive(copy[i])) {
indices.push_back(copy[i]);
}
}
}
};
struct ParticleDataImplVec3Wrapper : PointSetWrapper {
ParticleDataImpl<Vec3> *points;
ParticleDataImplVec3Wrapper(ParticleAccelGrid *inAccel) : PointSetWrapper(inAccel)
{
}
Vec3 getVec3(int id) const
{
return (*points)[id];
}
void setVec3(int id, Vec3 vec)
{
(*points)[id] = vec;
}
void updateAccel()
{
accel->fillWith(*points);
}
bool isActive(int i) const
{
return true;
}
};
//
// **** globals ****
//
ParticleAccelGrid accelCoarse, accelSurface;
BasicParticleSystemWrapper coarseParticles(&accelCoarse), surfacePoints(&accelSurface);
ParticleDataImplVec3Wrapper coarseParticlesPrevPos(
&accelCoarse); // WARNING: reusing the coarse accel grid to save space, don't query
// coarseParticlesPrevPos and coarseParticles at the same time.
vector<Vec3> tempSurfaceVec3; // to store misc info on surface points
vector<Real> tempSurfaceFloat; // to store misc info on surface points
int frameCount = 0;
//
//**** weighting kernels *****
//
Real triangularWeight(Real distance, Real radius)
{
return 1.0f - distance / radius;
}
Real exponentialWeight(Real distance, Real radius, Real falloff)
{
if (distance > radius)
return 0;
Real tmp = distance / radius;
return expf(-falloff * tmp * tmp);
}
Real weightKernelAdvection(Real distance)
{
if (distance > 2.f * params.outerRadius) {
return 0;
}
else {
return triangularWeight(distance, 2.f * params.outerRadius);
}
}
Real weightKernelCoarseDensity(Real distance)
{
return exponentialWeight(distance, params.outerRadius, 2.0f);
}
Real weightSurfaceNormal(Real distance)
{
if (distance > params.normalRadius) {
return 0;
}
else {
return triangularWeight(distance, params.normalRadius);
}
}
Real weightSurfaceTangent(Real distance)
{
if (distance > params.tangentRadius) {
return 0;
}
else {
return triangularWeight(distance, params.tangentRadius);
}
}
//
// **** utility ****
//
bool isInDomain(Vec3 pos)
{
return params.bndXm <= pos.x && pos.x <= params.bndXp && params.bndYm <= pos.y &&
pos.y <= params.bndYp && params.bndZm <= pos.z && pos.z <= params.bndZp;
}
Real smoothstep(Real edgeLeft, Real edgeRight, Real val)
{
Real x = clamp((val - edgeLeft) / (edgeRight - edgeLeft), Real(0.), Real(1.));
return x * x * (3 - 2 * x);
}
//
// **** surface initialization ****
//
void initFines(const BasicParticleSystemWrapper &coarseParticles,
BasicParticleSystemWrapper &surfacePoints,
const FlagGrid &flags)
{
unsigned int discretization = (unsigned int)M_PI * (params.outerRadius + params.innerRadius) /
params.meanFineDistance;
Real dtheta = 2 * params.meanFineDistance / (params.outerRadius + params.innerRadius);
Real outerRadius2 = params.outerRadius * params.outerRadius;
surfacePoints.clear();
for (int idx = 0; idx < (int)coarseParticles.size(); idx++) {
if (idx % 500 == 0) {
cout << "Initializing surface points : " << setprecision(4)
<< 100.f * idx / coarseParticles.size() << "%" << endl;
}
if (coarseParticles.isActive(idx)) {
// check flags if we are near surface
bool nearSurface = false;
Vec3 pos = coarseParticles.getPos(idx);
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
for (int k = -1; k <= 1; k++) {
if (!flags.isFluid(((int)pos.x) + i, ((int)pos.y) + j, ((int)pos.z) + k)) {
nearSurface = true;
break;
}
}
}
}
if (nearSurface) {
for (unsigned int i = 0; i <= discretization / 2; ++i) {
Real discretization2 = Real(floor(2 * M_PI * sin(i * dtheta) / dtheta) + 1);
for (Real phi = 0; phi < 2 * M_PI; phi += Real(2 * M_PI / discretization2)) {
Real theta = i * dtheta;
Vec3 normal(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));
Vec3 position = coarseParticles.getPos(idx) + params.outerRadius * normal;
bool valid = true;
LOOP_NEIGHBORS_BEGIN(coarseParticles, position, 2.f * params.outerRadius)
if (idx != idn && normSquare(position - coarseParticles.getPos(idn)) < outerRadius2) {
valid = false;
break;
}
LOOP_NEIGHBORS_END
if (valid) {
surfacePoints.addParticle(position);
}
}
}
}
}
}
}
//
// **** surface advection ****
//
struct advectSurfacePoints : public KernelBase {
advectSurfacePoints(BasicParticleSystemWrapper &surfacePoints,
const BasicParticleSystemWrapper &coarseParticles,
const ParticleDataImplVec3Wrapper &coarseParticlesPrevPos)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
coarseParticles(coarseParticles),
coarseParticlesPrevPos(coarseParticlesPrevPos)
{
runMessage();
run();
}
inline void op(IndexInt idx,
BasicParticleSystemWrapper &surfacePoints,
const BasicParticleSystemWrapper &coarseParticles,
const ParticleDataImplVec3Wrapper &coarseParticlesPrevPos) const
{
if (surfacePoints.isActive(idx)) {
Vec3 avgDisplacement(0, 0, 0);
Real totalWeight = 0;
Vec3 p = surfacePoints.getPos(idx);
LOOP_NEIGHBORS_BEGIN(
coarseParticlesPrevPos, surfacePoints.getPos(idx), 2.0f * params.outerRadius)
if ((coarseParticles.getStatus(idn) & ParticleBase::PNEW) == 0 &&
(coarseParticles.getStatus(idn) & ParticleBase::PDELETE) == 0) {
Vec3 disp = coarseParticles.getPos(idn) - coarseParticlesPrevPos.getVec3(idn);
Real distance = norm(coarseParticlesPrevPos.getVec3(idn) - p);
Real w = weightKernelAdvection(distance);
avgDisplacement += w * disp;
totalWeight += w;
}
LOOP_NEIGHBORS_END
if (totalWeight != 0)
avgDisplacement /= totalWeight;
surfacePoints.setPos(idx, p + avgDisplacement);
}
}
inline BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline const BasicParticleSystemWrapper &getArg1()
{
return coarseParticles;
}
typedef BasicParticleSystemWrapper type1;
inline const ParticleDataImplVec3Wrapper &getArg2()
{
return coarseParticlesPrevPos;
}
typedef ParticleDataImplVec3Wrapper type2;
void runMessage()
{
debMsg("Executing kernel advectSurfacePoints ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, coarseParticles, coarseParticlesPrevPos);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
BasicParticleSystemWrapper &surfacePoints;
const BasicParticleSystemWrapper &coarseParticles;
const ParticleDataImplVec3Wrapper &coarseParticlesPrevPos;
};
//
// **** value and gradient of level-set band constraint ****
//
Real computeConstraintLevel(const BasicParticleSystemWrapper &coarseParticles, Vec3 pos)
{
Real lvl = 0.0f;
LOOP_NEIGHBORS_BEGIN(coarseParticles, pos, 1.5f * params.outerRadius)
lvl += expf(-params.constraintA * normSquare(coarseParticles.getPos(idn) - pos));
LOOP_NEIGHBORS_END
if (lvl > 1.0f)
lvl = 1.0f;
lvl = (sqrtf(-logf(lvl) / params.constraintA) - params.innerRadius) /
(params.outerRadius - params.innerRadius);
return lvl;
}
Vec3 computeConstraintGradient(const BasicParticleSystemWrapper &coarseParticles, Vec3 pos)
{
Vec3 gradient(0, 0, 0);
LOOP_NEIGHBORS_BEGIN(coarseParticles, pos, 1.5f * params.outerRadius)
gradient += 2.f * params.constraintA *
(Real)(expf(-params.constraintA * normSquare(coarseParticles.getPos(idn) - pos))) *
(pos - coarseParticles.getPos(idn));
LOOP_NEIGHBORS_END
return getNormalized(gradient);
}
//
// **** compute surface normals ****
//
struct computeSurfaceNormals : public KernelBase {
computeSurfaceNormals(const BasicParticleSystemWrapper &surfacePoints,
const BasicParticleSystemWrapper &coarseParticles,
ParticleDataImpl<Vec3> &surfaceNormals)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
coarseParticles(coarseParticles),
surfaceNormals(surfaceNormals)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
const BasicParticleSystemWrapper &coarseParticles,
ParticleDataImpl<Vec3> &surfaceNormals) const
{
Vec3 pos = surfacePoints.getPos(idx);
// approx normal with gradient
Vec3 gradient = computeConstraintGradient(coarseParticles, pos);
// get tangent frame
Vec3 n = getNormalized(gradient);
Vec3 vx(1, 0, 0);
Vec3 vy(0, 1, 0);
Real dotX = dot(n, vx);
Real dotY = dot(n, vy);
Vec3 t1 = getNormalized(fabs(dotX) < fabs(dotY) ? cross(n, vx) : cross(n, vy));
Vec3 t2 = getNormalized(cross(n, t1)); // initial frame
// linear fit of neighboring surface points in approximated tangent frame
Real sw = 0, swx = 0, swy = 0, swxy = 0, swx2 = 0, swy2 = 0, swxz = 0, swyz = 0, swz = 0;
LOOP_NEIGHBORS_BEGIN(surfacePoints, pos, params.normalRadius)
LOOP_GHOSTS_POS_BEGIN(surfacePoints.getPos(idn), params.normalRadius)
Real x = dot(gPos - pos, t1);
Real y = dot(gPos - pos, t2);
Real z = dot(gPos - pos, n);
Real w = weightSurfaceNormal(norm(pos - gPos));
swx2 += w * x * x;
swy2 += w * y * y;
swxy += w * x * y;
swxz += w * x * z;
swyz += w * y * z;
swx += w * x;
swy += w * y;
swz += w * z;
sw += w;
LOOP_GHOSTS_END
LOOP_NEIGHBORS_END
Real det = -sw * swxy * swxy + 2.f * swx * swxy * swy - swx2 * swy * swy - swx * swx * swy2 +
sw * swx2 * swy2;
if (det == 0) {
surfaceNormals[idx] = Vec3(0, 0, 0);
}
else {
Vec3 abc = 1.f / det *
Vec3(swxz * (-swy * swy + sw * swy2) + swyz * (-sw * swxy + swx * swy) +
swz * (swxy * swy - swx * swy2),
swxz * (-sw * swxy + swx * swy) + swyz * (-swx * swx + sw * swx2) +
swz * (swx * swxy - swx2 * swy),
swxz * (swxy * swy - swx * swy2) + swyz * (swx * swxy - swx2 * swy) +
swz * (-swxy * swxy + swx2 * swy2));
Vec3 normal = -getNormalized(t1 * abc.x + t2 * abc.y - n);
if (dot(gradient, normal) < 0) {
normal = -normal;
}
surfaceNormals[idx] = normal;
}
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline const BasicParticleSystemWrapper &getArg1()
{
return coarseParticles;
}
typedef BasicParticleSystemWrapper type1;
inline ParticleDataImpl<Vec3> &getArg2()
{
return surfaceNormals;
}
typedef ParticleDataImpl<Vec3> type2;
void runMessage()
{
debMsg("Executing kernel computeSurfaceNormals ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, coarseParticles, surfaceNormals);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
const BasicParticleSystemWrapper &coarseParticles;
ParticleDataImpl<Vec3> &surfaceNormals;
};
//
// **** smooth surface normals ****
//
struct computeAveragedNormals : public KernelBase {
computeAveragedNormals(const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceNormals(surfaceNormals)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals) const
{
Vec3 pos = surfacePoints.getPos(idx);
Vec3 newNormal = Vec3(0, 0, 0);
LOOP_NEIGHBORS_BEGIN(surfacePoints, pos, params.normalRadius)
Real w = weightSurfaceNormal(norm(pos - surfacePoints.getPos(idn)));
newNormal += w * surfaceNormals[idn];
LOOP_NEIGHBORS_END
tempSurfaceVec3[idx] = getNormalized(newNormal);
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline const ParticleDataImpl<Vec3> &getArg1()
{
return surfaceNormals;
}
typedef ParticleDataImpl<Vec3> type1;
void runMessage()
{
debMsg("Executing kernel computeAveragedNormals ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, surfaceNormals);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
const ParticleDataImpl<Vec3> &surfaceNormals;
};
struct assignNormals : public KernelBase {
assignNormals(const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Vec3> &surfaceNormals)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceNormals(surfaceNormals)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Vec3> &surfaceNormals) const
{
surfaceNormals[idx] = tempSurfaceVec3[idx];
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline ParticleDataImpl<Vec3> &getArg1()
{
return surfaceNormals;
}
typedef ParticleDataImpl<Vec3> type1;
void runMessage()
{
debMsg("Executing kernel assignNormals ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, surfaceNormals);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
ParticleDataImpl<Vec3> &surfaceNormals;
};
void smoothSurfaceNormals(const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Vec3> &surfaceNormals)
{
tempSurfaceVec3.resize(surfacePoints.size());
computeAveragedNormals(surfacePoints, surfaceNormals);
assignNormals(surfacePoints, surfaceNormals);
}
//
// **** addition/deletion of particles. Not parallel to prevent write/delete conflicts ****
//
void addDeleteSurfacePoints(BasicParticleSystemWrapper &surfacePoints)
{
int fixedSize = surfacePoints.size();
for (int idx = 0; idx < fixedSize; idx++) {
// compute proxy tangent displacement
Vec3 pos = surfacePoints.getPos(idx);
Vec3 gradient = computeConstraintGradient(coarseParticles, pos);
Real wt = 0;
Vec3 tangentDisplacement(0, 0, 0);
LOOP_NEIGHBORS_BEGIN(surfacePoints, pos, params.tangentRadius)
if (idn != idx) {
Vec3 dir = pos - surfacePoints.getPos(idn);
Real length = norm(dir);
dir = getNormalized(dir);
// Decompose direction into normal and tangent directions.
Vec3 dn = dot(dir, gradient) * gradient;
Vec3 dt = dir - dn;
Real w = weightSurfaceTangent(length);
wt += w;
tangentDisplacement += w * dt;
}
LOOP_NEIGHBORS_END
if (norm(tangentDisplacement) != 0) {
tangentDisplacement = getNormalized(tangentDisplacement);
}
// check density criterion, add surface point if necessary
Vec3 creationPos = pos + params.meanFineDistance * tangentDisplacement;
if (isInDomain(creationPos) &&
!surfacePoints.hasNeighbor(creationPos, params.meanFineDistance - (1e-6))) {
// create point
surfacePoints.addBuffered(creationPos);
}
}
surfacePoints.doCompress();
surfacePoints.insertBufferedParticles();
// check density criterion, delete surface points if necessary
fixedSize = surfacePoints.size();
for (int idx = 0; idx < fixedSize; idx++) {
if (!isInDomain(surfacePoints.getPos(idx)) ||
surfacePoints.hasNeighborOtherThanItself(idx, 0.67 * params.meanFineDistance)) {
surfacePoints.kill(idx);
}
}
// delete surface points if no coarse neighbors in advection radius
fixedSize = surfacePoints.size();
for (int idx = 0; idx < fixedSize; idx++) {
Vec3 pos = surfacePoints.getPos(idx);
if (!coarseParticles.hasNeighbor(pos, 2.f * params.outerRadius)) {
surfacePoints.kill(idx);
}
}
// delete surface point if too far from constraint
fixedSize = surfacePoints.size();
for (int idx = 0; idx < fixedSize; idx++) {
Real level = computeConstraintLevel(coarseParticles, surfacePoints.getPos(idx));
if (level < -0.2 || level > 1.2) {
surfacePoints.kill(idx);
}
}
surfacePoints.doCompress();
surfacePoints.insertBufferedParticles();
}
//
// **** surface maintenance ****
//
struct computeSurfaceDensities : public KernelBase {
computeSurfaceDensities(const BasicParticleSystemWrapper &surfacePoints, void *dummy)
: KernelBase(surfacePoints.size()), surfacePoints(surfacePoints), dummy(dummy)
{
runMessage();
run();
}
inline void op(IndexInt idx, const BasicParticleSystemWrapper &surfacePoints, void *dummy) const
{
Vec3 pos = surfacePoints.getPos(idx);
Real density = 0;
LOOP_NEIGHBORS_BEGIN(surfacePoints, pos, params.normalRadius)
LOOP_GHOSTS_POS_BEGIN(surfacePoints.getPos(idn), params.normalRadius)
density += weightSurfaceNormal(norm(pos - gPos));
LOOP_GHOSTS_END
LOOP_NEIGHBORS_END
tempSurfaceFloat[idx] = density;
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline void *getArg1()
{
return dummy;
}
typedef void type1;
void runMessage()
{
debMsg("Executing kernel computeSurfaceDensities ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, dummy);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
void *dummy;
};
struct computeSurfaceDisplacements : public KernelBase {
computeSurfaceDisplacements(const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceNormals(surfaceNormals)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals) const
{
Vec3 pos = surfacePoints.getPos(idx);
Vec3 normal = surfaceNormals[idx];
Vec3 displacementNormal(0, 0, 0);
Vec3 displacementTangent(0, 0, 0);
Real wTotal = 0;
LOOP_NEIGHBORS_BEGIN(surfacePoints, pos, params.normalRadius)
LOOP_GHOSTS_POS_NORMAL_BEGIN(
surfacePoints.getPos(idn), surfaceNormals[idn], params.normalRadius)
Vec3 dir = pos - gPos;
Real length = norm(dir);
Vec3 dn = dot(dir, surfaceNormals[idx]) * surfaceNormals[idx];
Vec3 dt = dir - dn;
if (tempSurfaceFloat[idn] == 0) {
continue;
}
Real w = weightSurfaceNormal(length) / tempSurfaceFloat[idn];
Vec3 crossVec = getNormalized(cross(normal, -dir));
Vec3 projectedNormal = getNormalized(gNormal - dot(crossVec, gNormal) * crossVec);
if (dot(projectedNormal, normal) < 0 || abs(dot(normal, normal + projectedNormal)) < 1e-6) {
continue;
}
dn = -dot(normal + projectedNormal, dir) / dot(normal, normal + projectedNormal) * normal;
displacementNormal += w * dn;
displacementTangent += w * getNormalized(dt);
wTotal += w;
LOOP_GHOSTS_END
LOOP_NEIGHBORS_END
if (wTotal != 0) {
displacementNormal /= wTotal;
displacementTangent /= wTotal;
}
displacementNormal *= .75f;
displacementTangent *= .25f * params.meanFineDistance;
tempSurfaceVec3[idx] = displacementNormal + displacementTangent;
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline const ParticleDataImpl<Vec3> &getArg1()
{
return surfaceNormals;
}
typedef ParticleDataImpl<Vec3> type1;
void runMessage()
{
debMsg("Executing kernel computeSurfaceDisplacements ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, surfaceNormals);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
const ParticleDataImpl<Vec3> &surfaceNormals;
};
struct applySurfaceDisplacements : public KernelBase {
applySurfaceDisplacements(BasicParticleSystemWrapper &surfacePoints, void *dummy)
: KernelBase(surfacePoints.size()), surfacePoints(surfacePoints), dummy(dummy)
{
runMessage();
run();
}
inline void op(IndexInt idx, BasicParticleSystemWrapper &surfacePoints, void *dummy) const
{
surfacePoints.setPos(idx, surfacePoints.getPos(idx) + tempSurfaceVec3[idx]);
}
inline BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline void *getArg1()
{
return dummy;
}
typedef void type1;
void runMessage()
{
debMsg("Executing kernel applySurfaceDisplacements ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, dummy);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
BasicParticleSystemWrapper &surfacePoints;
void *dummy;
};
void regularizeSurfacePoints(BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals)
{
tempSurfaceVec3.resize(surfacePoints.size());
tempSurfaceFloat.resize(surfacePoints.size());
computeSurfaceDensities(surfacePoints, 0);
computeSurfaceDisplacements(surfacePoints, surfaceNormals);
applySurfaceDisplacements(surfacePoints, 0);
}
struct constrainSurface : public KernelBase {
constrainSurface(BasicParticleSystemWrapper &surfacePoints,
const BasicParticleSystemWrapper &coarseParticles)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
coarseParticles(coarseParticles)
{
runMessage();
run();
}
inline void op(IndexInt idx,
BasicParticleSystemWrapper &surfacePoints,
const BasicParticleSystemWrapper &coarseParticles) const
{
Vec3 pos = surfacePoints.getPos(idx);
Real level = computeConstraintLevel(coarseParticles, surfacePoints.getPos(idx));
if (level > 1) {
surfacePoints.setPos(
idx,
pos - (params.outerRadius - params.innerRadius) * (level - 1) *
computeConstraintGradient(coarseParticles, surfacePoints.getPos(idx)));
}
else if (level < 0) {
surfacePoints.setPos(
idx,
pos - (params.outerRadius - params.innerRadius) * level *
computeConstraintGradient(coarseParticles, surfacePoints.getPos(idx)));
}
}
inline BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline const BasicParticleSystemWrapper &getArg1()
{
return coarseParticles;
}
typedef BasicParticleSystemWrapper type1;
void runMessage()
{
debMsg("Executing kernel constrainSurface ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, coarseParticles);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
BasicParticleSystemWrapper &surfacePoints;
const BasicParticleSystemWrapper &coarseParticles;
};
struct interpolateNewWaveData : public KernelBase {
interpolateNewWaveData(const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Real> &surfaceWaveH,
ParticleDataImpl<Real> &surfaceWaveDtH,
ParticleDataImpl<Real> &surfaceWaveSeed,
ParticleDataImpl<Real> &surfaceWaveSeedAmplitude)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceWaveH(surfaceWaveH),
surfaceWaveDtH(surfaceWaveDtH),
surfaceWaveSeed(surfaceWaveSeed),
surfaceWaveSeedAmplitude(surfaceWaveSeedAmplitude)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Real> &surfaceWaveH,
ParticleDataImpl<Real> &surfaceWaveDtH,
ParticleDataImpl<Real> &surfaceWaveSeed,
ParticleDataImpl<Real> &surfaceWaveSeedAmplitude) const
{
if (surfacePoints.getStatus(idx) & ParticleBase::PNEW) {
Vec3 pos = surfacePoints.getPos(idx);
surfaceWaveH[idx] = 0;
surfaceWaveDtH[idx] = 0;
Real wTotal = 0;
LOOP_NEIGHBORS_BEGIN(surfacePoints, pos, params.tangentRadius)
if (!(surfacePoints.getStatus(idn) & ParticleBase::PNEW)) {
Real w = weightSurfaceTangent(norm(pos - surfacePoints.getPos(idn)));
surfaceWaveH[idx] += w * surfaceWaveH[idn];
surfaceWaveDtH[idx] += w * surfaceWaveDtH[idn];
surfaceWaveSeed[idx] += w * surfaceWaveSeed[idn];
surfaceWaveSeedAmplitude[idx] += w * surfaceWaveSeedAmplitude[idn];
wTotal += w;
}
LOOP_NEIGHBORS_END
if (wTotal != 0) {
surfaceWaveH[idx] /= wTotal;
surfaceWaveDtH[idx] /= wTotal;
surfaceWaveSeed[idx] /= wTotal;
surfaceWaveSeedAmplitude[idx] /= wTotal;
}
}
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline ParticleDataImpl<Real> &getArg1()
{
return surfaceWaveH;
}
typedef ParticleDataImpl<Real> type1;
inline ParticleDataImpl<Real> &getArg2()
{
return surfaceWaveDtH;
}
typedef ParticleDataImpl<Real> type2;
inline ParticleDataImpl<Real> &getArg3()
{
return surfaceWaveSeed;
}
typedef ParticleDataImpl<Real> type3;
inline ParticleDataImpl<Real> &getArg4()
{
return surfaceWaveSeedAmplitude;
}
typedef ParticleDataImpl<Real> type4;
void runMessage()
{
debMsg("Executing kernel interpolateNewWaveData ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx,
surfacePoints,
surfaceWaveH,
surfaceWaveDtH,
surfaceWaveSeed,
surfaceWaveSeedAmplitude);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
ParticleDataImpl<Real> &surfaceWaveH;
ParticleDataImpl<Real> &surfaceWaveDtH;
ParticleDataImpl<Real> &surfaceWaveSeed;
ParticleDataImpl<Real> &surfaceWaveSeedAmplitude;
};
void surfaceMaintenance(const BasicParticleSystemWrapper &coarseParticles,
BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Vec3> &surfaceNormals,
ParticleDataImpl<Real> &surfaceWaveH,
ParticleDataImpl<Real> &surfaceWaveDtH,
ParticleDataImpl<Real> &surfaceWaveSeed,
ParticleDataImpl<Real> &surfaceWaveSeedAmplitude,
int nbIterations)
{
int countIterations = nbIterations;
while (countIterations > 0) {
addDeleteSurfacePoints(surfacePoints);
surfacePoints.updateAccel();
computeSurfaceNormals(surfacePoints, coarseParticles, surfaceNormals);
smoothSurfaceNormals(surfacePoints, surfaceNormals);
regularizeSurfacePoints(surfacePoints, surfaceNormals);
surfacePoints.updateAccel();
constrainSurface(surfacePoints, coarseParticles);
surfacePoints.updateAccel();
interpolateNewWaveData(
surfacePoints, surfaceWaveH, surfaceWaveDtH, surfaceWaveSeed, surfaceWaveSeedAmplitude);
countIterations--;
}
}
//
// **** surface wave seeding and evolution ****
//
struct addSeed : public KernelBase {
addSeed(const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Real> &surfaceWaveH,
const ParticleDataImpl<Real> &surfaceWaveSeed)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceWaveH(surfaceWaveH),
surfaceWaveSeed(surfaceWaveSeed)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Real> &surfaceWaveH,
const ParticleDataImpl<Real> &surfaceWaveSeed) const
{
surfaceWaveH[idx] += surfaceWaveSeed[idx];
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline ParticleDataImpl<Real> &getArg1()
{
return surfaceWaveH;
}
typedef ParticleDataImpl<Real> type1;
inline const ParticleDataImpl<Real> &getArg2()
{
return surfaceWaveSeed;
}
typedef ParticleDataImpl<Real> type2;
void runMessage()
{
debMsg("Executing kernel addSeed ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, surfaceWaveH, surfaceWaveSeed);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
ParticleDataImpl<Real> &surfaceWaveH;
const ParticleDataImpl<Real> &surfaceWaveSeed;
};
struct computeSurfaceWaveNormal : public KernelBase {
computeSurfaceWaveNormal(const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals,
const ParticleDataImpl<Real> &surfaceWaveH)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceNormals(surfaceNormals),
surfaceWaveH(surfaceWaveH)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals,
const ParticleDataImpl<Real> &surfaceWaveH) const
{
Vec3 pos = surfacePoints.getPos(idx);
// get tangent frame
Vec3 n = getNormalized(surfaceNormals[idx]);
Vec3 vx(1, 0, 0);
Vec3 vy(0, 1, 0);
Real dotX = dot(n, vx);
Real dotY = dot(n, vy);
Vec3 t1 = getNormalized(fabs(dotX) < fabs(dotY) ? cross(n, vx) : cross(n, vy));
Vec3 t2 = getNormalized(cross(n, t1));
// linear fit
Real sw = 0, swx = 0, swy = 0, swxy = 0, swx2 = 0, swy2 = 0, swxz = 0, swyz = 0, swz = 0;
LOOP_NEIGHBORS_BEGIN(surfacePoints, pos, params.tangentRadius)
LOOP_GHOSTS_POS_BEGIN(surfacePoints.getPos(idn), params.tangentRadius)
Real x = dot(gPos - pos, t1);
Real y = dot(gPos - pos, t2);
Real z = surfaceWaveH[idn];
Real w = weightSurfaceTangent(norm(pos - gPos));
swx2 += w * x * x;
swy2 += w * y * y;
swxy += w * x * y;
swxz += w * x * z;
swyz += w * y * z;
swx += w * x;
swy += w * y;
swz += w * z;
sw += w;
LOOP_GHOSTS_END
LOOP_NEIGHBORS_END
Real det = -sw * swxy * swxy + 2.f * swx * swxy * swy - swx2 * swy * swy - swx * swx * swy2 +
sw * swx2 * swy2;
if (det == 0) {
tempSurfaceVec3[idx] = Vec3(0, 0, 0);
}
else {
Vec3 abc = 1.f / det *
Vec3(swxz * (-swy * swy + sw * swy2) + swyz * (-sw * swxy + swx * swy) +
swz * (swxy * swy - swx * swy2),
swxz * (-sw * swxy + swx * swy) + swyz * (-swx * swx + sw * swx2) +
swz * (swx * swxy - swx2 * swy),
swxz * (swxy * swy - swx * swy2) + swyz * (swx * swxy - swx2 * swy) +
swz * (-swxy * swxy + swx2 * swy2));
Vec3 waveNormal = -getNormalized(vx * abc.x + vy * abc.y - Vec3(0, 0, 1));
tempSurfaceVec3[idx] = waveNormal;
}
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline const ParticleDataImpl<Vec3> &getArg1()
{
return surfaceNormals;
}
typedef ParticleDataImpl<Vec3> type1;
inline const ParticleDataImpl<Real> &getArg2()
{
return surfaceWaveH;
}
typedef ParticleDataImpl<Real> type2;
void runMessage()
{
debMsg("Executing kernel computeSurfaceWaveNormal ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, surfaceNormals, surfaceWaveH);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
const ParticleDataImpl<Vec3> &surfaceNormals;
const ParticleDataImpl<Real> &surfaceWaveH;
};
struct computeSurfaceWaveLaplacians : public KernelBase {
computeSurfaceWaveLaplacians(const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals,
const ParticleDataImpl<Real> &surfaceWaveH)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceNormals(surfaceNormals),
surfaceWaveH(surfaceWaveH)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals,
const ParticleDataImpl<Real> &surfaceWaveH) const
{
Real laplacian = 0;
Real wTotal = 0;
Vec3 pPos = surfacePoints.getPos(idx);
Vec3 pNormal = surfaceNormals[idx];
Vec3 vx(1, 0, 0);
Vec3 vy(0, 1, 0);
Real dotX = dot(pNormal, vx);
Real dotY = dot(pNormal, vy);
Vec3 t1 = getNormalized(fabs(dotX) < fabs(dotY) ? cross(pNormal, vx) : cross(pNormal, vy));
Vec3 t2 = getNormalized(cross(pNormal, t1));
Vec3 pWaveNormal = tempSurfaceVec3[idx];
Real ph = surfaceWaveH[idx];
if (pWaveNormal.z == 0) {
tempSurfaceFloat[idx] = 0;
}
else {
LOOP_NEIGHBORS_BEGIN(surfacePoints, pPos, params.tangentRadius)
Real nh = surfaceWaveH[idn];
LOOP_GHOSTS_POS_BEGIN(surfacePoints.getPos(idn), params.tangentRadius)
Vec3 dir = gPos - pPos;
Real lengthDir = norm(dir);
if (lengthDir < 1e-5)
continue;
Vec3 tangentDir = lengthDir * getNormalized(dir - dot(dir, pNormal) * pNormal);
Real dirX = dot(tangentDir, t1);
Real dirY = dot(tangentDir, t2);
Real dz = nh - ph - (-pWaveNormal.x / pWaveNormal.z) * dirX -
(-pWaveNormal.y / pWaveNormal.z) * dirY;
Real w = weightSurfaceTangent(norm(pPos - gPos));
wTotal += w;
laplacian += clamp(w * 4 * dz / (lengthDir * lengthDir), Real(-100.), Real(100.));
LOOP_GHOSTS_END
LOOP_NEIGHBORS_END
if (wTotal != 0) {
tempSurfaceFloat[idx] = laplacian / wTotal;
}
else {
tempSurfaceFloat[idx] = 0;
}
}
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline const ParticleDataImpl<Vec3> &getArg1()
{
return surfaceNormals;
}
typedef ParticleDataImpl<Vec3> type1;
inline const ParticleDataImpl<Real> &getArg2()
{
return surfaceWaveH;
}
typedef ParticleDataImpl<Real> type2;
void runMessage()
{
debMsg("Executing kernel computeSurfaceWaveLaplacians ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, surfaceNormals, surfaceWaveH);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
const ParticleDataImpl<Vec3> &surfaceNormals;
const ParticleDataImpl<Real> &surfaceWaveH;
};
struct evolveWave : public KernelBase {
evolveWave(const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Real> &surfaceWaveH,
ParticleDataImpl<Real> &surfaceWaveDtH,
const ParticleDataImpl<Real> &surfaceWaveSeed)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceWaveH(surfaceWaveH),
surfaceWaveDtH(surfaceWaveDtH),
surfaceWaveSeed(surfaceWaveSeed)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Real> &surfaceWaveH,
ParticleDataImpl<Real> &surfaceWaveDtH,
const ParticleDataImpl<Real> &surfaceWaveSeed) const
{
surfaceWaveDtH[idx] += params.waveSpeed * params.waveSpeed * params.dt * tempSurfaceFloat[idx];
surfaceWaveDtH[idx] /= (1 + params.dt * params.waveDamping);
surfaceWaveH[idx] += params.dt * surfaceWaveDtH[idx];
surfaceWaveH[idx] /= (1 + params.dt * params.waveDamping);
surfaceWaveH[idx] -= surfaceWaveSeed[idx];
// clamp H and DtH (to prevent rare extreme behaviors)
surfaceWaveDtH[idx] = clamp(surfaceWaveDtH[idx],
-params.waveMaxFrequency * params.waveMaxAmplitude,
params.waveMaxFrequency * params.waveMaxAmplitude);
surfaceWaveH[idx] = clamp(
surfaceWaveH[idx], -params.waveMaxAmplitude, params.waveMaxAmplitude);
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline ParticleDataImpl<Real> &getArg1()
{
return surfaceWaveH;
}
typedef ParticleDataImpl<Real> type1;
inline ParticleDataImpl<Real> &getArg2()
{
return surfaceWaveDtH;
}
typedef ParticleDataImpl<Real> type2;
inline const ParticleDataImpl<Real> &getArg3()
{
return surfaceWaveSeed;
}
typedef ParticleDataImpl<Real> type3;
void runMessage()
{
debMsg("Executing kernel evolveWave ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, surfaceWaveH, surfaceWaveDtH, surfaceWaveSeed);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
ParticleDataImpl<Real> &surfaceWaveH;
ParticleDataImpl<Real> &surfaceWaveDtH;
const ParticleDataImpl<Real> &surfaceWaveSeed;
};
struct computeSurfaceCurvature : public KernelBase {
computeSurfaceCurvature(const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceNormals(surfaceNormals)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals) const
{
Vec3 pPos = surfacePoints.getPos(idx);
Real wTotal = 0;
Real curv = 0;
Vec3 pNormal = surfaceNormals[idx];
LOOP_NEIGHBORS_BEGIN(surfacePoints, pPos, params.normalRadius)
LOOP_GHOSTS_POS_NORMAL_BEGIN(
surfacePoints.getPos(idn), surfaceNormals[idn], params.normalRadius)
Vec3 dir = pPos - gPos;
if (dot(pNormal, gNormal) < 0) {
continue;
} // backfacing
Real dist = norm(dir);
if (dist < params.normalRadius / 100.f) {
continue;
}
Real distn = dot(dir, pNormal);
Real w = weightSurfaceNormal(dist);
curv += w * distn;
wTotal += w;
LOOP_GHOSTS_END
LOOP_NEIGHBORS_END
if (wTotal != 0) {
curv /= wTotal;
}
tempSurfaceFloat[idx] = fabs(curv);
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline const ParticleDataImpl<Vec3> &getArg1()
{
return surfaceNormals;
}
typedef ParticleDataImpl<Vec3> type1;
void runMessage()
{
debMsg("Executing kernel computeSurfaceCurvature ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, surfaceNormals);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
const ParticleDataImpl<Vec3> &surfaceNormals;
};
struct smoothCurvature : public KernelBase {
smoothCurvature(const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Real> &surfaceWaveSource)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceWaveSource(surfaceWaveSource)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Real> &surfaceWaveSource) const
{
Vec3 pPos = surfacePoints.getPos(idx);
Real curv = 0;
Real wTotal = 0;
LOOP_NEIGHBORS_BEGIN(surfacePoints, pPos, params.normalRadius)
Real w = weightSurfaceNormal(norm(pPos - surfacePoints.getPos(idn)));
curv += w * tempSurfaceFloat[idn];
wTotal += w;
LOOP_NEIGHBORS_END
if (wTotal != 0) {
curv /= wTotal;
}
surfaceWaveSource[idx] = curv;
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline ParticleDataImpl<Real> &getArg1()
{
return surfaceWaveSource;
}
typedef ParticleDataImpl<Real> type1;
void runMessage()
{
debMsg("Executing kernel smoothCurvature ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, surfaceWaveSource);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
ParticleDataImpl<Real> &surfaceWaveSource;
};
struct seedWaves : public KernelBase {
seedWaves(const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Real> &surfaceWaveSeed,
ParticleDataImpl<Real> &surfaceWaveSeedAmplitude,
ParticleDataImpl<Real> &surfaceWaveSource)
: KernelBase(surfacePoints.size()),
surfacePoints(surfacePoints),
surfaceWaveSeed(surfaceWaveSeed),
surfaceWaveSeedAmplitude(surfaceWaveSeedAmplitude),
surfaceWaveSource(surfaceWaveSource)
{
runMessage();
run();
}
inline void op(IndexInt idx,
const BasicParticleSystemWrapper &surfacePoints,
ParticleDataImpl<Real> &surfaceWaveSeed,
ParticleDataImpl<Real> &surfaceWaveSeedAmplitude,
ParticleDataImpl<Real> &surfaceWaveSource) const
{
Real source = smoothstep(params.waveSeedingCurvatureThresholdRegionCenter -
params.waveSeedingCurvatureThresholdRegionRadius,
params.waveSeedingCurvatureThresholdRegionCenter +
params.waveSeedingCurvatureThresholdRegionRadius,
(Real)surfaceWaveSource[idx]) *
2.f -
1.f;
Real freq = params.waveSeedFrequency;
Real theta = params.dt * frameCount * params.waveSpeed * freq;
Real costheta = cosf(theta);
Real maxSeedAmplitude = params.waveMaxSeedingAmplitude * params.waveMaxAmplitude;
surfaceWaveSeedAmplitude[idx] = clamp<Real>(surfaceWaveSeedAmplitude[idx] +
source * params.waveSeedStepSizeRatioOfMax *
maxSeedAmplitude,
0.f,
maxSeedAmplitude);
surfaceWaveSeed[idx] = surfaceWaveSeedAmplitude[idx] * costheta;
// source values for display (not used after this point anyway)
surfaceWaveSource[idx] = (source >= 0) ? 1 : 0;
}
inline const BasicParticleSystemWrapper &getArg0()
{
return surfacePoints;
}
typedef BasicParticleSystemWrapper type0;
inline ParticleDataImpl<Real> &getArg1()
{
return surfaceWaveSeed;
}
typedef ParticleDataImpl<Real> type1;
inline ParticleDataImpl<Real> &getArg2()
{
return surfaceWaveSeedAmplitude;
}
typedef ParticleDataImpl<Real> type2;
inline ParticleDataImpl<Real> &getArg3()
{
return surfaceWaveSource;
}
typedef ParticleDataImpl<Real> type3;
void runMessage()
{
debMsg("Executing kernel seedWaves ", 3);
debMsg("Kernel range"
<< " size " << size << " ",
4);
};
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
op(idx, surfacePoints, surfaceWaveSeed, surfaceWaveSeedAmplitude, surfaceWaveSource);
}
void run()
{
tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
}
const BasicParticleSystemWrapper &surfacePoints;
ParticleDataImpl<Real> &surfaceWaveSeed;
ParticleDataImpl<Real> &surfaceWaveSeedAmplitude;
ParticleDataImpl<Real> &surfaceWaveSource;
};
void surfaceWaves(const BasicParticleSystemWrapper &surfacePoints,
const ParticleDataImpl<Vec3> &surfaceNormals,
ParticleDataImpl<Real> &surfaceWaveH,
ParticleDataImpl<Real> &surfaceWaveDtH,
ParticleDataImpl<Real> &surfaceWaveSource,
ParticleDataImpl<Real> &surfaceWaveSeed,
ParticleDataImpl<Real> &surfaceWaveSeedAmplitude)
{
addSeed(surfacePoints, surfaceWaveH, surfaceWaveSeed);
computeSurfaceWaveNormal(surfacePoints, surfaceNormals, surfaceWaveH);
computeSurfaceWaveLaplacians(surfacePoints, surfaceNormals, surfaceWaveH);
evolveWave(surfacePoints, surfaceWaveH, surfaceWaveDtH, surfaceWaveSeed);
computeSurfaceCurvature(surfacePoints, surfaceNormals);
smoothCurvature(surfacePoints, surfaceWaveSource);
seedWaves(surfacePoints, surfaceWaveSeed, surfaceWaveSeedAmplitude, surfaceWaveSource);
}
//
// **** main function ****
//
void particleSurfaceTurbulence(const FlagGrid &flags,
BasicParticleSystem &coarseParts,
ParticleDataImpl<Vec3> &coarsePartsPrevPos,
BasicParticleSystem &surfPoints,
ParticleDataImpl<Vec3> &surfaceNormals,
ParticleDataImpl<Real> &surfaceWaveH,
ParticleDataImpl<Real> &surfaceWaveDtH,
BasicParticleSystem &surfacePointsDisplaced,
ParticleDataImpl<Real> &surfaceWaveSource,
ParticleDataImpl<Real> &surfaceWaveSeed,
ParticleDataImpl<Real> &surfaceWaveSeedAmplitude,
int res,
Real outerRadius = 1.0f,
int surfaceDensity = 20,
int nbSurfaceMaintenanceIterations = 4,
Real dt = 0.005f,
Real waveSpeed = 16.0f,
Real waveDamping = 0.0f,
Real waveSeedFrequency = 4,
Real waveMaxAmplitude = 0.25f,
Real waveMaxFrequency = 800,
Real waveMaxSeedingAmplitude = 0.5,
Real waveSeedingCurvatureThresholdRegionCenter = 0.025f,
Real waveSeedingCurvatureThresholdRegionRadius = 0.01f,
Real waveSeedStepSizeRatioOfMax = 0.05f)
{
#if USE_CHRONO == 1
static std::chrono::high_resolution_clock::time_point begin, end;
end = std::chrono::high_resolution_clock::now();
cout << std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count() / 1000000000.f
<< " : time sim" << endl;
begin = std::chrono::high_resolution_clock::now();
#endif
// wrap data
coarseParticles.points = &coarseParts;
coarseParticlesPrevPos.points = &coarsePartsPrevPos;
surfacePoints.points = &surfPoints;
// copy parameters
params.res = res;
params.outerRadius = outerRadius;
params.surfaceDensity = surfaceDensity;
params.nbSurfaceMaintenanceIterations = nbSurfaceMaintenanceIterations;
params.dt = dt;
params.waveSpeed = waveSpeed;
params.waveDamping = waveDamping;
params.waveSeedFrequency = waveSeedFrequency;
params.waveMaxAmplitude = waveMaxAmplitude;
params.waveMaxFrequency = waveMaxFrequency;
params.waveMaxSeedingAmplitude = waveMaxSeedingAmplitude;
params.waveSeedingCurvatureThresholdRegionCenter = waveSeedingCurvatureThresholdRegionCenter;
params.waveSeedingCurvatureThresholdRegionRadius = waveSeedingCurvatureThresholdRegionRadius;
params.waveSeedStepSizeRatioOfMax = waveSeedStepSizeRatioOfMax;
// compute other parameters
params.innerRadius = params.outerRadius / 2.0;
params.meanFineDistance = M_PI * (params.outerRadius + params.innerRadius) /
params.surfaceDensity;
params.constraintA = logf(2.0f / (1.0f + weightKernelCoarseDensity(params.outerRadius +
params.innerRadius))) /
(powf((params.outerRadius + params.innerRadius) / 2, 2) -
params.innerRadius * params.innerRadius);
params.normalRadius = 0.5f * (params.outerRadius + params.innerRadius);
params.tangentRadius = 2.1f * params.meanFineDistance;
params.bndXm = params.bndYm = params.bndZm = 2;
params.bndXp = params.bndYp = params.bndZp = params.res - 2;
if (frameCount == 0) {
// initialize accel grids
accelCoarse.init(2.f * res / params.outerRadius);
accelSurface.init(1.f * res / (2.f * params.meanFineDistance));
// update coarse accel structure
coarseParticles.updateAccel();
// create surface points
initFines(coarseParticles, surfacePoints, flags);
// smooth surface
surfaceMaintenance(coarseParticles,
surfacePoints,
surfaceNormals,
surfaceWaveH,
surfaceWaveDtH,
surfaceWaveSeed,
surfaceWaveSeedAmplitude,
6 * params.nbSurfaceMaintenanceIterations);
// set wave values to zero
for (int idx = 0; idx < surfacePoints.size(); idx++) {
surfaceWaveH[idx] = 0;
surfaceWaveDtH[idx] = 0;
surfaceWaveSeed[idx] = 0;
surfaceWaveSeedAmplitude[idx] = 0;
}
}
else {
// update coarse accel structure with previous coarse particles positions
coarseParticlesPrevPos.updateAccel();
// advect surface points following coarse particles
advectSurfacePoints(surfacePoints, coarseParticles, coarseParticlesPrevPos);
surfacePoints.updateAccel();
// update acceleration structure for surface points
coarseParticles.updateAccel();
// surface maintenance
surfaceMaintenance(coarseParticles,
surfacePoints,
surfaceNormals,
surfaceWaveH,
surfaceWaveDtH,
surfaceWaveSeed,
surfaceWaveSeedAmplitude,
params.nbSurfaceMaintenanceIterations);
// surface waves
surfaceWaves(surfacePoints,
surfaceNormals,
surfaceWaveH,
surfaceWaveDtH,
surfaceWaveSource,
surfaceWaveSeed,
surfaceWaveSeedAmplitude);
}
frameCount++;
// save positions as previous positions for next step
for (int id = 0; id < coarseParticles.size(); id++) {
if ((coarseParticles.getStatus(id) & ParticleBase::PNEW) == 0 &&
(coarseParticles.getStatus(id) & ParticleBase::PDELETE) == 0) {
coarseParticlesPrevPos.setVec3(id, coarseParticles.getPos(id));
}
}
// create displaced points for display
surfacePointsDisplaced.clear();
for (int idx = 0; idx < surfacePoints.size(); idx++) {
if ((surfacePoints.getStatus(idx) & ParticleBase::PDELETE) == 0) {
surfacePointsDisplaced.addParticle(surfacePoints.getPos(idx) +
surfaceNormals[idx] * surfaceWaveH[idx]);
}
}
#if USE_CHRONO == 1
end = std::chrono::high_resolution_clock::now();
cout << std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count() / 1000000000.f
<< " : time upres" << endl;
begin = std::chrono::high_resolution_clock::now();
#endif
}
static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "particleSurfaceTurbulence", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 0, &_lock);
BasicParticleSystem &coarseParts = *_args.getPtr<BasicParticleSystem>(
"coarseParts", 1, &_lock);
ParticleDataImpl<Vec3> &coarsePartsPrevPos = *_args.getPtr<ParticleDataImpl<Vec3>>(
"coarsePartsPrevPos", 2, &_lock);
BasicParticleSystem &surfPoints = *_args.getPtr<BasicParticleSystem>(
"surfPoints", 3, &_lock);
ParticleDataImpl<Vec3> &surfaceNormals = *_args.getPtr<ParticleDataImpl<Vec3>>(
"surfaceNormals", 4, &_lock);
ParticleDataImpl<Real> &surfaceWaveH = *_args.getPtr<ParticleDataImpl<Real>>(
"surfaceWaveH", 5, &_lock);
ParticleDataImpl<Real> &surfaceWaveDtH = *_args.getPtr<ParticleDataImpl<Real>>(
"surfaceWaveDtH", 6, &_lock);
BasicParticleSystem &surfacePointsDisplaced = *_args.getPtr<BasicParticleSystem>(
"surfacePointsDisplaced", 7, &_lock);
ParticleDataImpl<Real> &surfaceWaveSource = *_args.getPtr<ParticleDataImpl<Real>>(
"surfaceWaveSource", 8, &_lock);
ParticleDataImpl<Real> &surfaceWaveSeed = *_args.getPtr<ParticleDataImpl<Real>>(
"surfaceWaveSeed", 9, &_lock);
ParticleDataImpl<Real> &surfaceWaveSeedAmplitude = *_args.getPtr<ParticleDataImpl<Real>>(
"surfaceWaveSeedAmplitude", 10, &_lock);
int res = _args.get<int>("res", 11, &_lock);
Real outerRadius = _args.getOpt<Real>("outerRadius", 12, 1.0f, &_lock);
int surfaceDensity = _args.getOpt<int>("surfaceDensity", 13, 20, &_lock);
int nbSurfaceMaintenanceIterations = _args.getOpt<int>(
"nbSurfaceMaintenanceIterations", 14, 4, &_lock);
Real dt = _args.getOpt<Real>("dt", 15, 0.005f, &_lock);
Real waveSpeed = _args.getOpt<Real>("waveSpeed", 16, 16.0f, &_lock);
Real waveDamping = _args.getOpt<Real>("waveDamping", 17, 0.0f, &_lock);
Real waveSeedFrequency = _args.getOpt<Real>("waveSeedFrequency", 18, 4, &_lock);
Real waveMaxAmplitude = _args.getOpt<Real>("waveMaxAmplitude", 19, 0.25f, &_lock);
Real waveMaxFrequency = _args.getOpt<Real>("waveMaxFrequency", 20, 800, &_lock);
Real waveMaxSeedingAmplitude = _args.getOpt<Real>(
"waveMaxSeedingAmplitude", 21, 0.5, &_lock);
Real waveSeedingCurvatureThresholdRegionCenter = _args.getOpt<Real>(
"waveSeedingCurvatureThresholdRegionCenter", 22, 0.025f, &_lock);
Real waveSeedingCurvatureThresholdRegionRadius = _args.getOpt<Real>(
"waveSeedingCurvatureThresholdRegionRadius", 23, 0.01f, &_lock);
Real waveSeedStepSizeRatioOfMax = _args.getOpt<Real>(
"waveSeedStepSizeRatioOfMax", 24, 0.05f, &_lock);
_retval = getPyNone();
particleSurfaceTurbulence(flags,
coarseParts,
coarsePartsPrevPos,
surfPoints,
surfaceNormals,
surfaceWaveH,
surfaceWaveDtH,
surfacePointsDisplaced,
surfaceWaveSource,
surfaceWaveSeed,
surfaceWaveSeedAmplitude,
res,
outerRadius,
surfaceDensity,
nbSurfaceMaintenanceIterations,
dt,
waveSpeed,
waveDamping,
waveSeedFrequency,
waveMaxAmplitude,
waveMaxFrequency,
waveMaxSeedingAmplitude,
waveSeedingCurvatureThresholdRegionCenter,
waveSeedingCurvatureThresholdRegionRadius,
waveSeedStepSizeRatioOfMax);
_args.check();
}
pbFinalizePlugin(parent, "particleSurfaceTurbulence", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("particleSurfaceTurbulence", e.what());
return 0;
}
}
static const Pb::Register _RP_particleSurfaceTurbulence("", "particleSurfaceTurbulence", _W_0);
extern "C" {
void PbRegister_particleSurfaceTurbulence()
{
KEEP_UNUSED(_RP_particleSurfaceTurbulence);
}
}
void debugCheckParts(const BasicParticleSystem &parts, const FlagGrid &flags)
{
for (int idx = 0; idx < parts.size(); idx++) {
Vec3i p = toVec3i(parts.getPos(idx));
if (!flags.isInBounds(p)) {
debMsg("bad position??? " << idx << " " << parts.getPos(idx), 1);
exit(1);
}
}
}
static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
try {
PbArgs _args(_linargs, _kwds);
FluidSolver *parent = _args.obtainParent();
bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
pbPreparePlugin(parent, "debugCheckParts", !noTiming);
PyObject *_retval = 0;
{
ArgLocker _lock;
const BasicParticleSystem &parts = *_args.getPtr<BasicParticleSystem>("parts", 0, &_lock);
const FlagGrid &flags = *_args.getPtr<FlagGrid>("flags", 1, &_lock);
_retval = getPyNone();
debugCheckParts(parts, flags);
_args.check();
}
pbFinalizePlugin(parent, "debugCheckParts", !noTiming);
return _retval;
}
catch (std::exception &e) {
pbSetError("debugCheckParts", e.what());
return 0;
}
}
static const Pb::Register _RP_debugCheckParts("", "debugCheckParts", _W_1);
extern "C" {
void PbRegister_debugCheckParts()
{
KEEP_UNUSED(_RP_debugCheckParts);
}
}
} // namespace SurfaceTurbulence
} // namespace Manta