added emitter - sph properties
This commit is contained in:
+129
-2
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user