Welcome to mirror list, hosted at ThFree Co, Russian Federation.

events.cpp « bparticles « simulations « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c66179cc6f1d2b994aa5007939bc5082c9b63cbd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "BLI_hash.h"
#include "BLI_utildefines.h"

#include "events.hpp"

namespace BParticles {

/* Age Reached Event
 ******************************************/

void AgeReachedEvent::filter(EventFilterInterface &interface)
{
  AttributesRef attributes = interface.attributes();

  ParticleFunctionEvaluator inputs{m_inputs_fn, interface.mask(), interface.attributes()};
  inputs.context_builder().set_buffer_cache(interface.buffer_cache());
  inputs.compute();

  float end_time = interface.step_end_time();
  auto birth_times = attributes.get<float>("Birth Time");
  auto was_activated_before = attributes.get<bool>(m_is_triggered_attribute);

  for (uint pindex : interface.mask()) {
    if (was_activated_before[pindex]) {
      continue;
    }

    float trigger_age = inputs.get_single<float>("Age", 0, pindex);
    float birth_time = birth_times[pindex];
    float age_at_end = end_time - birth_time;

    if (age_at_end >= trigger_age) {
      FloatInterval time_span = interface.time_span(pindex);

      float age_at_start = age_at_end - time_span.size();
      if (trigger_age < age_at_start) {
        interface.trigger_particle(pindex, 0.0f);
      }
      else {
        float time_factor = time_span.safe_factor_of(birth_time + trigger_age);
        CLAMP(time_factor, 0.0f, 1.0f);
        interface.trigger_particle(pindex, time_factor);
      }
    }
  }
}

void AgeReachedEvent::execute(EventExecuteInterface &interface)
{
  auto was_activated_before = interface.attributes().get<bool>(m_is_triggered_attribute);
  for (uint pindex : interface.pindices()) {
    was_activated_before[pindex] = true;
  }

  m_action.execute_from_event(interface);
}

/* Custom Event
 ***********************************************/

void CustomEvent::filter(EventFilterInterface &interface)
{
  FN::EventFilterEndTimeContext end_time_context = {interface.step_end_time()};
  FN::EventFilterDurationsContext durations_context = {interface.remaining_durations()};

  ParticleFunctionEvaluator inputs{m_inputs_fn, interface.mask(), interface.attributes()};
  FN::MFContextBuilder &context_builder = inputs.context_builder();
  context_builder.set_buffer_cache(interface.buffer_cache());
  context_builder.add_global_context(end_time_context);
  context_builder.add_element_context(durations_context,
                                      FN::MFElementContextIndices::FromDirectMapping());
  inputs.compute();

  for (uint pindex : interface.mask()) {
    bool condition = inputs.get_single<bool>("Condition", 0, pindex);
    if (condition) {
      float time_factor = inputs.get_single<float>("Time Factor", 1, pindex);
      time_factor = std::min(std::max(time_factor, 0.0f), 1.0f);
      interface.trigger_particle(pindex, time_factor);
    }
  }
}

void CustomEvent::execute(EventExecuteInterface &interface)
{
  m_action.execute_from_event(interface);
}

/* Collision Event
 ***********************************************/

void MeshCollisionEvent::filter(EventFilterInterface &interface)
{
  AttributesRef attributes = interface.attributes();
  auto positions = attributes.get<float3>("Position");
  auto last_collision_step = attributes.get<int32_t>(m_last_collision_attribute);
  auto position_offsets = interface.attribute_offsets().get<float3>("Position");

  uint current_update_index = interface.simulation_state().time().current_update_index();

  for (uint pindex : interface.mask()) {
    if (last_collision_step[pindex] == current_update_index) {
      continue;
    }

    float3 world_ray_start = positions[pindex];
    float3 world_ray_direction = position_offsets[pindex];
    float3 world_ray_end = world_ray_start + world_ray_direction;

    float3 local_ray_start = m_world_to_local_begin.transform_position(world_ray_start);
    float3 local_ray_end = m_world_to_local_end.transform_position(world_ray_end);
    float3 local_ray_direction = local_ray_end - local_ray_start;
    float local_ray_length = local_ray_direction.normalize_and_get_length();

    auto result = this->ray_cast(local_ray_start, local_ray_direction, local_ray_length);
    if (result.success) {
      float time_factor = result.distance / local_ray_length;
      interface.trigger_particle(pindex, time_factor);
      if (float3::dot(result.normal, local_ray_direction) > 0) {
        result.normal = -result.normal;
      }
    }
  }
}

MeshCollisionEvent::RayCastResult MeshCollisionEvent::ray_cast(float3 start,
                                                               float3 normalized_direction,
                                                               float max_distance)
{
  BVHTreeRayHit hit;
  hit.dist = max_distance;
  hit.index = -1;
  BLI_bvhtree_ray_cast(m_bvhtree_data.tree,
                       start,
                       normalized_direction,
                       0.0f,
                       &hit,
                       m_bvhtree_data.raycast_callback,
                       (void *)&m_bvhtree_data);

  return {hit.index >= 0, hit.index, float3(hit.no), hit.dist};
}

void MeshCollisionEvent::execute(EventExecuteInterface &interface)
{
  auto last_collision_step = interface.attributes().get<int32_t>(m_last_collision_attribute);
  uint current_update_index = interface.simulation_state().time().current_update_index();

  for (uint pindex : interface.pindices()) {
    last_collision_step[pindex] = current_update_index;
  }
  m_action.execute_from_event(interface);
}

}  // namespace BParticles