Add safety checks for particles data to prevent division by 0

This commit is contained in:
Wojtek Figat
2021-02-06 15:58:12 +01:00
parent d27edbf5a9
commit 25f35b22be
3 changed files with 23 additions and 23 deletions

View File

@@ -69,7 +69,7 @@ namespace
scale *= 1.72531f;
}
return noise / weight;
return noise / Math::Max(weight, ZeroTolerance);
}
VariantType::Types GetVariantType(ParticleAttribute::ValueTypes type)
@@ -486,7 +486,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
float particleDrag = drag; \
if (useSpriteSize) \
particleDrag *= ((Vector2*)spriteSizePtr)->MulValues(); \
*((Vector3*)velocityPtr) *= Math::Max(0.0f, 1.0f - (particleDrag * _deltaTime) / *(float*)massPtr); \
*((Vector3*)velocityPtr) *= Math::Max(0.0f, 1.0f - (particleDrag * _deltaTime) / Math::Max(*(float*)massPtr, ZeroTolerance)); \
velocityPtr += stride; \
massPtr += stride; \
spriteSizePtr += stride
@@ -545,7 +545,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
Vector3 vectorFieldUVW = Vector3::Transform(*((Vector3*)positionPtr), invFieldTransformMatrix); \
Vector3 force = Noise3D(vectorFieldUVW + 0.5f, octavesCount, roughness); \
force = Vector3::Transform(force, fieldTransformMatrix) * intensity; \
*((Vector3*)velocityPtr) += force * (_deltaTime / *(float*)massPtr); \
*((Vector3*)velocityPtr) += force * (_deltaTime / Math::Max(*(float*)massPtr, ZeroTolerance)); \
positionPtr += stride; \
velocityPtr += stride; \
massPtr += stride
@@ -1009,7 +1009,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
#define INPUTS_FETCH() \
const Vector3 center = (Vector3)GetValue(centerBox, 2); \
const float radius = (float)GetValue(radiusBox, 3); \
const float radius = Math::Max((float)GetValue(radiusBox, 3), ZeroTolerance); \
const float thickness = (float)GetValue(thicknessBox, 4); \
const float arc = (float)GetValue(arcBox, 5) * DegreesToRadians
#define LOGIC() \
@@ -1017,20 +1017,20 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
float sinTheta, cosTheta; \
Math::SinCos(u.X * TWO_PI, sinTheta, cosTheta); \
float r = Math::Saturate(thickness / radius); \
Vector2 s1_1 = r * Vector2(cosTheta, sinTheta) + Vector2(1, 0); \
Vector2 s1_2 = r * Vector2(-cosTheta, sinTheta) + Vector2(1, 0); \
float w = s1_1.X / (s1_1.X + s1_2.X); \
Vector2 s11 = r * Vector2(cosTheta, sinTheta) + Vector2(1, 0); \
Vector2 s12 = r * Vector2(-cosTheta, sinTheta) + Vector2(1, 0); \
float w = s11.X / (s11.X + s12.X); \
Vector3 t; \
float phi; \
if (u.Y < w) \
{ \
phi = arc * u.Y / w; \
t = Vector3(s1_1.X, 0, s1_1.Y); \
t = Vector3(s11.X, 0, s11.Y); \
} \
else \
{ \
phi = arc * (u.Y - w) / (1.0f - w); \
t = Vector3(s1_2.X, 0, s1_2.Y); \
t = Vector3(s12.X, 0, s12.Y); \
} \
float s, c; \
Math::SinCos(phi, c, s); \
@@ -1262,7 +1262,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
if (sign * sqrLength <= sign * totalRadius * totalRadius) \
{ \
float dist = Math::Sqrt(sqrLength); \
Vector3 n = sign * dir / dist; \
Vector3 n = sign * dir / Math::Max(dist, ZeroTolerance); \
*(Vector3*)positionPtr = position - n * (dist - totalRadius) * sign; \
COLLISION_LOGIC()
@@ -1374,7 +1374,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
collision = Math::Abs(dir.Y) > halfHeight || sqrLength > cylinderRadiusT * cylinderRadiusT; \
if (collision) \
{ \
float dist = Math::Sqrt(sqrLength); \
float dist = Math::Max(Math::Sqrt(sqrLength), ZeroTolerance); \
float distToCap = sign * (halfHeight - Math::Abs(dir.Y)); \
float distToSide = sign * (cylinderRadiusT - dist); \
Vector3 n = Vector3(dir.X / dist, Math::Sign(dir.Y), dir.Z / dist) * sign; \

View File

@@ -284,7 +284,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessGroupParticles(Box* box, Node* node
{
const float age = GET_PARTICLE_ATTRIBUTE(0, float);
const float lifetime = GET_PARTICLE_ATTRIBUTE(1, float);
value = age / lifetime;
value = age / Math::Max(lifetime, ZeroTolerance);
break;
}
// Effect Position

View File

@@ -177,7 +177,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
" {{\n"
" // Linear Drag\n"
" float drag = {2} * {3}.x * {3}.y;\n"
" {0} *= max(0.0f, 1.0f - (drag * DeltaTime) / {1});\n"
" {0} *= max(0.0f, 1.0f - (drag * DeltaTime) / max({1}, PARTICLE_THRESHOLD));\n"
" }}\n"
), velocity.Value, mass.Value, drag.Value, spriteSize.Value);
}
@@ -188,7 +188,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
" {{\n"
" // Linear Drag\n"
" float drag = {2};\n"
" {0} *= max(0.0f, 1.0f - (drag * DeltaTime) / {1});\n"
" {0} *= max(0.0f, 1.0f - (drag * DeltaTime) / max({1}, PARTICLE_THRESHOLD));\n"
" }}\n"
), velocity.Value, mass.Value, drag.Value);
}
@@ -219,7 +219,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
" float3 vectorFieldUVW = mul(invFieldTransformMatrix, float4({0}, 1.0f)).xyz;\n"
" float3 force = Noise3D(vectorFieldUVW + 0.5f, {8}, {6});\n"
" force = mul(fieldTransformMatrix, float4(force, 0.0f)).xyz * {7};\n"
" {1} += force * (DeltaTime / {2});\n"
" {1} += force * (DeltaTime / max({2}, PARTICLE_THRESHOLD));\n"
" }}\n"
), position.Value, velocity.Value, mass.Value, fieldPosition.Value, fieldRotation.Value, fieldScale.Value, roughness.Value, intensity.Value, octavesCount.Value);
break;
@@ -486,21 +486,21 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
" float3 u = RAND3;\n"
" float sinTheta, cosTheta;\n"
" sincos(u.x * PI * 2.0f, sinTheta, cosTheta);\n"
" float r = saturate((float){4} / {3});\n"
" float2 s1_1 = r * float2( cosTheta, sinTheta) + float2(1, 0);\n"
" float2 s1_2 = r * float2(-cosTheta, sinTheta) + float2(1, 0);\n"
" float w = s1_1.x / (s1_1.x + s1_2.x);\n"
" float r = saturate((float){4} / max({3}, PARTICLE_THRESHOLD));\n"
" float2 s11 = r * float2( cosTheta, sinTheta) + float2(1, 0);\n"
" float2 s12 = r * float2(-cosTheta, sinTheta) + float2(1, 0);\n"
" float w = s11.x / (s11.x + s12.x);\n"
" float3 t;\n"
" float phi;\n"
" if (u.y < w)\n"
" {{\n"
" phi = radians({5}) * u.y / w;\n"
" t = float3(s1_1.x, 0, s1_1.y);\n"
" t = float3(s11.x, 0, s11.y);\n"
" }}\n"
" else\n"
" {{\n"
" phi = radians({5}) * (u.y - w) / (1.0f - w);\n"
" t = float3(s1_2.x, 0, s1_2.y);\n"
" t = float3(s12.x, 0, s12.y);\n"
" }}\n"
" float s, c;\n"
" sincos(phi, c, s);\n"
@@ -693,7 +693,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
" if ({4} * sqrLength <= {4} * totalRadius * totalRadius)\n"
" {{\n"
" float dist = sqrt(sqrLength);\n"
" float3 n = {4} * dir / dist;\n"
" float3 n = {4} * dir / max(dist, PARTICLE_THRESHOLD);\n"
" {0} -= n * (dist - totalRadius) * {4};\n"
COLLISION_LOGIC()
" }}\n"
@@ -787,7 +787,7 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
" collision = abs(dir.y) > halfHeight || sqrLength > cylinderRadiusT * cylinderRadiusT;\n"
" if (collision)\n"
" {{\n"
" float dist = sqrt(sqrLength);\n"
" float dist = max(sqrt(sqrLength), PARTICLE_THRESHOLD);\n"
" float distToCap = {4} * (halfHeight - abs(dir.y));\n"
" float distToSide = {4} * (cylinderRadiusT - dist);\n"
" float3 n = float3(dir.x / dist, sign(dir.y), dir.z / dist) * {4};\n"