Fix missing particle layout attributes when using Particle Emitter Function

#1640
This commit is contained in:
Wojtek Figat
2023-10-12 17:39:42 +02:00
parent bd4127676b
commit 8af2f458d7
3 changed files with 29 additions and 11 deletions

View File

@@ -37,12 +37,12 @@ public:
/// <summary> /// <summary>
/// Flag valid for used particle nodes that need per-particle data to evaluate its value (including dependant nodes linked to input boxes). Used to skip per-particle graph evaluation if graph uses the same value for all particles (eg. is not using per-particle seed or position node). /// Flag valid for used particle nodes that need per-particle data to evaluate its value (including dependant nodes linked to input boxes). Used to skip per-particle graph evaluation if graph uses the same value for all particles (eg. is not using per-particle seed or position node).
/// </summary> /// </summary>
bool UsesParticleData; bool UsesParticleData = false;
/// <summary> /// <summary>
/// Flag valid for used particle nodes that result in constant data (nothing random nor particle data). /// Flag valid for used particle nodes that result in constant data (nothing random nor particle data).
/// </summary> /// </summary>
bool IsConstant; bool IsConstant = true;
/// <summary> /// <summary>
/// The cached particle attribute indices used by the simulation graph to access particle properties. /// The cached particle attribute indices used by the simulation graph to access particle properties.
@@ -50,6 +50,8 @@ public:
int32 Attributes[PARTICLE_EMITTER_MAX_ATTRIBUTES_REFS_PER_NODE]; int32 Attributes[PARTICLE_EMITTER_MAX_ATTRIBUTES_REFS_PER_NODE];
}; };
void InitParticleEmitterFunctionCall(const Guid& assetId, AssetReference<Asset>& asset, bool& usesParticleData, ParticleLayout& layout);
/// <summary> /// <summary>
/// The Particle Emitter Graph used to simulate particles. /// The Particle Emitter Graph used to simulate particles.
/// </summary> /// </summary>
@@ -157,8 +159,6 @@ public:
if (node->Used) if (node->Used)
return; return;
node->Used = true; node->Used = true;
node->UsesParticleData = false;
node->IsConstant = true;
#define USE_ATTRIBUTE(name, valueType, slot) \ #define USE_ATTRIBUTE(name, valueType, slot) \
{ \ { \
@@ -292,14 +292,11 @@ public:
case GRAPH_NODE_MAKE_TYPE(14, 214): case GRAPH_NODE_MAKE_TYPE(14, 214):
case GRAPH_NODE_MAKE_TYPE(14, 215): case GRAPH_NODE_MAKE_TYPE(14, 215):
case GRAPH_NODE_MAKE_TYPE(14, 216): case GRAPH_NODE_MAKE_TYPE(14, 216):
{
node->IsConstant = false; node->IsConstant = false;
break; break;
}
// Particle Emitter Function // Particle Emitter Function
case GRAPH_NODE_MAKE_TYPE(14, 300): case GRAPH_NODE_MAKE_TYPE(14, 300):
node->Assets[0] = Content::LoadAsync<Asset>((Guid)node->Values[0]); InitParticleEmitterFunctionCall((Guid)node->Values[0], node->Assets[0], node->UsesParticleData, Layout);
node->UsesParticleData = true; // TODO: analyze emitter function graph to detect if it's actually using any particle data at all (even from inputs after inline)
break; break;
// Particle Index // Particle Index
case GRAPH_NODE_MAKE_TYPE(14, 301): case GRAPH_NODE_MAKE_TYPE(14, 301):
@@ -564,7 +561,7 @@ public:
return true; return true;
// Compute particle data layout and initialize used nodes (for only used nodes, start depth searching rom the modules) // Compute particle data layout and initialize used nodes (for only used nodes, start depth searching rom the modules)
Layout.AddAttribute(TEXT("Position"), ParticleAttribute::ValueTypes::Float3); //Layout.AddAttribute(TEXT("Position"), ParticleAttribute::ValueTypes::Float3);
#define PROCESS_MODULES(modules) for (int32 i = 0; i < modules.Count(); i++) { modules[i]->Used = false; InitializeNode(modules[i]); } #define PROCESS_MODULES(modules) for (int32 i = 0; i < modules.Count(); i++) { modules[i]->Used = false; InitializeNode(modules[i]); }
PROCESS_MODULES(SpawnModules); PROCESS_MODULES(SpawnModules);
PROCESS_MODULES(InitModules); PROCESS_MODULES(InitModules);

View File

@@ -9,6 +9,27 @@
#endif #endif
#include "Engine/Content/Factories/BinaryAssetFactory.h" #include "Engine/Content/Factories/BinaryAssetFactory.h"
void InitParticleEmitterFunctionCall(const Guid& assetId, AssetReference<Asset>& asset, bool& usesParticleData, ParticleLayout& layout)
{
const auto function = Content::Load<ParticleEmitterFunction>(assetId);
asset = function;
if (function)
{
// Insert any used particle data into the calling graph
for (const ParticleAttribute& e : function->Graph.Layout.Attributes)
{
if (layout.FindAttribute(e.Name, e.ValueType) == -1)
layout.AddAttribute(e.Name, e.ValueType);
}
// Detect if function needs to be evaluated per-particle
for (int32 i = 0; i < function->Outputs.Count() && !usesParticleData; i++)
{
usesParticleData = function->Graph.Nodes[function->Outputs.Get()[i]].UsesParticleData;
}
}
}
REGISTER_BINARY_ASSET(ParticleEmitterFunction, "FlaxEngine.ParticleEmitterFunction", false); REGISTER_BINARY_ASSET(ParticleEmitterFunction, "FlaxEngine.ParticleEmitterFunction", false);
ParticleEmitterFunction::ParticleEmitterFunction(const SpawnParams& params, const AssetInfo* info) ParticleEmitterFunction::ParticleEmitterFunction(const SpawnParams& params, const AssetInfo* info)

View File

@@ -262,11 +262,11 @@ protected:
FORCE_INLINE Value tryGetValue(Box* box) FORCE_INLINE Value tryGetValue(Box* box)
{ {
return box && box->HasConnection() ? eatBox(box->GetParent<Node>(), box->FirstConnection()) : Value::Zero; return box && box->Connections.HasItems() ? eatBox(box->GetParent<Node>(), (VisjectGraphBox*)box->Connections.Get()[0]) : Value::Zero;
} }
FORCE_INLINE Value tryGetValue(Box* box, const Value& defaultValue) FORCE_INLINE Value tryGetValue(Box* box, const Value& defaultValue)
{ {
return box && box->HasConnection() ? eatBox(box->GetParent<Node>(), box->FirstConnection()) : defaultValue; return box && box->Connections.HasItems() ? eatBox(box->GetParent<Node>(), (VisjectGraphBox*)box->Connections.Get()[0]) : defaultValue;
} }
}; };