Add Collision (Global SDF) particle module

This commit is contained in:
Wojciech Figat
2022-03-28 13:39:20 +02:00
parent bcc4a2c0a4
commit 3a9edabd03
7 changed files with 106 additions and 47 deletions

BIN
Content/Editor/Primitives/Sphere.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -1357,7 +1357,7 @@ namespace FlaxEditor.Surface.Archetypes
true,
(int)ModuleType.Update,
false, // Invert
0.0f, // Radius
5.0f, // Radius
0.0f, // Roughness
0.1f, // Elasticity
0.0f, // Friction
@@ -1400,6 +1400,34 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Input(-0.5f + 3.0f, "Stick Force", true, typeof(float), 3, 5),
},
},
new NodeArchetype
{
TypeID = 336,
Create = CreateParticleModuleNode,
Title = "Collision (Global SDF)",
Description = "Collides particles with the scene Global SDF",
Flags = DefaultModuleFlags,
Size = new Vector2(200, 5 * Surface.Constants.LayoutOffsetY),
DefaultValues = new object[]
{
true,
(int)ModuleType.Update,
false, // Invert
5.0f, // Radius
0.4f, // Roughness
0.1f, // Elasticity
0.0f, // Friction
0.0f, // Lifetime Loss
},
Elements = new[]
{
NodeElementArchetype.Factory.Input(-0.5f + 0, "Radius", true, typeof(float), 0, 3),
NodeElementArchetype.Factory.Input(-0.5f + 1, "Roughness", true, typeof(float), 1, 4),
NodeElementArchetype.Factory.Input(-0.5f + 2, "Elasticity", true, typeof(float), 2, 5),
NodeElementArchetype.Factory.Input(-0.5f + 3, "Friction", true, typeof(float), 3, 6),
NodeElementArchetype.Factory.Input(-0.5f + 4, "Lifetime Loss", true, typeof(float), 4, 7),
},
},
GetParticleAttribute(ModuleType.Update, 350, "Set Position", "Sets the particle position", typeof(Vector3), Vector3.Zero),
GetParticleAttribute(ModuleType.Update, 351, "Set Lifetime", "Sets the particle lifetime (in seconds)", typeof(float), 10.0f),
GetParticleAttribute(ModuleType.Update, 352, "Set Age", "Sets the particle age (in seconds)", typeof(float), 0.0f),

View File

@@ -1475,6 +1475,12 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
// Not supported
break;
}
// Collision (Global SDF)
case 336:
{
// Not supported
break;
}
#undef COLLISION_BEGIN
#undef COLLISION_INPUTS_FETCH

View File

