Particle system is complete. Rejoice!
This commit is contained in:
parent
6075dfe511
commit
4286aef693
|
@ -105,23 +105,23 @@ public:
|
|||
}
|
||||
|
||||
static void get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2, Vector3 &c1, Vector3 &c2) {
|
||||
#if 0
|
||||
//do the function 'd' as defined by pb. I think is is dot product of some sort
|
||||
#if 1
|
||||
//do the function 'd' as defined by pb. I think is is dot product of some sort
|
||||
#define d_of(m, n, o, p) ((m.x - n.x) * (o.x - p.x) + (m.y - n.y) * (o.y - p.y) + (m.z - n.z) * (o.z - p.z))
|
||||
|
||||
//calculate the parametric position on the 2 curves, mua and mub
|
||||
real_t mua = ( d_of(p1,q1,q2,q1) * d_of(q2,q1,p2,p1) - d_of(p1,q1,p2,p1) * d_of(q2,q1,q2,q1) ) / ( d_of(p2,p1,p2,p1) * d_of(q2,q1,q2,q1) - d_of(q2,q1,p2,p1) * d_of(q2,q1,p2,p1) );
|
||||
real_t mub = ( d_of(p1,q1,q2,q1) + mua * d_of(q2,q1,p2,p1) ) / d_of(q2,q1,q2,q1);
|
||||
real_t mua = (d_of(p1, q1, q2, q1) * d_of(q2, q1, p2, p1) - d_of(p1, q1, p2, p1) * d_of(q2, q1, q2, q1)) / (d_of(p2, p1, p2, p1) * d_of(q2, q1, q2, q1) - d_of(q2, q1, p2, p1) * d_of(q2, q1, p2, p1));
|
||||
real_t mub = (d_of(p1, q1, q2, q1) + mua * d_of(q2, q1, p2, p1)) / d_of(q2, q1, q2, q1);
|
||||
|
||||
//clip the value between [0..1] constraining the solution to lie on the original curves
|
||||
if (mua < 0) mua = 0;
|
||||
if (mub < 0) mub = 0;
|
||||
if (mua > 1) mua = 1;
|
||||
if (mub > 1) mub = 1;
|
||||
c1 = p1.linear_interpolate(p2,mua);
|
||||
c2 = q1.linear_interpolate(q2,mub);
|
||||
#endif
|
||||
|
||||
c1 = p1.linear_interpolate(p2, mua);
|
||||
c2 = q1.linear_interpolate(q2, mub);
|
||||
#else
|
||||
//this is broken do not use
|
||||
Vector3 u = p2 - p1;
|
||||
Vector3 v = q2 - q1;
|
||||
Vector3 w = p1 - q1;
|
||||
|
@ -144,8 +144,9 @@ public:
|
|||
|
||||
c1 = w + sc * u;
|
||||
c2 = w + tc * v;
|
||||
// get the difference of the two closest points
|
||||
//Vector dP = w + (sc * u) - (tc * v); // = L1(sc) - L2(tc)
|
||||
// get the difference of the two closest points
|
||||
//Vector dP = w + (sc * u) - (tc * v); // = L1(sc) - L2(tc)
|
||||
#endif
|
||||
}
|
||||
|
||||
static real_t get_closest_distance_between_segments(const Vector3 &p_from_a, const Vector3 &p_to_a, const Vector3 &p_from_b, const Vector3 &p_to_b) {
|
||||
|
|
|
@ -1216,7 +1216,26 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
|
|||
return rebind;
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) {
|
||||
struct RasterizerGLES3Particle {
|
||||
|
||||
float color[4];
|
||||
float velocity_active[4];
|
||||
float custom[4];
|
||||
float xform_1[4];
|
||||
float xform_2[4];
|
||||
float xform_3[4];
|
||||
};
|
||||
|
||||
struct RasterizerGLES3ParticleSort {
|
||||
|
||||
Vector3 z_dir;
|
||||
bool operator()(const RasterizerGLES3Particle &p_a, const RasterizerGLES3Particle &p_b) const {
|
||||
|
||||
return z_dir.dot(Vector3(p_a.xform_1[3], p_a.xform_2[3], p_a.xform_3[3])) < z_dir.dot(Vector3(p_b.xform_1[3], p_b.xform_2[3], p_b.xform_3[3]));
|
||||
}
|
||||
};
|
||||
|
||||
void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transform &p_view_transform) {
|
||||
|
||||
switch (e->instance->base_type) {
|
||||
|
||||
|
@ -1289,28 +1308,54 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) {
|
|||
RasterizerStorageGLES3::Particles *particles = static_cast<RasterizerStorageGLES3::Particles *>(e->owner);
|
||||
RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry);
|
||||
|
||||
glBindVertexArray(s->instancing_array_id); // use the instancing array ID
|
||||
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //modify the buffer
|
||||
if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->particle_valid_histories[1]) {
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer, this was used 2 frames ago so it should be good enough for flushing
|
||||
RasterizerGLES3Particle *particle_array = (RasterizerGLES3Particle *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
|
||||
|
||||
SortArray<RasterizerGLES3Particle, RasterizerGLES3ParticleSort> sorter;
|
||||
|
||||
if (particles->use_local_coords) {
|
||||
sorter.compare.z_dir = e->instance->transform.affine_inverse().xform(p_view_transform.basis.get_axis(2)).normalized();
|
||||
} else {
|
||||
sorter.compare.z_dir = p_view_transform.basis.get_axis(2).normalized();
|
||||
}
|
||||
|
||||
sorter.sort(particle_array, particles->amount);
|
||||
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
|
||||
glBindVertexArray(s->instancing_array_id); // use the instancing array ID
|
||||
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer
|
||||
|
||||
} else {
|
||||
|
||||
glBindVertexArray(s->instancing_array_id); // use the instancing array ID
|
||||
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //modify the buffer
|
||||
}
|
||||
|
||||
int stride = sizeof(float) * 4 * 6;
|
||||
|
||||
//transform
|
||||
|
||||
glEnableVertexAttribArray(8); //xform x
|
||||
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3);
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9); //xform y
|
||||
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4);
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(10); //xform z
|
||||
glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5);
|
||||
glVertexAttribDivisor(10, 1);
|
||||
glEnableVertexAttribArray(11); //color
|
||||
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0);
|
||||
glVertexAttribDivisor(11, 1);
|
||||
glEnableVertexAttribArray(12); //custom
|
||||
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2);
|
||||
glVertexAttribDivisor(12, 1);
|
||||
if (particles->draw_order != VS::PARTICLES_DRAW_ORDER_LIFETIME) {
|
||||
|
||||
glEnableVertexAttribArray(8); //xform x
|
||||
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3);
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9); //xform y
|
||||
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4);
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(10); //xform z
|
||||
glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5);
|
||||
glVertexAttribDivisor(10, 1);
|
||||
glEnableVertexAttribArray(11); //color
|
||||
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0);
|
||||
glVertexAttribDivisor(11, 1);
|
||||
glEnableVertexAttribArray(12); //custom
|
||||
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2);
|
||||
glVertexAttribDivisor(12, 1);
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
|
@ -1491,17 +1536,88 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
|
|||
|
||||
int amount = particles->amount;
|
||||
|
||||
if (s->index_array_len > 0) {
|
||||
if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_LIFETIME) {
|
||||
//split
|
||||
|
||||
glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount);
|
||||
int stride = sizeof(float) * 4 * 6;
|
||||
int split = int(Math::ceil(particles->phase * particles->amount));
|
||||
|
||||
storage->info.render_vertices_count += s->index_array_len * amount;
|
||||
if (amount - split > 0) {
|
||||
glEnableVertexAttribArray(8); //xform x
|
||||
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 3);
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9); //xform y
|
||||
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 4);
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(10); //xform z
|
||||
glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 5);
|
||||
glVertexAttribDivisor(10, 1);
|
||||
glEnableVertexAttribArray(11); //color
|
||||
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + 0);
|
||||
glVertexAttribDivisor(11, 1);
|
||||
glEnableVertexAttribArray(12); //custom
|
||||
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + stride * split + sizeof(float) * 4 * 2);
|
||||
glVertexAttribDivisor(12, 1);
|
||||
|
||||
if (s->index_array_len > 0) {
|
||||
|
||||
glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount - split);
|
||||
|
||||
storage->info.render_vertices_count += s->index_array_len * (amount - split);
|
||||
|
||||
} else {
|
||||
|
||||
glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount - split);
|
||||
|
||||
storage->info.render_vertices_count += s->array_len * (amount - split);
|
||||
}
|
||||
}
|
||||
|
||||
if (split > 0) {
|
||||
glEnableVertexAttribArray(8); //xform x
|
||||
glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3);
|
||||
glVertexAttribDivisor(8, 1);
|
||||
glEnableVertexAttribArray(9); //xform y
|
||||
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4);
|
||||
glVertexAttribDivisor(9, 1);
|
||||
glEnableVertexAttribArray(10); //xform z
|
||||
glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5);
|
||||
glVertexAttribDivisor(10, 1);
|
||||
glEnableVertexAttribArray(11); //color
|
||||
glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0);
|
||||
glVertexAttribDivisor(11, 1);
|
||||
glEnableVertexAttribArray(12); //custom
|
||||
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2);
|
||||
glVertexAttribDivisor(12, 1);
|
||||
|
||||
if (s->index_array_len > 0) {
|
||||
|
||||
glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, split);
|
||||
|
||||
storage->info.render_vertices_count += s->index_array_len * split;
|
||||
|
||||
} else {
|
||||
|
||||
glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, split);
|
||||
|
||||
storage->info.render_vertices_count += s->array_len * split;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount);
|
||||
if (s->index_array_len > 0) {
|
||||
|
||||
storage->info.render_vertices_count += s->array_len * amount;
|
||||
glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount);
|
||||
|
||||
storage->info.render_vertices_count += s->index_array_len * amount;
|
||||
|
||||
} else {
|
||||
|
||||
glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount);
|
||||
|
||||
storage->info.render_vertices_count += s->array_len * amount;
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
@ -1841,7 +1957,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
|
|||
|
||||
if (e->owner != prev_owner || prev_base_type != e->instance->base_type || prev_geometry != e->geometry) {
|
||||
|
||||
_setup_geometry(e);
|
||||
_setup_geometry(e, p_view_transform);
|
||||
storage->info.render_surface_switch_count++;
|
||||
}
|
||||
|
||||
|
|
|
@ -692,7 +692,7 @@ public:
|
|||
_FORCE_INLINE_ void _set_cull(bool p_front, bool p_reverse_cull);
|
||||
|
||||
_FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material *p_material, bool p_alpha_pass);
|
||||
_FORCE_INLINE_ void _setup_geometry(RenderList::Element *e);
|
||||
_FORCE_INLINE_ void _setup_geometry(RenderList::Element *e, const Transform &p_view_transform);
|
||||
_FORCE_INLINE_ void _render_geometry(RenderList::Element *e);
|
||||
_FORCE_INLINE_ void _setup_light(RenderList::Element *e, const Transform &p_view_transform);
|
||||
|
||||
|
|
|
@ -3005,6 +3005,7 @@ void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh, const Rect3 &p_aab
|
|||
|
||||
mesh->custom_aabb = p_aabb;
|
||||
}
|
||||
|
||||
Rect3 RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const {
|
||||
|
||||
const Mesh *mesh = mesh_owner.getornull(p_mesh);
|
||||
|
@ -4883,6 +4884,22 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount)
|
|||
}
|
||||
}
|
||||
|
||||
if (particles->histories_enabled) {
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
glBindVertexArray(particles->particle_vao_histories[i]);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[i]);
|
||||
glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_DYNAMIC_COPY);
|
||||
|
||||
for (int j = 0; j < 6; j++) {
|
||||
glEnableVertexAttribArray(j);
|
||||
glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (j * 16));
|
||||
}
|
||||
particles->particle_valid_histories[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
particles->prev_ticks = 0;
|
||||
|
@ -4917,18 +4934,61 @@ void RasterizerStorageGLES3::particles_set_randomness_ratio(RID p_particles, flo
|
|||
ERR_FAIL_COND(!particles);
|
||||
particles->randomness = p_ratio;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::_particles_update_histories(Particles *particles) {
|
||||
|
||||
bool needs_histories = particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH;
|
||||
|
||||
if (needs_histories == particles->histories_enabled)
|
||||
return;
|
||||
|
||||
particles->histories_enabled = needs_histories;
|
||||
|
||||
int floats = particles->amount * 24;
|
||||
|
||||
if (!needs_histories) {
|
||||
|
||||
glDeleteBuffers(2, particles->particle_buffer_histories);
|
||||
glDeleteVertexArrays(2, particles->particle_vao_histories);
|
||||
|
||||
} else {
|
||||
|
||||
glGenBuffers(2, particles->particle_buffer_histories);
|
||||
glGenVertexArrays(2, particles->particle_vao_histories);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
glBindVertexArray(particles->particle_vao_histories[i]);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[i]);
|
||||
glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), NULL, GL_DYNAMIC_COPY);
|
||||
|
||||
for (int j = 0; j < 6; j++) {
|
||||
glEnableVertexAttribArray(j);
|
||||
glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (j * 16));
|
||||
}
|
||||
|
||||
particles->particle_valid_histories[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
particles->clear = true;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::particles_set_custom_aabb(RID p_particles, const Rect3 &p_aabb) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
particles->custom_aabb = p_aabb;
|
||||
_particles_update_histories(particles);
|
||||
particles->instance_change_notify();
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_gravity(RID p_particles, const Vector3 &p_gravity) {
|
||||
|
||||
void RasterizerStorageGLES3::particles_set_speed_scale(RID p_particles, float p_scale) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->gravity = p_gravity;
|
||||
particles->speed_scale = p_scale;
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
|
||||
|
||||
|
@ -4968,6 +5028,7 @@ void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles, VS::Parti
|
|||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->draw_order = p_order;
|
||||
_particles_update_histories(particles);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles, int p_passes) {
|
||||
|
@ -5001,7 +5062,39 @@ Rect3 RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
|
|||
const Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND_V(!particles, Rect3());
|
||||
|
||||
return particles->computed_aabb;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]);
|
||||
|
||||
float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT);
|
||||
Rect3 aabb;
|
||||
|
||||
Transform inv = particles->emission_transform.affine_inverse();
|
||||
|
||||
for (int i = 0; i < particles->amount; i++) {
|
||||
int ofs = i * 24;
|
||||
Vector3 pos = Vector3(data[ofs + 15], data[ofs + 19], data[ofs + 23]);
|
||||
if (!particles->use_local_coords) {
|
||||
pos = inv.xform(pos);
|
||||
}
|
||||
if (i == 0)
|
||||
aabb.pos = pos;
|
||||
else
|
||||
aabb.expand_to(pos);
|
||||
}
|
||||
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
float longest_axis = 0;
|
||||
for (int i = 0; i < particles->draw_passes.size(); i++) {
|
||||
if (particles->draw_passes[i].is_valid()) {
|
||||
Rect3 maabb = mesh_get_aabb(particles->draw_passes[i], RID());
|
||||
longest_axis = MAX(maabb.get_longest_axis_size(), longest_axis);
|
||||
}
|
||||
}
|
||||
|
||||
aabb.grow_by(longest_axis);
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
Rect3 RasterizerStorageGLES3::particles_get_aabb(RID p_particles) const {
|
||||
|
@ -5009,7 +5102,7 @@ Rect3 RasterizerStorageGLES3::particles_get_aabb(RID p_particles) const {
|
|||
const Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND_V(!particles, Rect3());
|
||||
|
||||
return Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2));
|
||||
return particles->custom_aabb;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::particles_set_emission_transform(RID p_particles, const Transform &p_transform) {
|
||||
|
@ -5022,7 +5115,7 @@ void RasterizerStorageGLES3::particles_set_emission_transform(RID p_particles, c
|
|||
|
||||
void RasterizerStorageGLES3::_particles_process(Particles *particles, float p_delta) {
|
||||
|
||||
float new_phase = Math::fmod((float)particles->phase + (p_delta / particles->lifetime), (float)1.0);
|
||||
float new_phase = Math::fmod((float)particles->phase + (p_delta / particles->lifetime) * particles->speed_scale, (float)1.0);
|
||||
|
||||
if (particles->clear) {
|
||||
particles->cycle_number = 0;
|
||||
|
@ -5034,7 +5127,7 @@ void RasterizerStorageGLES3::_particles_process(Particles *particles, float p_de
|
|||
shaders.particles.set_uniform(ParticlesShaderGLES3::PREV_SYSTEM_PHASE, particles->phase);
|
||||
particles->phase = new_phase;
|
||||
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA, p_delta);
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA, p_delta * particles->speed_scale);
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::CLEAR, particles->clear);
|
||||
if (particles->use_local_coords)
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, Transform());
|
||||
|
@ -5154,7 +5247,6 @@ void RasterizerStorageGLES3::update_particles() {
|
|||
shaders.particles.set_uniform(ParticlesShaderGLES3::TIME, Color(frame.time[0], frame.time[1], frame.time[2], frame.time[3]));
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::EXPLOSIVENESS, particles->explosiveness);
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::LIFETIME, particles->lifetime);
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::GRAVITY, particles->gravity);
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::ATTRACTOR_COUNT, 0);
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::EMITTING, particles->emitting);
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::RANDOMNESS, particles->randomness);
|
||||
|
@ -5201,6 +5293,20 @@ void RasterizerStorageGLES3::update_particles() {
|
|||
}
|
||||
|
||||
particle_update_list.remove(particle_update_list.first());
|
||||
|
||||
if (particles->histories_enabled) {
|
||||
|
||||
SWAP(particles->particle_buffer_histories[0], particles->particle_buffer_histories[1]);
|
||||
SWAP(particles->particle_vao_histories[0], particles->particle_vao_histories[1]);
|
||||
SWAP(particles->particle_valid_histories[0], particles->particle_valid_histories[1]);
|
||||
|
||||
//copy
|
||||
glBindBuffer(GL_COPY_READ_BUFFER, particles->particle_buffers[0]);
|
||||
glBindBuffer(GL_COPY_WRITE_BUFFER, particles->particle_buffer_histories[0]);
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, particles->amount * 24 * sizeof(float));
|
||||
|
||||
particles->particle_valid_histories[0] = true;
|
||||
}
|
||||
}
|
||||
|
||||
glDisable(GL_RASTERIZER_DISCARD);
|
||||
|
|
|
@ -995,7 +995,6 @@ public:
|
|||
float explosiveness;
|
||||
float randomness;
|
||||
Rect3 custom_aabb;
|
||||
Vector3 gravity;
|
||||
bool use_local_coords;
|
||||
RID process_material;
|
||||
|
||||
|
@ -1003,11 +1002,14 @@ public:
|
|||
|
||||
Vector<RID> draw_passes;
|
||||
|
||||
Rect3 computed_aabb;
|
||||
|
||||
GLuint particle_buffers[2];
|
||||
GLuint particle_vaos[2];
|
||||
|
||||
GLuint particle_buffer_histories[2];
|
||||
GLuint particle_vao_histories[2];
|
||||
bool particle_valid_histories[2];
|
||||
bool histories_enabled;
|
||||
|
||||
SelfList<Particles> particle_element;
|
||||
|
||||
float phase;
|
||||
|
@ -1016,6 +1018,8 @@ public:
|
|||
|
||||
uint32_t cycle_number;
|
||||
|
||||
float speed_scale;
|
||||
|
||||
int fixed_fps;
|
||||
bool fractional_delta;
|
||||
float frame_remainder;
|
||||
|
@ -1037,6 +1041,10 @@ public:
|
|||
fixed_fps = 0;
|
||||
fractional_delta = false;
|
||||
frame_remainder = 0;
|
||||
histories_enabled = false;
|
||||
speed_scale = 1.0;
|
||||
|
||||
custom_aabb = Rect3(Vector3(-4, -4, -4), Vector3(8, 8, 8));
|
||||
|
||||
draw_order = VS::PARTICLES_DRAW_ORDER_INDEX;
|
||||
particle_buffers[0] = 0;
|
||||
|
@ -1054,6 +1062,10 @@ public:
|
|||
|
||||
glDeleteBuffers(2, particle_buffers);
|
||||
glDeleteVertexArrays(2, particle_vaos);
|
||||
if (histories_enabled) {
|
||||
glDeleteBuffers(2, particle_buffer_histories);
|
||||
glDeleteVertexArrays(2, particle_vao_histories);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1072,7 +1084,7 @@ public:
|
|||
virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio);
|
||||
virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio);
|
||||
virtual void particles_set_custom_aabb(RID p_particles, const Rect3 &p_aabb);
|
||||
virtual void particles_set_gravity(RID p_particles, const Vector3 &p_gravity);
|
||||
virtual void particles_set_speed_scale(RID p_particles, float p_scale);
|
||||
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable);
|
||||
virtual void particles_set_process_material(RID p_particles, RID p_material);
|
||||
virtual void particles_set_fixed_fps(RID p_particles, int p_fps);
|
||||
|
@ -1087,6 +1099,8 @@ public:
|
|||
virtual Rect3 particles_get_current_aabb(RID p_particles);
|
||||
virtual Rect3 particles_get_aabb(RID p_particles) const;
|
||||
|
||||
virtual void _particles_update_histories(Particles *particles);
|
||||
|
||||
virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform);
|
||||
void _particles_process(Particles *p_particles, float p_delta);
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ uniform float explosiveness;
|
|||
uniform float randomness;
|
||||
uniform vec4 time;
|
||||
uniform float delta;
|
||||
uniform vec3 gravity;
|
||||
|
||||
uniform int attractor_count;
|
||||
uniform Attractor attractors[MAX_ATTRACTORS];
|
||||
uniform bool clear;
|
||||
|
@ -69,9 +69,19 @@ uint hash(uint x) {
|
|||
|
||||
void main() {
|
||||
|
||||
#ifdef PARTICLES_COPY
|
||||
|
||||
out_color=color;
|
||||
out_velocity_active=velocity_active;
|
||||
out_custom = custom;
|
||||
out_xform_1 = xform_1;
|
||||
out_xform_2 = xform_2;
|
||||
out_xform_3 = xform_3;
|
||||
|
||||
#else
|
||||
|
||||
bool apply_forces=true;
|
||||
bool apply_velocity=true;
|
||||
vec3 current_gravity = gravity;
|
||||
float local_delta=delta;
|
||||
|
||||
float mass = 1.0;
|
||||
|
@ -164,7 +174,7 @@ VERTEX_SHADER_CODE
|
|||
|
||||
if (true) {
|
||||
|
||||
vec3 force = current_gravity;
|
||||
vec3 force = vec3(0.0);
|
||||
for(int i=0;i<attractor_count;i++) {
|
||||
|
||||
vec3 rel_vec = xform[3].xyz - attractors[i].pos;
|
||||
|
@ -211,6 +221,7 @@ VERTEX_SHADER_CODE
|
|||
out_xform_2 = xform[1];
|
||||
out_xform_3 = xform[2];
|
||||
|
||||
#endif //PARTICLES_COPY
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -113,48 +113,7 @@ void ParticlesEditor::_menu_option(int p_option) {
|
|||
switch (p_option) {
|
||||
|
||||
case MENU_OPTION_GENERATE_AABB: {
|
||||
#if 0
|
||||
Transform globalizer = node->get_global_transform();
|
||||
ParticleSystemSW pssw;
|
||||
for (int i = 0; i < VS::PARTICLE_VAR_MAX; i++) {
|
||||
|
||||
pssw.particle_vars[i] = node->get_variable((Particles::Variable)i);
|
||||
pssw.particle_randomness[i] = node->get_randomness((Particles::Variable)i);
|
||||
}
|
||||
|
||||
pssw.emission_half_extents = node->get_emission_half_extents();
|
||||
pssw.emission_points = node->get_emission_points();
|
||||
pssw.emission_base_velocity = node->get_emission_base_velocity();
|
||||
pssw.amount = node->get_amount();
|
||||
pssw.gravity_normal = node->get_gravity_normal();
|
||||
pssw.emitting = true;
|
||||
pssw.height_from_velocity = node->has_height_from_velocity();
|
||||
pssw.color_phase_count = 1;
|
||||
|
||||
ParticleSystemProcessSW pp;
|
||||
float delta = 0.01;
|
||||
float lifetime = pssw.particle_vars[VS::PARTICLE_LIFETIME];
|
||||
|
||||
Transform localizer = globalizer.affine_inverse();
|
||||
AABB aabb;
|
||||
for (float t = 0; t < lifetime; t += delta) {
|
||||
|
||||
pp.process(&pssw, globalizer, delta);
|
||||
for (int i = 0; i < pp.particle_data.size(); i++) {
|
||||
|
||||
Vector3 p = localizer.xform(pp.particle_data[i].pos);
|
||||
|
||||
if (t == 0 && i == 0)
|
||||
aabb.pos = p;
|
||||
else
|
||||
aabb.expand_to(p);
|
||||
}
|
||||
}
|
||||
|
||||
aabb.grow_by(aabb.get_longest_axis_size() * 0.2);
|
||||
|
||||
node->set_visibility_aabb(aabb);
|
||||
#endif
|
||||
generate_aabb->popup_centered_minsize();
|
||||
} break;
|
||||
case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH: {
|
||||
|
||||
|
@ -186,6 +145,33 @@ void ParticlesEditor::_menu_option(int p_option) {
|
|||
}
|
||||
}
|
||||
|
||||
void ParticlesEditor::_generate_aabb() {
|
||||
|
||||
float time = generate_seconds->get_value();
|
||||
|
||||
float running = 0.0;
|
||||
|
||||
EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time));
|
||||
|
||||
Rect3 rect;
|
||||
while (running < time) {
|
||||
|
||||
uint64_t ticks = OS::get_singleton()->get_ticks_usec();
|
||||
ep.step("Generating..", int(running), true);
|
||||
OS::get_singleton()->delay_usec(1000);
|
||||
|
||||
Rect3 capture = node->capture_aabb();
|
||||
if (rect == Rect3())
|
||||
rect = capture;
|
||||
else
|
||||
rect.merge_with(capture);
|
||||
|
||||
running += (OS::get_singleton()->get_ticks_usec() - ticks) / 1000000.0;
|
||||
}
|
||||
|
||||
node->set_visibility_aabb(rect);
|
||||
}
|
||||
|
||||
void ParticlesEditor::edit(Particles *p_particles) {
|
||||
|
||||
node = p_particles;
|
||||
|
@ -392,6 +378,7 @@ void ParticlesEditor::_bind_methods() {
|
|||
ClassDB::bind_method("_resource_seleted", &ParticlesEditor::_resource_seleted);
|
||||
ClassDB::bind_method("_node_selected", &ParticlesEditor::_node_selected);
|
||||
ClassDB::bind_method("_generate_emission_points", &ParticlesEditor::_generate_emission_points);
|
||||
ClassDB::bind_method("_generate_aabb", &ParticlesEditor::_generate_aabb);
|
||||
|
||||
//ClassDB::bind_method("_populate",&ParticlesEditor::_populate);
|
||||
}
|
||||
|
@ -456,6 +443,20 @@ ParticlesEditor::ParticlesEditor() {
|
|||
|
||||
emission_file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
|
||||
|
||||
generate_aabb = memnew(ConfirmationDialog);
|
||||
generate_aabb->set_title(TTR("Generate Visibility AABB"));
|
||||
VBoxContainer *genvb = memnew(VBoxContainer);
|
||||
generate_aabb->add_child(genvb);
|
||||
generate_seconds = memnew(SpinBox);
|
||||
genvb->add_margin_child(TTR("Generation Time (sec):"), generate_seconds);
|
||||
generate_seconds->set_min(0.1);
|
||||
generate_seconds->set_max(25);
|
||||
generate_seconds->set_value(2);
|
||||
|
||||
add_child(generate_aabb);
|
||||
|
||||
generate_aabb->connect("confirmed", this, "_generate_aabb");
|
||||
|
||||
//options->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
|
||||
//options->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,9 @@ class ParticlesEditor : public Control {
|
|||
SpinBox *emission_amount;
|
||||
OptionButton *emission_fill;
|
||||
|
||||
ConfirmationDialog *generate_aabb;
|
||||
SpinBox *generate_seconds;
|
||||
|
||||
enum Menu {
|
||||
|
||||
MENU_OPTION_GENERATE_AABB,
|
||||
|
@ -68,6 +71,7 @@ class ParticlesEditor : public Control {
|
|||
|
||||
PoolVector<Face3> geometry;
|
||||
|
||||
void _generate_aabb();
|
||||
void _generate_emission_points();
|
||||
void _resource_seleted(const String &p_res);
|
||||
void _node_selected(const NodePath &p_path);
|
||||
|
|
|
@ -2021,6 +2021,131 @@ VisibilityNotifierGizmo::VisibilityNotifierGizmo(VisibilityNotifier *p_notifier)
|
|||
|
||||
///
|
||||
|
||||
String ParticlesGizmo::get_handle_name(int p_idx) const {
|
||||
|
||||
switch (p_idx) {
|
||||
case 0: return "Size X";
|
||||
case 1: return "Size Y";
|
||||
case 2: return "Size Z";
|
||||
case 3: return "Pos X";
|
||||
case 4: return "Pos Y";
|
||||
case 5: return "Pos Z";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
Variant ParticlesGizmo::get_handle_value(int p_idx) const {
|
||||
|
||||
return particles->get_visibility_aabb();
|
||||
}
|
||||
void ParticlesGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) {
|
||||
|
||||
Transform gt = particles->get_global_transform();
|
||||
//gt.orthonormalize();
|
||||
Transform gi = gt.affine_inverse();
|
||||
|
||||
bool move = p_idx >= 3;
|
||||
p_idx = p_idx % 3;
|
||||
|
||||
Rect3 aabb = particles->get_visibility_aabb();
|
||||
Vector3 ray_from = p_camera->project_ray_origin(p_point);
|
||||
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
|
||||
|
||||
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) };
|
||||
|
||||
Vector3 ofs = aabb.pos + aabb.size * 0.5;
|
||||
|
||||
Vector3 axis;
|
||||
axis[p_idx] = 1.0;
|
||||
|
||||
if (move) {
|
||||
|
||||
Vector3 ra, rb;
|
||||
Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb);
|
||||
|
||||
float d = ra[p_idx];
|
||||
|
||||
aabb.pos[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5;
|
||||
particles->set_visibility_aabb(aabb);
|
||||
|
||||
} else {
|
||||
Vector3 ra, rb;
|
||||
Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb);
|
||||
|
||||
float d = ra[p_idx] - ofs[p_idx];
|
||||
if (d < 0.001)
|
||||
d = 0.001;
|
||||
//resize
|
||||
aabb.pos[p_idx] = (aabb.pos[p_idx] + aabb.size[p_idx] * 0.5) - d;
|
||||
aabb.size[p_idx] = d * 2;
|
||||
particles->set_visibility_aabb(aabb);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticlesGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
|
||||
|
||||
if (p_cancel) {
|
||||
particles->set_visibility_aabb(p_restore);
|
||||
return;
|
||||
}
|
||||
|
||||
UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
|
||||
ur->create_action(TTR("Change Particles AABB"));
|
||||
ur->add_do_method(particles, "set_custom_aabb", particles->get_visibility_aabb());
|
||||
ur->add_undo_method(particles, "set_custom_aabb", p_restore);
|
||||
ur->commit_action();
|
||||
}
|
||||
|
||||
void ParticlesGizmo::redraw() {
|
||||
|
||||
clear();
|
||||
|
||||
Vector<Vector3> lines;
|
||||
Rect3 aabb = particles->get_visibility_aabb();
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
Vector3 a, b;
|
||||
aabb.get_edge(i, a, b);
|
||||
lines.push_back(a);
|
||||
lines.push_back(b);
|
||||
}
|
||||
|
||||
Vector<Vector3> handles;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
||||
Vector3 ax;
|
||||
ax[i] = aabb.pos[i] + aabb.size[i];
|
||||
ax[(i + 1) % 3] = aabb.pos[(i + 1) % 3] + aabb.size[(i + 1) % 3] * 0.5;
|
||||
ax[(i + 2) % 3] = aabb.pos[(i + 2) % 3] + aabb.size[(i + 2) % 3] * 0.5;
|
||||
handles.push_back(ax);
|
||||
}
|
||||
|
||||
Vector3 center = aabb.pos + aabb.size * 0.5;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
||||
Vector3 ax;
|
||||
ax[i] = 1.0;
|
||||
handles.push_back(center + ax);
|
||||
lines.push_back(center);
|
||||
lines.push_back(center + ax);
|
||||
}
|
||||
|
||||
add_lines(lines, SpatialEditorGizmos::singleton->particles_material);
|
||||
add_collision_segments(lines);
|
||||
//add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05);
|
||||
add_handles(handles);
|
||||
}
|
||||
ParticlesGizmo::ParticlesGizmo(Particles *p_particles) {
|
||||
|
||||
particles = p_particles;
|
||||
set_spatial_node(p_particles);
|
||||
}
|
||||
|
||||
////////
|
||||
|
||||
///
|
||||
|
||||
String ReflectionProbeGizmo::get_handle_name(int p_idx) const {
|
||||
|
||||
switch (p_idx) {
|
||||
|
@ -2938,6 +3063,12 @@ Ref<SpatialEditorGizmo> SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) {
|
|||
return misg;
|
||||
}
|
||||
|
||||
if (p_spatial->cast_to<Particles>()) {
|
||||
|
||||
Ref<ParticlesGizmo> misg = memnew(ParticlesGizmo(p_spatial->cast_to<Particles>()));
|
||||
return misg;
|
||||
}
|
||||
|
||||
if (p_spatial->cast_to<ReflectionProbe>()) {
|
||||
|
||||
Ref<ReflectionProbeGizmo> misg = memnew(ReflectionProbeGizmo(p_spatial->cast_to<ReflectionProbe>()));
|
||||
|
@ -3152,6 +3283,7 @@ SpatialEditorGizmos::SpatialEditorGizmos() {
|
|||
raycast_material = create_line_material(Color(1.0, 0.8, 0.6));
|
||||
car_wheel_material = create_line_material(Color(0.6, 0.8, 1.0));
|
||||
visibility_notifier_material = create_line_material(Color(1.0, 0.5, 1.0));
|
||||
particles_material = create_line_material(Color(1.0, 1.0, 0.5));
|
||||
reflection_probe_material = create_line_material(Color(0.5, 1.0, 0.7));
|
||||
reflection_probe_material_internal = create_line_material(Color(0.3, 0.8, 0.5, 0.15));
|
||||
gi_probe_material = create_line_material(Color(0.7, 1.0, 0.5));
|
||||
|
|
|
@ -33,22 +33,22 @@
|
|||
#include "editor/plugins/spatial_editor_plugin.h"
|
||||
#include "scene/3d/body_shape.h"
|
||||
#include "scene/3d/camera.h"
|
||||
#include "scene/3d/collision_polygon.h"
|
||||
#include "scene/3d/gi_probe.h"
|
||||
#include "scene/3d/light.h"
|
||||
#include "scene/3d/listener.h"
|
||||
#include "scene/3d/mesh_instance.h"
|
||||
#include "scene/3d/navigation_mesh.h"
|
||||
#include "scene/3d/particles.h"
|
||||
#include "scene/3d/physics_joint.h"
|
||||
#include "scene/3d/portal.h"
|
||||
#include "scene/3d/position_3d.h"
|
||||
#include "scene/3d/ray_cast.h"
|
||||
#include "scene/3d/reflection_probe.h"
|
||||
#include "scene/3d/room_instance.h"
|
||||
#include "scene/3d/test_cube.h"
|
||||
#include "scene/3d/visibility_notifier.h"
|
||||
|
||||
#include "scene/3d/collision_polygon.h"
|
||||
#include "scene/3d/physics_joint.h"
|
||||
#include "scene/3d/vehicle_body.h"
|
||||
#include "scene/3d/visibility_notifier.h"
|
||||
|
||||
class Camera;
|
||||
|
||||
|
@ -244,6 +244,22 @@ public:
|
|||
VisibilityNotifierGizmo(VisibilityNotifier *p_notifier = NULL);
|
||||
};
|
||||
|
||||
class ParticlesGizmo : public EditorSpatialGizmo {
|
||||
|
||||
GDCLASS(ParticlesGizmo, EditorSpatialGizmo);
|
||||
|
||||
Particles *particles;
|
||||
|
||||
public:
|
||||
virtual String get_handle_name(int p_idx) const;
|
||||
virtual Variant get_handle_value(int p_idx) const;
|
||||
virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point);
|
||||
virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false);
|
||||
|
||||
void redraw();
|
||||
ParticlesGizmo(Particles *p_particles = NULL);
|
||||
};
|
||||
|
||||
class ReflectionProbeGizmo : public EditorSpatialGizmo {
|
||||
|
||||
GDCLASS(ReflectionProbeGizmo, EditorSpatialGizmo);
|
||||
|
@ -420,6 +436,7 @@ public:
|
|||
Ref<SpatialMaterial> portal_material;
|
||||
Ref<SpatialMaterial> raycast_material;
|
||||
Ref<SpatialMaterial> visibility_notifier_material;
|
||||
Ref<SpatialMaterial> particles_material;
|
||||
Ref<SpatialMaterial> car_wheel_material;
|
||||
Ref<SpatialMaterial> joint_material;
|
||||
|
||||
|
|
|
@ -71,15 +71,12 @@ void Particles::set_randomness_ratio(float p_ratio) {
|
|||
randomness_ratio = p_ratio;
|
||||
VS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio);
|
||||
}
|
||||
void Particles::set_custom_aabb(const Rect3 &p_aabb) {
|
||||
void Particles::set_visibility_aabb(const Rect3 &p_aabb) {
|
||||
|
||||
custom_aabb = p_aabb;
|
||||
VS::get_singleton()->particles_set_custom_aabb(particles, custom_aabb);
|
||||
}
|
||||
void Particles::set_gravity(const Vector3 &p_gravity) {
|
||||
|
||||
gravity = p_gravity;
|
||||
VS::get_singleton()->particles_set_gravity(particles, gravity);
|
||||
visibility_aabb = p_aabb;
|
||||
VS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb);
|
||||
update_gizmo();
|
||||
_change_notify("visibility_aabb");
|
||||
}
|
||||
void Particles::set_use_local_coordinates(bool p_enable) {
|
||||
|
||||
|
@ -93,6 +90,14 @@ void Particles::set_process_material(const Ref<Material> &p_material) {
|
|||
if (process_material.is_valid())
|
||||
material_rid = process_material->get_rid();
|
||||
VS::get_singleton()->particles_set_process_material(particles, material_rid);
|
||||
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
void Particles::set_speed_scale(float p_scale) {
|
||||
|
||||
speed_scale = p_scale;
|
||||
VS::get_singleton()->particles_set_speed_scale(particles, p_scale);
|
||||
}
|
||||
|
||||
bool Particles::is_emitting() const {
|
||||
|
@ -119,13 +124,9 @@ float Particles::get_randomness_ratio() const {
|
|||
|
||||
return randomness_ratio;
|
||||
}
|
||||
Rect3 Particles::get_custom_aabb() const {
|
||||
Rect3 Particles::get_visibility_aabb() const {
|
||||
|
||||
return custom_aabb;
|
||||
}
|
||||
Vector3 Particles::get_gravity() const {
|
||||
|
||||
return gravity;
|
||||
return visibility_aabb;
|
||||
}
|
||||
bool Particles::get_use_local_coordinates() const {
|
||||
|
||||
|
@ -136,6 +137,11 @@ Ref<Material> Particles::get_process_material() const {
|
|||
return process_material;
|
||||
}
|
||||
|
||||
float Particles::get_speed_scale() const {
|
||||
|
||||
return speed_scale;
|
||||
}
|
||||
|
||||
void Particles::set_draw_order(DrawOrder p_order) {
|
||||
|
||||
draw_order = p_order;
|
||||
|
@ -170,6 +176,8 @@ void Particles::set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh) {
|
|||
mesh_rid = p_mesh->get_rid();
|
||||
|
||||
VS::get_singleton()->particles_set_draw_pass_mesh(particles, p_pass, mesh_rid);
|
||||
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
Ref<Mesh> Particles::get_draw_pass_mesh(int p_pass) const {
|
||||
|
@ -197,6 +205,37 @@ bool Particles::get_fractional_delta() const {
|
|||
return fractional_delta;
|
||||
}
|
||||
|
||||
String Particles::get_configuration_warning() const {
|
||||
|
||||
String warnings;
|
||||
|
||||
bool meshes_found = false;
|
||||
|
||||
for (int i = 0; i < draw_passes.size(); i++) {
|
||||
if (draw_passes[i].is_valid()) {
|
||||
meshes_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!meshes_found) {
|
||||
warnings += "- " + TTR("Nothing is visible because meshes have not been assigned to draw passes.");
|
||||
}
|
||||
|
||||
if (process_material.is_null()) {
|
||||
if (warnings != String())
|
||||
warnings += "\n";
|
||||
warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted.");
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
||||
|
||||
Rect3 Particles::capture_aabb() const {
|
||||
|
||||
return VS::get_singleton()->particles_get_current_aabb(particles);
|
||||
}
|
||||
|
||||
void Particles::_validate_property(PropertyInfo &property) const {
|
||||
|
||||
if (property.name.begins_with("draw_pass_")) {
|
||||
|
@ -216,12 +255,12 @@ void Particles::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &Particles::set_pre_process_time);
|
||||
ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &Particles::set_explosiveness_ratio);
|
||||
ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &Particles::set_randomness_ratio);
|
||||
ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &Particles::set_custom_aabb);
|
||||
ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &Particles::set_gravity);
|
||||
ClassDB::bind_method(D_METHOD("set_visibility_aabb", "aabb"), &Particles::set_visibility_aabb);
|
||||
ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &Particles::set_use_local_coordinates);
|
||||
ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &Particles::set_fixed_fps);
|
||||
ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &Particles::set_fractional_delta);
|
||||
ClassDB::bind_method(D_METHOD("set_process_material", "material:Material"), &Particles::set_process_material);
|
||||
ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &Particles::set_speed_scale);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_emitting"), &Particles::is_emitting);
|
||||
ClassDB::bind_method(D_METHOD("get_amount"), &Particles::get_amount);
|
||||
|
@ -229,12 +268,12 @@ void Particles::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_pre_process_time"), &Particles::get_pre_process_time);
|
||||
ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &Particles::get_explosiveness_ratio);
|
||||
ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &Particles::get_randomness_ratio);
|
||||
ClassDB::bind_method(D_METHOD("get_custom_aabb"), &Particles::get_custom_aabb);
|
||||
ClassDB::bind_method(D_METHOD("get_gravity"), &Particles::get_gravity);
|
||||
ClassDB::bind_method(D_METHOD("get_visibility_aabb"), &Particles::get_visibility_aabb);
|
||||
ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &Particles::get_use_local_coordinates);
|
||||
ClassDB::bind_method(D_METHOD("get_fixed_fps"), &Particles::get_fixed_fps);
|
||||
ClassDB::bind_method(D_METHOD("get_fractional_delta"), &Particles::get_fractional_delta);
|
||||
ClassDB::bind_method(D_METHOD("get_process_material:Material"), &Particles::get_process_material);
|
||||
ClassDB::bind_method(D_METHOD("get_speed_scale"), &Particles::get_speed_scale);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &Particles::set_draw_order);
|
||||
|
||||
|
@ -246,20 +285,23 @@ void Particles::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_draw_passes"), &Particles::get_draw_passes);
|
||||
ClassDB::bind_method(D_METHOD("get_draw_pass_mesh:Mesh", "pass"), &Particles::get_draw_pass_mesh);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("capture_aabb"), &Particles::capture_aabb);
|
||||
|
||||
ADD_GROUP("Parameters", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,100000,1"), "set_amount", "get_amount");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01"), "set_lifetime", "get_lifetime");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_speed_scale", "get_speed_scale");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::RECT3, "custom_aabb"), "set_custom_aabb", "get_custom_aabb");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::RECT3, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ParticlesMaterial,ShaderMaterial"), "set_process_material", "get_process_material");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order");
|
||||
ADD_GROUP("Process Material", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ParticlesMaterial,ShaderMaterial"), "set_process_material", "get_process_material");
|
||||
ADD_GROUP("Draw Passes", "draw_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_passes", PROPERTY_HINT_RANGE, "0," + itos(MAX_DRAW_PASSES) + ",1"), "set_draw_passes", "get_draw_passes");
|
||||
for (int i = 0; i < MAX_DRAW_PASSES; i++) {
|
||||
|
@ -278,16 +320,18 @@ Particles::Particles() {
|
|||
particles = VS::get_singleton()->particles_create();
|
||||
set_base(particles);
|
||||
set_emitting(true);
|
||||
set_amount(100);
|
||||
set_amount(8);
|
||||
set_lifetime(1);
|
||||
set_fixed_fps(0);
|
||||
set_fractional_delta(true);
|
||||
set_pre_process_time(0);
|
||||
set_explosiveness_ratio(0);
|
||||
set_randomness_ratio(0);
|
||||
set_gravity(Vector3(0, -9.8, 0));
|
||||
set_visibility_aabb(Rect3(Vector3(-4, -4, -4), Vector3(8, 8, 8)));
|
||||
set_use_local_coordinates(true);
|
||||
set_draw_passes(1);
|
||||
set_draw_order(DRAW_ORDER_INDEX);
|
||||
set_speed_scale(1);
|
||||
}
|
||||
|
||||
Particles::~Particles() {
|
||||
|
@ -362,6 +406,8 @@ void ParticlesMaterial::init_shaders() {
|
|||
shader_names->trail_divisor = "trail_divisor";
|
||||
shader_names->trail_size_modifier = "trail_size_modifier";
|
||||
shader_names->trail_color_modifier = "trail_color_modifier";
|
||||
|
||||
shader_names->gravity = "gravity";
|
||||
}
|
||||
|
||||
void ParticlesMaterial::finish_shaders() {
|
||||
|
@ -437,6 +483,8 @@ void ParticlesMaterial::_update_shader() {
|
|||
|
||||
code += "uniform int trail_divisor;\n";
|
||||
|
||||
code += "uniform vec3 gravity;\n";
|
||||
|
||||
if (color_ramp.is_valid())
|
||||
code += "uniform sampler2D color_ramp;\n";
|
||||
|
||||
|
@ -633,7 +681,7 @@ void ParticlesMaterial::_update_shader() {
|
|||
else
|
||||
code += " float tex_anim_offset = 0.0;\n";
|
||||
|
||||
code += " vec3 force = vec3(0.0); \n";
|
||||
code += " vec3 force = gravity; \n";
|
||||
code += " vec3 pos = TRANSFORM[3].xyz; \n";
|
||||
code += " //apply linear acceleration\n";
|
||||
code += " force+=normalize(VELOCITY) * (linear_accel+tex_linear_accel)*mix(1.0,rand_from_seed(alt_seed),linear_accel_random);\n";
|
||||
|
@ -643,7 +691,7 @@ void ParticlesMaterial::_update_shader() {
|
|||
code += " //org=p_transform.origin;\n";
|
||||
code += " force+=normalize(pos-org) * (radial_accel+tex_radial_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random);\n";
|
||||
code += " //apply tangential acceleration;\n";
|
||||
code += " force+=normalize(cross(normalize(pos-org),normalize(GRAVITY))) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random));\n";
|
||||
code += " force+=normalize(cross(normalize(pos-org),normalize(gravity))) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random));\n";
|
||||
code += " //apply attractor forces\n";
|
||||
code += " VELOCITY+=force * DELTA;\n";
|
||||
if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid())
|
||||
|
@ -1168,6 +1216,21 @@ Ref<GradientTexture> ParticlesMaterial::get_trail_color_modifier() const {
|
|||
return trail_color_modifier;
|
||||
}
|
||||
|
||||
void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) {
|
||||
|
||||
gravity = p_gravity;
|
||||
Vector3 gset = gravity;
|
||||
if (gset == Vector3()) {
|
||||
gset = Vector3(0, -0.000001, 0); //as gravity is used as upvector in some calculations
|
||||
}
|
||||
VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->gravity, gset);
|
||||
}
|
||||
|
||||
Vector3 ParticlesMaterial::get_gravity() const {
|
||||
|
||||
return gravity;
|
||||
}
|
||||
|
||||
void ParticlesMaterial::_validate_property(PropertyInfo &property) const {
|
||||
|
||||
if (property.name == "color" && color_ramp.is_valid()) {
|
||||
|
@ -1248,6 +1311,9 @@ void ParticlesMaterial::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_trail_color_modifier", "texture:GradientTexture"), &ParticlesMaterial::set_trail_color_modifier);
|
||||
ClassDB::bind_method(D_METHOD("get_trail_color_modifier:GradientTexture"), &ParticlesMaterial::get_trail_color_modifier);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity);
|
||||
ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity);
|
||||
|
||||
ADD_GROUP("Trail", "trail_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_divisor", PROPERTY_HINT_RANGE, "1,1000000,1"), "set_trail_divisor", "get_trail_divisor");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_size_modifier", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_trail_size_modifier", "get_trail_size_modifier");
|
||||
|
@ -1265,6 +1331,8 @@ void ParticlesMaterial::_bind_methods() {
|
|||
ADD_GROUP("Spread", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness");
|
||||
ADD_GROUP("Gravity", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity");
|
||||
ADD_GROUP("Initial Velocity", "initial_");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY);
|
||||
|
@ -1361,6 +1429,7 @@ ParticlesMaterial::ParticlesMaterial()
|
|||
set_emission_sphere_radius(1);
|
||||
set_emission_box_extents(Vector3(1, 1, 1));
|
||||
set_trail_divisor(1);
|
||||
set_gravity(Vector3(0, -9.8, 0));
|
||||
emission_point_count = 1;
|
||||
|
||||
for (int i = 0; i < PARAM_MAX; i++) {
|
||||
|
|
|
@ -63,8 +63,8 @@ private:
|
|||
float pre_process_time;
|
||||
float explosiveness_ratio;
|
||||
float randomness_ratio;
|
||||
Rect3 custom_aabb;
|
||||
Vector3 gravity;
|
||||
float speed_scale;
|
||||
Rect3 visibility_aabb;
|
||||
bool local_coords;
|
||||
int fixed_fps;
|
||||
bool fractional_delta;
|
||||
|
@ -89,10 +89,10 @@ public:
|
|||
void set_pre_process_time(float p_time);
|
||||
void set_explosiveness_ratio(float p_ratio);
|
||||
void set_randomness_ratio(float p_ratio);
|
||||
void set_custom_aabb(const Rect3 &p_aabb);
|
||||
void set_gravity(const Vector3 &p_gravity);
|
||||
void set_visibility_aabb(const Rect3 &p_aabb);
|
||||
void set_use_local_coordinates(bool p_enable);
|
||||
void set_process_material(const Ref<Material> &p_material);
|
||||
void set_speed_scale(float p_scale);
|
||||
|
||||
bool is_emitting() const;
|
||||
int get_amount() const;
|
||||
|
@ -100,10 +100,10 @@ public:
|
|||
float get_pre_process_time() const;
|
||||
float get_explosiveness_ratio() const;
|
||||
float get_randomness_ratio() const;
|
||||
Rect3 get_custom_aabb() const;
|
||||
Vector3 get_gravity() const;
|
||||
Rect3 get_visibility_aabb() const;
|
||||
bool get_use_local_coordinates() const;
|
||||
Ref<Material> get_process_material() const;
|
||||
float get_speed_scale() const;
|
||||
|
||||
void set_fixed_fps(int p_count);
|
||||
int get_fixed_fps() const;
|
||||
|
@ -120,6 +120,9 @@ public:
|
|||
void set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh);
|
||||
Ref<Mesh> get_draw_pass_mesh(int p_pass) const;
|
||||
|
||||
virtual String get_configuration_warning() const;
|
||||
|
||||
Rect3 capture_aabb() const;
|
||||
Particles();
|
||||
~Particles();
|
||||
};
|
||||
|
@ -270,6 +273,8 @@ private:
|
|||
StringName trail_divisor;
|
||||
StringName trail_size_modifier;
|
||||
StringName trail_color_modifier;
|
||||
|
||||
StringName gravity;
|
||||
};
|
||||
|
||||
static ShaderNames *shader_names;
|
||||
|
@ -304,6 +309,8 @@ private:
|
|||
Ref<CurveTexture> trail_size_modifier;
|
||||
Ref<GradientTexture> trail_color_modifier;
|
||||
|
||||
Vector3 gravity;
|
||||
|
||||
//do not save emission points here
|
||||
|
||||
protected:
|
||||
|
@ -358,6 +365,9 @@ public:
|
|||
void set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier);
|
||||
Ref<GradientTexture> get_trail_color_modifier() const;
|
||||
|
||||
void set_gravity(const Vector3 &p_gravity);
|
||||
Vector3 get_gravity() const;
|
||||
|
||||
static void init_shaders();
|
||||
static void finish_shaders();
|
||||
static void flush_changes();
|
||||
|
|
|
@ -441,7 +441,7 @@ public:
|
|||
virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0;
|
||||
virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0;
|
||||
virtual void particles_set_custom_aabb(RID p_particles, const Rect3 &p_aabb) = 0;
|
||||
virtual void particles_set_gravity(RID p_particles, const Vector3 &p_gravity) = 0;
|
||||
virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0;
|
||||
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
|
||||
virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
|
||||
virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
|
||||
|
|
|
@ -203,8 +203,6 @@ ShaderTypes::ShaderTypes() {
|
|||
shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["DELTA"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["NUMBER"] = ShaderLanguage::TYPE_UINT;
|
||||
shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["INDEX"] = ShaderLanguage::TYPE_INT;
|
||||
shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["SEED"] = ShaderLanguage::TYPE_UINT;
|
||||
shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["GRAVITY"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["EMISSION_TRANSFORM"] = ShaderLanguage::TYPE_MAT4;
|
||||
|
||||
shader_modes[VS::SHADER_PARTICLES].modes.insert("billboard");
|
||||
|
|
|
@ -852,7 +852,7 @@ public:
|
|||
BIND2(particles_set_explosiveness_ratio, RID, float)
|
||||
BIND2(particles_set_randomness_ratio, RID, float)
|
||||
BIND2(particles_set_custom_aabb, RID, const Rect3 &)
|
||||
BIND2(particles_set_gravity, RID, const Vector3 &)
|
||||
BIND2(particles_set_speed_scale, RID, float)
|
||||
BIND2(particles_set_use_local_coordinates, RID, bool)
|
||||
BIND2(particles_set_process_material, RID, RID)
|
||||
BIND2(particles_set_fixed_fps, RID, int)
|
||||
|
|
|
@ -480,7 +480,7 @@ public:
|
|||
virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0;
|
||||
virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0;
|
||||
virtual void particles_set_custom_aabb(RID p_particles, const Rect3 &p_aabb) = 0;
|
||||
virtual void particles_set_gravity(RID p_particles, const Vector3 &p_gravity) = 0;
|
||||
virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0;
|
||||
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
|
||||
virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
|
||||
virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
|
||||
|
|
Loading…
Reference in New Issue