You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
4.6 KiB
120 lines
4.6 KiB
// --------------------------------------------------------------------------------------- |
|
// Custom plugin properties |
|
// --------------------------------------------------------------------------------------- |
|
|
|
|
|
// Holds output data for emitting particles |
|
typedef struct |
|
{ |
|
float4 emitPosition; // xyz - position, w[0] - mixing distance squared |
|
float4 emitVelocity; // xyz - velocity, w - particle system |
|
int fluidB; // only index 0 |
|
int fluidC; // only index 0 |
|
int fluidD; // only index 0 |
|
int mixingFluidsAreTheSame; // only index 0 |
|
} FluidMixerData; |
|
|
|
#define FLUVIO_PLUGIN_DATA_RW_0 FluidMixerData |
|
|
|
// --------------------------------------------------------------------------------------- |
|
// Main include |
|
// --------------------------------------------------------------------------------------- |
|
|
|
#include "../../Includes/FluvioCompute.cginc" |
|
|
|
// --------------------------------------------------------------------------------------- |
|
// Main plugin |
|
// --------------------------------------------------------------------------------------- |
|
|
|
FLUVIO_KERNEL(OnUpdatePlugin) |
|
{ |
|
int particleIndex = get_global_id(0); |
|
|
|
if (!FluvioShouldUpdatePlugin(particleIndex)) return; |
|
|
|
for(EachNeighbor(particleIndex, neighborIndex)) |
|
{ |
|
if (!FluvioShouldUpdatePluginNeighbor(neighborIndex)) continue; |
|
|
|
FLUVIO_BUFFER_RW(FluidMixerData) mixerData = FluvioGetPluginBuffer(0); |
|
|
|
int fluid = fluvio_PluginFluidID; |
|
int fluidB = mixerData[0].fluidB; |
|
int fluidC = mixerData[0].fluidC; |
|
int fluidD = mixerData[0].fluidD; |
|
int mixingFluidsAreTheSame = mixerData[0].mixingFluidsAreTheSame; |
|
float mixingDistanceSq = mixerData[0].emitPosition.w; |
|
|
|
int particleFluid = solverData_GetFluidID(particleIndex); |
|
int neighborFluid = solverData_GetFluidID(neighborIndex); |
|
|
|
bool particleIsA = particleFluid == fluid; |
|
|
|
if ((mixingFluidsAreTheSame == 1 || particleFluid != neighborFluid) && // Fluids are not the same, unless A and B are the same |
|
(particleIsA || particleFluid == fluidB) && // First fluid is A or B |
|
(neighborFluid == fluid || neighborFluid == fluidB)) // Second fluid is A or B |
|
{ |
|
|
|
float4 position = solverData_GetPosition(particleIndex); |
|
float4 neighborPosition = solverData_GetPosition(neighborIndex); |
|
float4 dist = position - neighborPosition; |
|
|
|
// Make sure the particles are actually close |
|
if (dot(dist,dist) > mixingDistanceSq) |
|
return; |
|
|
|
float4 velocity = solverData_GetVelocity(particleIndex); |
|
float4 invMass = 1.0f/solverData_GetMass(particleIndex); |
|
|
|
bool emitC = false; |
|
bool particleIsA = fluid == particleFluid; |
|
|
|
// Despawn the current particle, unless Fluid C is null and the particle is from Fluid A |
|
if (fluidC != 0 || !particleIsA) |
|
{ |
|
emitC = true; |
|
solverData_SetLifetime(particleIndex, 0.0f); |
|
} |
|
|
|
// Emit a particle. We don't emit from the neighbor position, that gets handled in the opposite pair |
|
// We handle actual emission on the main thread. |
|
if (fluidD == 0 || particleIsA) |
|
{ |
|
if (emitC) |
|
{ |
|
// Set the system to Fluid C |
|
mixerData[particleIndex].emitVelocity.w = fluidC; |
|
} |
|
else |
|
{ |
|
mixerData[particleIndex].emitVelocity.w = 0; |
|
} |
|
} |
|
else |
|
{ |
|
// Set the system to Fluid D |
|
mixerData[particleIndex].emitVelocity.w = fluidD; |
|
} |
|
|
|
// Set emit position and velocity. These must be manually integrated since they won't be applied until after the solver has run. |
|
// The below is a standard Euler explicit integrator. |
|
float4 acceleration = solverData_GetFluid(fluid).gravity + solverData_GetForce(particleIndex)*invMass; |
|
float dtIter = fluvio_Time.y; |
|
int iterations = fluvio_Time.w; |
|
|
|
for (int iter = 0; iter < iterations; ++iter) |
|
{ |
|
float4 t = dtIter*acceleration; |
|
|
|
// Ignore very large velocity changes |
|
if (dot(t,t) > (FLUVIO_MAX_SQR_VELOCITY_CHANGE * fluvio_KernelSize.w * fluvio_KernelSize.w)) |
|
t *= 0; |
|
|
|
velocity += t; |
|
} |
|
|
|
mixerData[particleIndex].emitVelocity.xyz = velocity.xyz; |
|
mixerData[particleIndex].emitPosition.xyz = position.xyz + velocity.xyz * fluvio_Time.x; |
|
} |
|
} |
|
}
|
|
|