天津23维预案
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

// ---------------------------------------------------------------------------------------
// 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;
}
}
}