added emitter - sph properties

This commit is contained in:
turanszkij
2018-05-07 14:18:40 +01:00
parent cf3fdea255
commit 0bd3ada39e
6 changed files with 237 additions and 53 deletions
+129 -2
View File
@@ -18,7 +18,7 @@ EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui)
float screenH = (float)wiRenderer::GetDevice()->GetScreenHeight();
emitterWindow = new wiWindow(GUI, "Emitter Window");
emitterWindow->SetSize(XMFLOAT2(760, 800));
emitterWindow->SetSize(XMFLOAT2(800, 1000));
emitterWindow->SetEnabled(false);
GUI->AddWidget(emitterWindow);
@@ -87,8 +87,22 @@ EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui)
emitterWindow->AddWidget(depthCollisionsCheckBox);
sphCheckBox = new wiCheckBox("SPH - FluidSim: ");
sphCheckBox->SetPos(XMFLOAT2(x + 400, y));
sphCheckBox->OnClick([&](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->SPH_FLUIDSIMULATION = args.bValue;
}
});
sphCheckBox->SetCheck(false);
sphCheckBox->SetTooltip("Enable particle collisions with each other. Simulate with Smooth Particle Hydrodynamics (SPH) solver.");
emitterWindow->AddWidget(sphCheckBox);
debugCheckBox = new wiCheckBox("DEBUG: ");
debugCheckBox->SetPos(XMFLOAT2(x + 350, y));
debugCheckBox->SetPos(XMFLOAT2(x + 500, y));
debugCheckBox->OnClick([&](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
@@ -252,8 +266,95 @@ EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui)
emitMotionBlurSlider->SetTooltip("Set the motion blur amount for the particle system.");
emitterWindow->AddWidget(emitMotionBlurSlider);
emitMassSlider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "Mass: ");
emitMassSlider->SetSize(XMFLOAT2(360, 30));
emitMassSlider->SetPos(XMFLOAT2(x, y += step));
emitMassSlider->OnSlide([&](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->mass = args.fValue;
}
});
emitMassSlider->SetEnabled(false);
emitMassSlider->SetTooltip("Set the mass per particle.");
emitterWindow->AddWidget(emitMassSlider);
//////////////// SPH ////////////////////////////
y += step;
sph_h_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Smoothing Radius (h): ");
sph_h_Slider->SetSize(XMFLOAT2(360, 30));
sph_h_Slider->SetPos(XMFLOAT2(x, y += step));
sph_h_Slider->OnSlide([&](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->SPH_h = args.fValue;
}
});
sph_h_Slider->SetEnabled(false);
sph_h_Slider->SetTooltip("Set the SPH parameter: smoothing radius");
emitterWindow->AddWidget(sph_h_Slider);
sph_K_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Pressure Constant (K): ");
sph_K_Slider->SetSize(XMFLOAT2(360, 30));
sph_K_Slider->SetPos(XMFLOAT2(x, y += step));
sph_K_Slider->OnSlide([&](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->SPH_K = args.fValue;
}
});
sph_K_Slider->SetEnabled(false);
sph_K_Slider->SetTooltip("Set the SPH parameter: pressure constant");
emitterWindow->AddWidget(sph_K_Slider);
sph_p0_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Reference Density (p0): ");
sph_p0_Slider->SetSize(XMFLOAT2(360, 30));
sph_p0_Slider->SetPos(XMFLOAT2(x, y += step));
sph_p0_Slider->OnSlide([&](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->SPH_p0 = args.fValue;
}
});
sph_p0_Slider->SetEnabled(false);
sph_p0_Slider->SetTooltip("Set the SPH parameter: reference density");
emitterWindow->AddWidget(sph_p0_Slider);
sph_e_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Viscosity (e): ");
sph_e_Slider->SetSize(XMFLOAT2(360, 30));
sph_e_Slider->SetPos(XMFLOAT2(x, y += step));
sph_e_Slider->OnSlide([&](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->SPH_e = args.fValue;
}
});
sph_e_Slider->SetEnabled(false);
sph_e_Slider->SetTooltip("Set the SPH parameter: viscosity constant");
emitterWindow->AddWidget(sph_e_Slider);
////// UTIL /////////////////
y += step;
materialSelectButton = new wiButton("Select Material");
materialSelectButton->SetPos(XMFLOAT2(x, y += step));
materialSelectButton->SetSize(XMFLOAT2(150, 30));
@@ -271,6 +372,26 @@ EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui)
emitterWindow->AddWidget(materialSelectButton);
restartButton = new wiButton("Restart Emitter");
restartButton->SetPos(XMFLOAT2(x + 200, y));
restartButton->SetSize(XMFLOAT2(150, 30));
restartButton->OnClick([&](wiEventArgs args) {
if (materialWnd != nullptr)
{
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->Restart();
}
}
});
restartButton->SetTooltip("Restart particle system emitter");
emitterWindow->AddWidget(restartButton);
emitterWindow->Translate(XMFLOAT3(200, 50, 0));
emitterWindow->SetVisible(false);
@@ -325,6 +446,12 @@ void EmitterWindow::SetObject(Object* obj)
emitRandomnessSlider->SetValue(emitter->random_factor);
emitLifeRandomnessSlider->SetValue(emitter->random_life);
emitMotionBlurSlider->SetValue(emitter->motionBlurAmount);
emitMassSlider->SetValue(emitter->mass);
sph_h_Slider->SetValue(emitter->SPH_h);
sph_K_Slider->SetValue(emitter->SPH_K);
sph_p0_Slider->SetValue(emitter->SPH_p0);
sph_e_Slider->SetValue(emitter->SPH_e);
}
emitterWindow->SetEnabled(true);
+7
View File
@@ -37,6 +37,7 @@ public:
wiSlider* maxParticlesSlider;
wiCheckBox* sortCheckBox;
wiCheckBox* depthCollisionsCheckBox;
wiCheckBox* sphCheckBox;
wiCheckBox* debugCheckBox;
wiSlider* emitCountSlider;
wiSlider* emitSizeSlider;
@@ -47,7 +48,13 @@ public:
wiSlider* emitRandomnessSlider;
wiSlider* emitLifeRandomnessSlider;
wiSlider* emitMotionBlurSlider;
wiSlider* emitMassSlider;
wiSlider* sph_h_Slider;
wiSlider* sph_K_Slider;
wiSlider* sph_p0_Slider;
wiSlider* sph_e_Slider;
wiButton* materialSelectButton;
wiButton* restartButton;
};
+13 -1
View File
@@ -41,9 +41,21 @@ CBUFFER(EmittedParticleCB, CBSLOT_OTHER_EMITTEDPARTICLE)
float xParticleLifeSpan;
float xParticleLifeSpanRandomness;
float xParticleMass;
float xParticleMotionBlurAmount;
float xEmitterOpacity;
float2 xPadding_EmitterCB;
float xPadding0_EmitterCB;
float xSPH_h; // smoothing radius
float xSPH_h2; // smoothing radius ^ 2
float xSPH_h3; // smoothing radius ^ 3
float xSPH_h6; // smoothing radius ^ 6
float xSPH_h9; // smoothing radius ^ 9
float xSPH_K; // pressure constant
float xSPH_p0; // reference density
float xSPH_e; // viscosity constant
};
CBUFFER(SortConstants, 0)
+58 -46
View File
@@ -34,7 +34,7 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, ui
LDSParticles[groupIndex].position = particleA.position;
LDSParticles[groupIndex].size = particleSizeA;
LDSParticles[groupIndex].v = particleA.velocity;
LDSParticles[groupIndex].m = 1;
LDSParticles[groupIndex].m = xParticleMass;
LDSParticles[groupIndex].p = 0;
LDSParticles[groupIndex].P = 0;
@@ -49,12 +49,18 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, ui
LDSParticle particleA = LDSParticles[particleIndexA];
// Compute density field:
// SPH params:
const float h = xSPH_h; // smoothing radius
const float h2 = xSPH_h2; // smoothing radius ^ 2
const float h3 = xSPH_h3; // smoothing radius ^ 3
const float h6 = xSPH_h6; // smoothing radius ^ 6
const float h9 = xSPH_h9; // smoothing radius ^ 9
const float K = xSPH_K; // pressure constant
const float p0 = xSPH_p0; // reference density
const float e = xSPH_e; // viscosity constant
const float h = 1.0f; // smoothing radius
const float h2 = h*h;
const float h3 = h2 * h;
const float h9 = h3 * h3;
// Compute density field:
uint i;
@@ -68,10 +74,10 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, ui
float3 diff = particleA.position - particleB.position;
float r2 = dot(diff, diff); // distance squared
float range = particleA.size + particleB.size; // range of affection
float range2 = range * range; // range squared
//float range = particleA.size + particleB.size; // range of affection
//float range2 = range * range; // range squared
if (r2 < range2)
if (r2 < h2)
{
float W = (315.0f / (64.0f * PI * h9)) * pow(h2 - r2, 3); // poly6 smoothing kernel
@@ -81,10 +87,15 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, ui
}
}
int asd = 0;
if (particleA.p > p0) asd = 1;
if (particleA.p < p0) asd = -1;
// Can't be lower than reference density to avoid negative pressure!
//particleA.p = max(p0, particleA.p);
// Compute particle pressure:
const float K = 20; // pressure constant
const float p0 = 20; // reference density
particleA.P = max(p0, K * (particleA.p - p0));
particleA.P = K * (max(p0, particleA.p) - p0);
// Store the results:
LDSParticles[particleIndexA].p = particleA.p;
@@ -101,7 +112,6 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, ui
// Compute acceleration:
float3 a = 0; // pressure force
float3 av = 0; // viscosity force
const float e = 0.018f; // viscosity constant
for (i = 0; i < LDSParticleCount; ++i)
{
@@ -114,33 +124,31 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, ui
float r2 = dot(diff, diff); // distance squared
float r = sqrt(r2);
float range = particleA.size + particleB.size; // range of affection
//float range = particleA.size + particleB.size; // range of affection
if (r < range)
if (r < h)
{
float3 rNorm = normalize(diff);
float W = (-45 / (PI * pow(h, 6))) * pow(h - r, 2); // spiky kernel smoothing function
float W = (-45 / (PI * h6)) * pow(h - r, 2); // spiky kernel smoothing function
a += -(particleB.m / particleA.m) * ((particleA.P + particleB.P) / (2 * particleA.p * particleB.p)) * W * rNorm;
a += (particleB.m / particleA.m) * ((particleA.P + particleB.P) / (2 * particleA.p * particleB.p)) * W * rNorm;
float r3 = r2 * r;
float h2 = h * h;
float h3 = h2 * h;
W = -(r3 / (2 * h3)) + (r2 / h2) + (h / (2 * r)) - 1;
av += e * (particleB.m / particleA.m) * (1.0f / particleB.p) * (particleB.v - particleA.v) * W * rNorm;
av += (particleB.m / particleA.m) * (1.0f / particleB.p) * (particleB.v - particleA.v) * W * rNorm;
}
}
}
//a *= -1;
//av *= e;
a *= -1;
av *= e;
float3 force = a + av;
const float dt = g_xFrame_DeltaTime;
particleA.v += dt * force / particleA.p;
particleA.position += dt * particleA.v;
}
@@ -152,28 +160,28 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, ui
particleA.v.y *= -elastic;
}
//// box collision:
//float extent = 4;
//if (particleA.position.x + particleA.size > extent)
//{
// particleA.position.x = extent - particleA.size;
// particleA.v.x *= -elastic;
//}
//if (particleA.position.x - particleA.size < -extent)
//{
// particleA.position.x = -extent + particleA.size;
// particleA.v.x *= -elastic;
//}
//if (particleA.position.z + particleA.size > extent)
//{
// particleA.position.z = extent - particleA.size;
// particleA.v.z *= -elastic;
//}
//if (particleA.position.z - particleA.size < -extent)
//{
// particleA.position.z = -extent + particleA.size;
// particleA.v.z *= -elastic;
//}
// box collision:
float extent = 2;
if (particleA.position.x + particleA.size > extent)
{
particleA.position.x = extent - particleA.size;
particleA.v.x *= -elastic;
}
if (particleA.position.x - particleA.size < -extent)
{
particleA.position.x = -extent + particleA.size;
particleA.v.x *= -elastic;
}
if (particleA.position.z + particleA.size > extent)
{
particleA.position.z = extent - particleA.size;
particleA.v.z *= -elastic;
}
if (particleA.position.z - particleA.size < -extent)
{
particleA.position.z = -extent + particleA.size;
particleA.v.z *= -elastic;
}
particleA.v *= 0.99f;
@@ -189,10 +197,14 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, ui
particleBuffer[writeIndex].color_mirror = 0x00FFFFFF;
//particleBuffer[writeIndex].color_mirror |= ((uint)particleA.p) & 0xFF;
if (particleA.p > 0)
if (asd > 0)
{
particleBuffer[writeIndex].color_mirror = 0xFF;
}
if (asd < 0)
{
particleBuffer[writeIndex].color_mirror = 0xFF00;
}
}
+22 -4
View File
@@ -279,6 +279,10 @@ void wiEmittedParticle::Burst(float num)
{
emit += num;
}
void wiEmittedParticle::Restart()
{
buffersUpToDate = false;
}
void wiEmittedParticle::UpdateRenderData(GRAPHICSTHREAD threadID)
@@ -304,6 +308,17 @@ void wiEmittedParticle::UpdateRenderData(GRAPHICSTHREAD threadID)
cb.xParticleRotation = rotation * XM_PI * 60;
cb.xParticleColor = wiMath::CompressColor(XMFLOAT4(material->baseColor.x, material->baseColor.y, material->baseColor.z, 1));
cb.xEmitterOpacity = material->alpha;
cb.xParticleMass = mass;
// SPH:
cb.xSPH_h = SPH_h;
cb.xSPH_h2 = SPH_h * SPH_h;
cb.xSPH_h3 = cb.xSPH_h2 * SPH_h;
cb.xSPH_h6 = cb.xSPH_h2 * cb.xSPH_h2 * cb.xSPH_h2;
cb.xSPH_h9 = cb.xSPH_h3 * cb.xSPH_h3;
cb.xSPH_K = SPH_K;
cb.xSPH_p0 = SPH_p0;
cb.xSPH_e = SPH_e;
device->UpdateBuffer(constantBuffer, &cb, threadID);
device->BindConstantBuffer(CS, constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), threadID);
@@ -343,10 +358,13 @@ void wiEmittedParticle::UpdateRenderData(GRAPHICSTHREAD threadID)
device->DispatchIndirect(indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHEMIT, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
// perform N-body collision response simulation:
device->BindComputePSO(&CPSO_nbody, threadID);
device->DispatchIndirect(indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
if (SPH_FLUIDSIMULATION)
{
// perform N-body collision response simulation:
device->BindComputePSO(&CPSO_nbody, threadID);
device->DispatchIndirect(indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
}
// update CURRENT alive list, write NEW alive list
if (SORTING)
+8
View File
@@ -69,6 +69,7 @@ public:
void Update(float dt);
void Burst(float num);
void Restart();
void UpdateRenderData(GRAPHICSTHREAD threadID);
@@ -80,6 +81,7 @@ public:
bool SORTING = false;
bool DEPTHCOLLISIONS = false;
bool SPH_FLUIDSIMULATION = false;
PARTICLESHADERTYPE shaderType = SOFT;
@@ -92,6 +94,12 @@ public:
float count,life,random_life;
float scaleX,scaleY,rotation;
float motionBlurAmount;
float mass = 1.0f;
float SPH_h = 0.2f; // smoothing radius
float SPH_K = 20.0f; // pressure constant
float SPH_p0 = 20.0f; // reference density
float SPH_e = 0.018f; // viscosity constant
void SetMaxParticleCount(uint32_t value);
uint32_t GetMaxParticleCount() const { return MAX_PARTICLES; }