Particles: initial support for the Time input node
This commit is contained in:
parent
c8e45c3fe9
commit
3b9e16a4f7
|
@ -487,7 +487,7 @@ simulation_node_categories = [
|
|||
NodeItem("SimulationNodeParticleSimulation"),
|
||||
]),
|
||||
SimulationNodeCategory("SIM_INPUTS", "Input", items=[
|
||||
not_implemented_node("SimulationNodeTime"),
|
||||
NodeItem("SimulationNodeTime"),
|
||||
NodeItem("SimulationNodeParticleAttribute"),
|
||||
NodeItem("FunctionNodeGroupInstanceID"),
|
||||
NodeItem("ShaderNodeValue"),
|
||||
|
|
|
@ -79,6 +79,12 @@ class ResourceCollector : NonCopyable, NonMovable {
|
|||
*/
|
||||
template<typename T> void add(destruct_ptr<T> resource, const char *name)
|
||||
{
|
||||
/* There is no need to keep track of such types. */
|
||||
if (std::is_trivially_destructible_v<T>) {
|
||||
resource.release();
|
||||
return;
|
||||
}
|
||||
|
||||
BLI_assert(resource.get() != nullptr);
|
||||
this->add(
|
||||
resource.release(),
|
||||
|
|
|
@ -116,8 +116,9 @@ void ParticleFunctionEvaluator::compute_globals()
|
|||
fn::MFParamsBuilder params(*particle_fn_.global_fn_, mask_.min_array_size());
|
||||
|
||||
/* Add input parameters. */
|
||||
ParticleFunctionInputContext input_context{solve_context_, particles_};
|
||||
for (const ParticleFunctionInput *input : particle_fn_.global_inputs_) {
|
||||
input->add_input(particles_.attributes, params, resources_);
|
||||
input->add_input(input_context, params, resources_);
|
||||
}
|
||||
|
||||
/* Add output parameters. */
|
||||
|
@ -143,8 +144,9 @@ void ParticleFunctionEvaluator::compute_per_particle()
|
|||
fn::MFParamsBuilder params(*particle_fn_.per_particle_fn_, mask_.min_array_size());
|
||||
|
||||
/* Add input parameters. */
|
||||
ParticleFunctionInputContext input_context{solve_context_, particles_};
|
||||
for (const ParticleFunctionInput *input : particle_fn_.per_particle_inputs_) {
|
||||
input->add_input(particles_.attributes, params, resources_);
|
||||
input->add_input(input_context, params, resources_);
|
||||
}
|
||||
|
||||
/* Add output parameters. */
|
||||
|
|
|
@ -26,10 +26,15 @@
|
|||
|
||||
namespace blender::sim {
|
||||
|
||||
struct ParticleFunctionInputContext {
|
||||
const SimulationSolveContext &solve_context;
|
||||
const ParticleChunkContext &particles;
|
||||
};
|
||||
|
||||
class ParticleFunctionInput {
|
||||
public:
|
||||
virtual ~ParticleFunctionInput() = default;
|
||||
virtual void add_input(fn::AttributesRef attributes,
|
||||
virtual void add_input(ParticleFunctionInputContext &context,
|
||||
fn::MFParamsBuilder ¶ms,
|
||||
ResourceCollector &resources) const = 0;
|
||||
};
|
||||
|
|
|
@ -28,12 +28,15 @@
|
|||
|
||||
#include "BLI_hash.h"
|
||||
#include "BLI_rand.hh"
|
||||
#include "BLI_set.hh"
|
||||
|
||||
namespace blender::sim {
|
||||
|
||||
using fn::GVSpan;
|
||||
using fn::MFContextBuilder;
|
||||
using fn::MFDataType;
|
||||
using fn::MFDummyNode;
|
||||
using fn::MFFunctionNode;
|
||||
using fn::MFInputSocket;
|
||||
using fn::MFNetwork;
|
||||
using fn::MFNetworkEvaluator;
|
||||
|
@ -53,6 +56,8 @@ using nodes::NodeTreeRefMap;
|
|||
|
||||
struct DummyDataSources {
|
||||
Map<const MFOutputSocket *, std::string> particle_attributes;
|
||||
Set<const MFOutputSocket *> simulation_time;
|
||||
Set<const MFOutputSocket *> scene_time;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
@ -226,6 +231,47 @@ static void prepare_particle_attribute_nodes(CollectContext &context)
|
|||
}
|
||||
}
|
||||
|
||||
static void prepare_time_input_nodes(CollectContext &context)
|
||||
{
|
||||
Span<const DNode *> time_input_dnodes = nodes_by_type(context, "SimulationNodeTime");
|
||||
Vector<const DNode *> simulation_time_inputs;
|
||||
Vector<const DNode *> scene_time_inputs;
|
||||
for (const DNode *dnode : time_input_dnodes) {
|
||||
NodeSimInputTimeType type = (NodeSimInputTimeType)dnode->node_ref().bnode()->custom1;
|
||||
switch (type) {
|
||||
case NODE_SIM_INPUT_SIMULATION_TIME: {
|
||||
simulation_time_inputs.append(dnode);
|
||||
break;
|
||||
}
|
||||
case NODE_SIM_INPUT_SCENE_TIME: {
|
||||
scene_time_inputs.append(dnode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (simulation_time_inputs.size() > 0) {
|
||||
MFOutputSocket &new_socket = context.network.add_input("Simulation Time",
|
||||
MFDataType::ForSingle<float>());
|
||||
for (const DNode *dnode : simulation_time_inputs) {
|
||||
MFOutputSocket &old_socket = context.network_map.lookup_dummy(dnode->output(0));
|
||||
context.network.relink(old_socket, new_socket);
|
||||
context.network.remove(old_socket.node());
|
||||
}
|
||||
context.data_sources.simulation_time.add(&new_socket);
|
||||
}
|
||||
if (scene_time_inputs.size() > 0) {
|
||||
MFOutputSocket &new_socket = context.network.add_input("Scene Time",
|
||||
MFDataType::ForSingle<float>());
|
||||
for (const DNode *dnode : scene_time_inputs) {
|
||||
MFOutputSocket &old_socket = context.network_map.lookup_dummy(dnode->output(0));
|
||||
context.network.relink(old_socket, new_socket);
|
||||
context.network.remove(old_socket.node());
|
||||
}
|
||||
context.data_sources.scene_time.add(&new_socket);
|
||||
}
|
||||
}
|
||||
|
||||
class ParticleAttributeInput : public ParticleFunctionInput {
|
||||
private:
|
||||
std::string attribute_name_;
|
||||
|
@ -237,11 +283,12 @@ class ParticleAttributeInput : public ParticleFunctionInput {
|
|||
{
|
||||
}
|
||||
|
||||
void add_input(AttributesRef attributes,
|
||||
void add_input(ParticleFunctionInputContext &context,
|
||||
MFParamsBuilder ¶ms,
|
||||
ResourceCollector &UNUSED(resources)) const override
|
||||
{
|
||||
std::optional<GSpan> span = attributes.try_get(attribute_name_, attribute_type_);
|
||||
std::optional<GSpan> span = context.particles.attributes.try_get(attribute_name_,
|
||||
attribute_type_);
|
||||
if (span.has_value()) {
|
||||
params.add_readonly_single_input(*span);
|
||||
}
|
||||
|
@ -251,6 +298,29 @@ class ParticleAttributeInput : public ParticleFunctionInput {
|
|||
}
|
||||
};
|
||||
|
||||
class SceneTimeInput : public ParticleFunctionInput {
|
||||
void add_input(ParticleFunctionInputContext &context,
|
||||
MFParamsBuilder ¶ms,
|
||||
ResourceCollector &resources) const override
|
||||
{
|
||||
const float time = DEG_get_ctime(&context.solve_context.depsgraph);
|
||||
float *time_ptr = &resources.construct<float>(AT, time);
|
||||
params.add_readonly_single_input(time_ptr);
|
||||
}
|
||||
};
|
||||
|
||||
class SimulationTimeInput : public ParticleFunctionInput {
|
||||
void add_input(ParticleFunctionInputContext &context,
|
||||
MFParamsBuilder ¶ms,
|
||||
ResourceCollector &resources) const override
|
||||
{
|
||||
/* TODO: Vary this per particle. */
|
||||
const float time = context.solve_context.solve_interval.stop();
|
||||
float *time_ptr = &resources.construct<float>(AT, time);
|
||||
params.add_readonly_single_input(time_ptr);
|
||||
}
|
||||
};
|
||||
|
||||
static const ParticleFunction *create_particle_function_for_inputs(
|
||||
CollectContext &context, Span<const MFInputSocket *> sockets_to_compute)
|
||||
{
|
||||
|
@ -264,13 +334,21 @@ static const ParticleFunction *create_particle_function_for_inputs(
|
|||
|
||||
Vector<const ParticleFunctionInput *> per_particle_inputs;
|
||||
for (const MFOutputSocket *socket : dummy_deps) {
|
||||
const std::string *attribute_name = context.data_sources.particle_attributes.lookup_ptr(
|
||||
socket);
|
||||
if (attribute_name == nullptr) {
|
||||
return nullptr;
|
||||
if (context.data_sources.particle_attributes.contains(socket)) {
|
||||
const std::string *attribute_name = context.data_sources.particle_attributes.lookup_ptr(
|
||||
socket);
|
||||
if (attribute_name == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
per_particle_inputs.append(&context.resources.construct<ParticleAttributeInput>(
|
||||
AT, *attribute_name, socket->data_type().single_type()));
|
||||
}
|
||||
else if (context.data_sources.scene_time.contains(socket)) {
|
||||
per_particle_inputs.append(&context.resources.construct<SceneTimeInput>(AT));
|
||||
}
|
||||
else if (context.data_sources.simulation_time.contains(socket)) {
|
||||
per_particle_inputs.append(&context.resources.construct<SimulationTimeInput>(AT));
|
||||
}
|
||||
per_particle_inputs.append(&context.resources.construct<ParticleAttributeInput>(
|
||||
AT, *attribute_name, socket->data_type().single_type()));
|
||||
}
|
||||
|
||||
const MultiFunction &per_particle_fn = context.resources.construct<MFNetworkEvaluator>(
|
||||
|
@ -689,6 +767,7 @@ void collect_simulation_influences(Simulation &simulation,
|
|||
initialize_particle_attribute_builders(context);
|
||||
|
||||
prepare_particle_attribute_nodes(context);
|
||||
prepare_time_input_nodes(context);
|
||||
|
||||
collect_forces(context);
|
||||
collect_emitters(context);
|
||||
|
|
Loading…
Reference in New Issue