@@ -616,7 +616,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
auto position = AccessParticleAttribute(node, nodeGpu->Attributes[0], AccessMode::ReadWrite);
auto param = findOrAddGlobalSDF();
String wsPos = position.Value;
if (((ParticleEmitterGraphGPU*)_graphStack.Peek())->SimulationSpace == ParticlesSimulationSpace::Local)
if (IsLocalSimulationSpace())
wsPos = String::Format(TEXT("mul(float4({0}, 1), WorldMatrix).xyz"), wsPos);
_includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl"));
_writer.Write(
@@ -666,13 +666,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
case 330:
{
COLLISION_BEGIN();
auto planePositionBox = node->GetBox(5);
auto planeNormalBox = node->GetBox(6);
const Value planePosition = GetValue(planePositionBox, 8).AsVector3();
const Value planeNormal = GetValue(planeNormalBox, 9).AsVector3();
const Value planePosition = GetValue(node->GetBox(5), 8).AsVector3();
const Value planeNormal = GetValue(node->GetBox(6), 9).AsVector3();
_writer.Write(
TEXT(
" {{\n"
@@ -699,13 +694,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
case 331:
{
COLLISION_BEGIN();
auto spherePositionBox = node->GetBox(5);
auto sphereRadiusBox = node->GetBox(6);
const Value spherePosition = GetValue(spherePositionBox, 8).AsVector3();
const Value sphereRadius = GetValue(sphereRadiusBox, 9).AsFloat();
const Value spherePosition = GetValue(node->GetBox(5), 8).AsVector3();
const Value sphereRadius = GetValue(node->GetBox(6), 9).AsFloat();
_writer.Write(
TEXT(
" {{\n"
@@ -735,13 +725,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
case 332:
{
COLLISION_BEGIN();
auto boxPositionBox = node->GetBox(5);
auto boxSizeBox = node->GetBox(6);
const Value boxPosition = GetValue(boxPositionBox, 8).AsVector3();
const Value boxSize = GetValue(boxSizeBox, 9).AsVector3();
const Value boxPosition = GetValue(node->GetBox(5), 8).AsVector3();
const Value boxSize = GetValue(node->GetBox(6), 9).AsVector3();
_writer.Write(
TEXT(
" {{\n"
@@ -786,15 +771,9 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
case 333:
{
COLLISION_BEGIN();
auto cylinderPositionBox = node->GetBox(5);
auto cylinderHeightBox = node->GetBox(6);
auto cylinderRadiusBox = node->GetBox(7);
const Value cylinderPosition = GetValue(cylinderPositionBox, 8).AsVector3();
const Value cylinderHeight = GetValue(cylinderHeightBox, 9).AsFloat();
const Value cylinderRadius = GetValue(cylinderRadiusBox, 10).AsFloat();
const Value cylinderPosition = GetValue(node->GetBox(5), 8).AsVector3();
const Value cylinderHeight = GetValue(node->GetBox(6), 9).AsFloat();
const Value cylinderRadius = GetValue(node->GetBox(7), 10).AsFloat();
_writer.Write(
TEXT(
" {{\n"
@@ -842,13 +821,8 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
case 334:
{
COLLISION_BEGIN();
auto surfaceThicknessBox = node->GetBox(5);
const Value surfaceThickness = GetValue(surfaceThicknessBox, 8).AsFloat();
const Value surfaceThickness = GetValue(node->GetBox(5), 8).AsFloat();
const auto sceneDepthTexture = findOrAddSceneTexture(MaterialSceneTextures::SceneDepth);
_writer.Write(
TEXT(
" {{\n"
@@ -929,7 +903,51 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
" }}\n"
), position.Value, velocity.Value, mass.Value, param.ShaderName, attractionSpeed.Value, attractionForce.Value, stickDistance.Value, stickForce.Value);
break;
}
}
// Collision (Global SDF)
case 336:
{
COLLISION_BEGIN();
auto param = findOrAddGlobalSDF();
_includes.Add(TEXT("./Flax/GlobalSignDistanceField.hlsl"));
const Char* format = IsLocalSimulationSpace()
? TEXT(
" {{\n"
" // Collision (Global SDF)\n"
" float3 nextPos = {0} + {1} * DeltaTime;\n"
" nextPos = mul(float4(nextPos, 1), WorldMatrix).xyz;\n"
" float dist = SampleGlobalSDF({10}, {10}_Tex, nextPos);\n"
" if (dist < {5})\n"
" {{\n"
" {0} = mul(float4({0}, 1), WorldMatrix).xyz;\n"
" float3 n = normalize(SampleGlobalSDFGradient({10}, {10}_Tex, {0}, dist));\n"
" {0} += n * -dist;\n"
" {0} = mul(float4({0}, 1), InvWorldMatrix).xyz;\n"
COLLISION_LOGIC()
" }}\n"
)
: TEXT(
" {{\n"
" // Collision (Global SDF)\n"
" float3 nextPos = {0} + {1} * DeltaTime;\n"
" float dist = SampleGlobalSDF({10}, {10}_Tex, nextPos);\n"
" if (dist < {5})\n"
" {{\n"
" float3 n = normalize(SampleGlobalSDFGradient({10}, {10}_Tex, {0}, dist));\n"
" {0} += n * -dist;\n"
COLLISION_LOGIC()
" }}\n"
);
_writer.Write(format,
// 0-4
positionAttr.Value, velocityAttr.Value, ageAttr.Value, invert, sign,
// 5-9
radius.Value, roughness.Value, elasticity.Value, friction.Value, lifetimeLoss.Value,
// 10
param.ShaderName
);
break;
}
#undef COLLISION_BEGIN
#undef COLLISION_LOGIC

View File

@@ -427,14 +427,10 @@ void ParticleEmitterGPUGenerator::ProcessGroupParticles(Box* box, Node* node, Va
}
// Particle Position (world space)
case 212:
{
value = AccessParticleAttribute(node, TEXT("Position"), ParticleAttribute::ValueTypes::Vector3, AccessMode::Read);
if (((ParticleEmitterGraphGPU*)_graphStack.Peek())->SimulationSpace == ParticlesSimulationSpace::Local)
{
if (IsLocalSimulationSpace())
value = writeLocal(VariantType::Vector3, String::Format(TEXT("mul(float4({0}, 1), WorldMatrix).xyz"), value.Value), node);
}
break;
}
// Random Float Range
case 213:
{

View File

@@ -156,6 +156,16 @@ private:
{
return box->HasConnection() ? eatBox(box->GetParent<Node>(), box->FirstConnection()) : Value::Zero;
}
bool IsLocalSimulationSpace() const
{
return ((ParticleEmitterGraphGPU*)_graphStack.Peek())->SimulationSpace == ParticlesSimulationSpace::Local;
}
bool IsWorldSimulationSpace() const
{
return ((ParticleEmitterGraphGPU*)_graphStack.Peek())->SimulationSpace == ParticlesSimulationSpace::World;
}
};
#endif

View File

@@ -430,12 +430,13 @@ public:
USE_ATTRIBUTE(Position, Vector3, 0);
break;
}
// Collision (plane/sphere/box/cylinder/depth)
// Collision (plane/sphere/box/cylinder/depth/Global SDF)
case GRAPH_NODE_MAKE_TYPE(15, 330):
case GRAPH_NODE_MAKE_TYPE(15, 331):
case GRAPH_NODE_MAKE_TYPE(15, 332):
case GRAPH_NODE_MAKE_TYPE(15, 333):
case GRAPH_NODE_MAKE_TYPE(15, 334):
case GRAPH_NODE_MAKE_TYPE(15, 336):
{
USE_ATTRIBUTE(Position, Vector3, 0);
USE_ATTRIBUTE(Velocity, Vector3, 1);