| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  gpu_particles_collision_3d.cpp                                       */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                      https://godotengine.org                          */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2021-01-01 20:13:46 +01:00
										 |  |  | /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "gpu_particles_collision_3d.h"
 | 
					
						
							| 
									
										
										
										
											2020-10-12 10:57:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | #include "mesh_instance_3d.h"
 | 
					
						
							|  |  |  | #include "scene/3d/camera_3d.h"
 | 
					
						
							|  |  |  | #include "scene/main/viewport.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollision3D::set_cull_mask(uint32_t p_cull_mask) { | 
					
						
							|  |  |  | 	cull_mask = p_cull_mask; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_cull_mask(collision, p_cull_mask); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint32_t GPUParticlesCollision3D::get_cull_mask() const { | 
					
						
							|  |  |  | 	return cull_mask; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollision3D::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &GPUParticlesCollision3D::set_cull_mask); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_cull_mask"), &GPUParticlesCollision3D::get_cull_mask); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollision3D::GPUParticlesCollision3D(RS::ParticlesCollisionType p_type) { | 
					
						
							|  |  |  | 	collision = RS::get_singleton()->particles_collision_create(); | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_collision_type(collision, p_type); | 
					
						
							|  |  |  | 	set_base(collision); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollision3D::~GPUParticlesCollision3D() { | 
					
						
							|  |  |  | 	RS::get_singleton()->free(collision); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionSphere::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_radius", "radius"), &GPUParticlesCollisionSphere::set_radius); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_radius"), &GPUParticlesCollisionSphere::get_radius); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_radius", "get_radius"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | void GPUParticlesCollisionSphere::set_radius(real_t p_radius) { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	radius = p_radius; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_sphere_radius(_get_collision(), radius); | 
					
						
							| 
									
										
										
										
											2021-06-23 16:49:50 +02:00
										 |  |  | 	update_gizmos(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | real_t GPUParticlesCollisionSphere::get_radius() const { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	return radius; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AABB GPUParticlesCollisionSphere::get_aabb() const { | 
					
						
							|  |  |  | 	return AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2, radius * 2, radius * 2)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionSphere::GPUParticlesCollisionSphere() : | 
					
						
							|  |  |  | 		GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionSphere::~GPUParticlesCollisionSphere() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ///////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionBox::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionBox::set_extents); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionBox::get_extents); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionBox::set_extents(const Vector3 &p_extents) { | 
					
						
							|  |  |  | 	extents = p_extents; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); | 
					
						
							| 
									
										
										
										
											2021-06-23 16:49:50 +02:00
										 |  |  | 	update_gizmos(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vector3 GPUParticlesCollisionBox::get_extents() const { | 
					
						
							|  |  |  | 	return extents; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AABB GPUParticlesCollisionBox::get_aabb() const { | 
					
						
							|  |  |  | 	return AABB(-extents, extents * 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionBox::GPUParticlesCollisionBox() : | 
					
						
							|  |  |  | 		GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionBox::~GPUParticlesCollisionBox() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ///////////////////////////////
 | 
					
						
							|  |  |  | ///////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionSDF::_find_meshes(const AABB &p_aabb, Node *p_at_node, List<PlotMesh> &plot_meshes) { | 
					
						
							|  |  |  | 	MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node); | 
					
						
							|  |  |  | 	if (mi && mi->is_visible_in_tree()) { | 
					
						
							|  |  |  | 		Ref<Mesh> mesh = mi->get_mesh(); | 
					
						
							|  |  |  | 		if (mesh.is_valid()) { | 
					
						
							|  |  |  | 			AABB aabb = mesh->get_aabb(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | 			Transform3D xf = get_global_transform().affine_inverse() * mi->get_global_transform(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (p_aabb.intersects(xf.xform(aabb))) { | 
					
						
							|  |  |  | 				PlotMesh pm; | 
					
						
							|  |  |  | 				pm.local_xform = xf; | 
					
						
							|  |  |  | 				pm.mesh = mesh; | 
					
						
							|  |  |  | 				plot_meshes.push_back(pm); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Node3D *s = Object::cast_to<Node3D>(p_at_node); | 
					
						
							|  |  |  | 	if (s) { | 
					
						
							|  |  |  | 		if (s->is_visible_in_tree()) { | 
					
						
							|  |  |  | 			Array meshes = p_at_node->call("get_meshes"); | 
					
						
							|  |  |  | 			for (int i = 0; i < meshes.size(); i += 2) { | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | 				Transform3D mxf = meshes[i]; | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 				Ref<Mesh> mesh = meshes[i + 1]; | 
					
						
							|  |  |  | 				if (!mesh.is_valid()) { | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				AABB aabb = mesh->get_aabb(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | 				Transform3D xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				if (p_aabb.intersects(xf.xform(aabb))) { | 
					
						
							|  |  |  | 					PlotMesh pm; | 
					
						
							|  |  |  | 					pm.local_xform = xf; | 
					
						
							|  |  |  | 					pm.mesh = mesh; | 
					
						
							|  |  |  | 					plot_meshes.push_back(pm); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < p_at_node->get_child_count(); i++) { | 
					
						
							|  |  |  | 		Node *child = p_at_node->get_child(i); | 
					
						
							|  |  |  | 		_find_meshes(p_aabb, child, plot_meshes); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint32_t GPUParticlesCollisionSDF::_create_bvh(LocalVector<BVH> &bvh_tree, FacePos *p_faces, uint32_t p_face_count, const Face3 *p_triangles, float p_thickness) { | 
					
						
							|  |  |  | 	if (p_face_count == 1) { | 
					
						
							|  |  |  | 		return BVH::LEAF_BIT | p_faces[0].index; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uint32_t index = bvh_tree.size(); | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		BVH bvh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (uint32_t i = 0; i < p_face_count; i++) { | 
					
						
							|  |  |  | 			const Face3 &f = p_triangles[p_faces[i].index]; | 
					
						
							|  |  |  | 			AABB aabb(f.vertex[0], Vector3()); | 
					
						
							|  |  |  | 			aabb.expand_to(f.vertex[1]); | 
					
						
							|  |  |  | 			aabb.expand_to(f.vertex[2]); | 
					
						
							|  |  |  | 			if (p_thickness > 0.0) { | 
					
						
							|  |  |  | 				Vector3 normal = p_triangles[p_faces[i].index].get_plane().normal; | 
					
						
							|  |  |  | 				aabb.expand_to(f.vertex[0] - normal * p_thickness); | 
					
						
							|  |  |  | 				aabb.expand_to(f.vertex[1] - normal * p_thickness); | 
					
						
							|  |  |  | 				aabb.expand_to(f.vertex[2] - normal * p_thickness); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (i == 0) { | 
					
						
							|  |  |  | 				bvh.bounds = aabb; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				bvh.bounds.merge_with(aabb); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		bvh_tree.push_back(bvh); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uint32_t middle = p_face_count / 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SortArray<FacePos, FaceSort> s; | 
					
						
							|  |  |  | 	s.compare.axis = bvh_tree[index].bounds.get_longest_axis_index(); | 
					
						
							|  |  |  | 	s.sort(p_faces, p_face_count); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uint32_t left = _create_bvh(bvh_tree, p_faces, middle, p_triangles, p_thickness); | 
					
						
							|  |  |  | 	uint32_t right = _create_bvh(bvh_tree, p_faces + middle, p_face_count - middle, p_triangles, p_thickness); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bvh_tree[index].children[0] = left; | 
					
						
							|  |  |  | 	bvh_tree[index].children[1] = right; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | static _FORCE_INLINE_ real_t Vector3_dot2(const Vector3 &p_vec3) { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	return p_vec3.dot(p_vec3); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionSDF::_find_closest_distance(const Vector3 &p_pos, const BVH *bvh, uint32_t p_bvh_cell, const Face3 *triangles, float thickness, float &closest_distance) { | 
					
						
							|  |  |  | 	if (p_bvh_cell & BVH::LEAF_BIT) { | 
					
						
							|  |  |  | 		p_bvh_cell &= BVH::LEAF_MASK; //remove bit
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Vector3 point = p_pos; | 
					
						
							|  |  |  | 		Plane p = triangles[p_bvh_cell].get_plane(); | 
					
						
							|  |  |  | 		float d = p.distance_to(point); | 
					
						
							|  |  |  | 		float inside_d = 1e20; | 
					
						
							|  |  |  | 		if (d < 0 && d > -thickness) { | 
					
						
							|  |  |  | 			//inside planes, do this in 2D
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Vector3 x_axis = (triangles[p_bvh_cell].vertex[0] - triangles[p_bvh_cell].vertex[1]).normalized(); | 
					
						
							|  |  |  | 			Vector3 y_axis = p.normal.cross(x_axis).normalized(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Vector2 points[3]; | 
					
						
							|  |  |  | 			for (int i = 0; i < 3; i++) { | 
					
						
							|  |  |  | 				points[i] = Vector2(x_axis.dot(triangles[p_bvh_cell].vertex[i]), y_axis.dot(triangles[p_bvh_cell].vertex[i])); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Vector2 p2d = Vector2(x_axis.dot(point), y_axis.dot(point)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// https://www.shadertoy.com/view/XsXSz4
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				Vector2 e0 = points[1] - points[0]; | 
					
						
							|  |  |  | 				Vector2 e1 = points[2] - points[1]; | 
					
						
							|  |  |  | 				Vector2 e2 = points[0] - points[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				Vector2 v0 = p2d - points[0]; | 
					
						
							|  |  |  | 				Vector2 v1 = p2d - points[1]; | 
					
						
							|  |  |  | 				Vector2 v2 = p2d - points[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				Vector2 pq0 = v0 - e0 * CLAMP(v0.dot(e0) / e0.dot(e0), 0.0, 1.0); | 
					
						
							|  |  |  | 				Vector2 pq1 = v1 - e1 * CLAMP(v1.dot(e1) / e1.dot(e1), 0.0, 1.0); | 
					
						
							|  |  |  | 				Vector2 pq2 = v2 - e2 * CLAMP(v2.dot(e2) / e2.dot(e2), 0.0, 1.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				float s = SGN(e0.x * e2.y - e0.y * e2.x); | 
					
						
							|  |  |  | 				Vector2 d2 = Vector2(pq0.dot(pq0), s * (v0.x * e0.y - v0.y * e0.x)).min(Vector2(pq1.dot(pq1), s * (v1.x * e1.y - v1.y * e1.x))).min(Vector2(pq2.dot(pq2), s * (v2.x * e2.y - v2.y * e2.x))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				inside_d = -Math::sqrt(d2.x) * SGN(d2.y); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			//make sure distance to planes is not shorter if inside
 | 
					
						
							|  |  |  | 			if (inside_d < 0) { | 
					
						
							|  |  |  | 				inside_d = MAX(inside_d, d); | 
					
						
							|  |  |  | 				inside_d = MAX(inside_d, -(thickness + d)); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			closest_distance = MIN(closest_distance, inside_d); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if (d < 0) { | 
					
						
							|  |  |  | 				point -= p.normal * thickness; //flatten
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
 | 
					
						
							|  |  |  | 			Vector3 a = triangles[p_bvh_cell].vertex[0]; | 
					
						
							|  |  |  | 			Vector3 b = triangles[p_bvh_cell].vertex[1]; | 
					
						
							|  |  |  | 			Vector3 c = triangles[p_bvh_cell].vertex[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Vector3 ba = b - a; | 
					
						
							|  |  |  | 			Vector3 pa = point - a; | 
					
						
							|  |  |  | 			Vector3 cb = c - b; | 
					
						
							|  |  |  | 			Vector3 pb = point - b; | 
					
						
							|  |  |  | 			Vector3 ac = a - c; | 
					
						
							|  |  |  | 			Vector3 pc = point - c; | 
					
						
							|  |  |  | 			Vector3 nor = ba.cross(ac); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			inside_d = Math::sqrt( | 
					
						
							|  |  |  | 					(SGN(ba.cross(nor).dot(pa)) + | 
					
						
							|  |  |  | 									SGN(cb.cross(nor).dot(pb)) + | 
					
						
							|  |  |  | 									SGN(ac.cross(nor).dot(pc)) < | 
					
						
							|  |  |  | 							2.0) ? | 
					
						
							| 
									
										
										
										
											2021-01-12 16:57:55 +01:00
										 |  |  | 							  MIN(MIN( | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 										Vector3_dot2(ba * CLAMP(ba.dot(pa) / Vector3_dot2(ba), 0.0, 1.0) - pa), | 
					
						
							|  |  |  | 										Vector3_dot2(cb * CLAMP(cb.dot(pb) / Vector3_dot2(cb), 0.0, 1.0) - pb)), | 
					
						
							|  |  |  | 									Vector3_dot2(ac * CLAMP(ac.dot(pc) / Vector3_dot2(ac), 0.0, 1.0) - pc)) : | 
					
						
							| 
									
										
										
										
											2021-01-12 16:57:55 +01:00
										 |  |  | 							  nor.dot(pa) * nor.dot(pa) / Vector3_dot2(nor)); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			closest_distance = MIN(closest_distance, inside_d); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		bool pass = true; | 
					
						
							|  |  |  | 		if (!bvh[p_bvh_cell].bounds.has_point(p_pos)) { | 
					
						
							|  |  |  | 			//outside, find closest point
 | 
					
						
							|  |  |  | 			Vector3 he = bvh[p_bvh_cell].bounds.size * 0.5; | 
					
						
							|  |  |  | 			Vector3 center = bvh[p_bvh_cell].bounds.position + he; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Vector3 rel = (p_pos - center).abs(); | 
					
						
							|  |  |  | 			Vector3 closest(MIN(rel.x, he.x), MIN(rel.y, he.y), MIN(rel.z, he.z)); | 
					
						
							|  |  |  | 			float d = rel.distance_to(closest); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (d >= closest_distance) { | 
					
						
							|  |  |  | 				pass = false; //already closer than this aabb, discard
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (pass) { | 
					
						
							|  |  |  | 			_find_closest_distance(p_pos, bvh, bvh[p_bvh_cell].children[0], triangles, thickness, closest_distance); | 
					
						
							|  |  |  | 			_find_closest_distance(p_pos, bvh, bvh[p_bvh_cell].children[1], triangles, thickness, closest_distance); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionSDF::_compute_sdf_z(uint32_t p_z, ComputeSDFParams *params) { | 
					
						
							|  |  |  | 	int32_t z_ofs = p_z * params->size.y * params->size.x; | 
					
						
							|  |  |  | 	for (int32_t y = 0; y < params->size.y; y++) { | 
					
						
							|  |  |  | 		int32_t y_ofs = z_ofs + y * params->size.x; | 
					
						
							|  |  |  | 		for (int32_t x = 0; x < params->size.x; x++) { | 
					
						
							|  |  |  | 			int32_t x_ofs = y_ofs + x; | 
					
						
							|  |  |  | 			float &cell = params->cells[x_ofs]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Vector3 pos = params->cell_offset + Vector3(x, y, p_z) * params->cell_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			cell = 1e20; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			_find_closest_distance(pos, params->bvh, 0, params->triangles, params->thickness, cell); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionSDF::_compute_sdf(ComputeSDFParams *params) { | 
					
						
							|  |  |  | 	ThreadWorkPool work_pool; | 
					
						
							|  |  |  | 	work_pool.init(); | 
					
						
							|  |  |  | 	work_pool.begin_work(params->size.z, this, &GPUParticlesCollisionSDF::_compute_sdf_z, params); | 
					
						
							| 
									
										
										
										
											2021-03-24 20:44:13 -03:00
										 |  |  | 	while (!work_pool.is_done_dispatching()) { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 		OS::get_singleton()->delay_usec(10000); | 
					
						
							|  |  |  | 		bake_step_function(work_pool.get_work_index() * 100 / params->size.z, "Baking SDF"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	work_pool.end_work(); | 
					
						
							|  |  |  | 	work_pool.finish(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vector3i GPUParticlesCollisionSDF::get_estimated_cell_size() const { | 
					
						
							|  |  |  | 	static const int subdivs[RESOLUTION_MAX] = { 16, 32, 64, 128, 256, 512 }; | 
					
						
							|  |  |  | 	int subdiv = subdivs[get_resolution()]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	AABB aabb(-extents, extents * 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float cell_size = aabb.get_longest_axis_size() / float(subdiv); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Vector3i sdf_size = Vector3i(aabb.size / cell_size); | 
					
						
							|  |  |  | 	sdf_size.x = MAX(1, sdf_size.x); | 
					
						
							|  |  |  | 	sdf_size.y = MAX(1, sdf_size.y); | 
					
						
							|  |  |  | 	sdf_size.z = MAX(1, sdf_size.z); | 
					
						
							|  |  |  | 	return sdf_size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ref<Image> GPUParticlesCollisionSDF::bake() { | 
					
						
							|  |  |  | 	static const int subdivs[RESOLUTION_MAX] = { 16, 32, 64, 128, 256, 512 }; | 
					
						
							|  |  |  | 	int subdiv = subdivs[get_resolution()]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	AABB aabb(-extents, extents * 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float cell_size = aabb.get_longest_axis_size() / float(subdiv); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Vector3i sdf_size = Vector3i(aabb.size / cell_size); | 
					
						
							|  |  |  | 	sdf_size.x = MAX(1, sdf_size.x); | 
					
						
							|  |  |  | 	sdf_size.y = MAX(1, sdf_size.y); | 
					
						
							|  |  |  | 	sdf_size.z = MAX(1, sdf_size.z); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (bake_begin_function) { | 
					
						
							|  |  |  | 		bake_begin_function(100); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	aabb.size = Vector3(sdf_size) * cell_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	List<PlotMesh> plot_meshes; | 
					
						
							|  |  |  | 	_find_meshes(aabb, get_parent(), plot_meshes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	LocalVector<Face3> faces; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (bake_step_function) { | 
					
						
							|  |  |  | 		bake_step_function(0, "Finding Meshes"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 15:46:25 +02:00
										 |  |  | 	for (const PlotMesh &pm : plot_meshes) { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 		for (int i = 0; i < pm.mesh->get_surface_count(); i++) { | 
					
						
							|  |  |  | 			if (pm.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { | 
					
						
							|  |  |  | 				continue; //only triangles
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Array a = pm.mesh->surface_get_arrays(i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; | 
					
						
							|  |  |  | 			const Vector3 *vr = vertices.ptr(); | 
					
						
							|  |  |  | 			Vector<int> index = a[Mesh::ARRAY_INDEX]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (index.size()) { | 
					
						
							|  |  |  | 				int facecount = index.size() / 3; | 
					
						
							|  |  |  | 				const int *ir = index.ptr(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				for (int j = 0; j < facecount; j++) { | 
					
						
							|  |  |  | 					Face3 face; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					for (int k = 0; k < 3; k++) { | 
					
						
							|  |  |  | 						face.vertex[k] = pm.local_xform.xform(vr[ir[j * 3 + k]]); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					//test against original bounds
 | 
					
						
							| 
									
										
										
										
											2021-09-21 00:33:52 +05:45
										 |  |  | 					if (!Geometry3D::triangle_box_overlap(aabb.get_center(), aabb.size * 0.5, face.vertex)) { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 						continue; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					faces.push_back(face); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				int facecount = vertices.size() / 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				for (int j = 0; j < facecount; j++) { | 
					
						
							|  |  |  | 					Face3 face; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					for (int k = 0; k < 3; k++) { | 
					
						
							|  |  |  | 						face.vertex[k] = pm.local_xform.xform(vr[j * 3 + k]); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					//test against original bounds
 | 
					
						
							| 
									
										
										
										
											2021-09-21 00:33:52 +05:45
										 |  |  | 					if (!Geometry3D::triangle_box_overlap(aabb.get_center(), aabb.size * 0.5, face.vertex)) { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 						continue; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					faces.push_back(face); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//compute bvh
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(faces.size() <= 1, Ref<Image>()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	LocalVector<FacePos> face_pos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	face_pos.resize(faces.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float th = cell_size * thickness; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (uint32_t i = 0; i < faces.size(); i++) { | 
					
						
							|  |  |  | 		face_pos[i].index = i; | 
					
						
							|  |  |  | 		face_pos[i].center = (faces[i].vertex[0] + faces[i].vertex[1] + faces[i].vertex[2]) / 2; | 
					
						
							|  |  |  | 		if (th > 0.0) { | 
					
						
							|  |  |  | 			face_pos[i].center -= faces[i].get_plane().normal * th * 0.5; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (bake_step_function) { | 
					
						
							|  |  |  | 		bake_step_function(0, "Creating BVH"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	LocalVector<BVH> bvh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_create_bvh(bvh, face_pos.ptr(), face_pos.size(), faces.ptr(), th); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Vector<uint8_t> data; | 
					
						
							| 
									
										
										
										
											2021-09-07 23:25:35 -05:00
										 |  |  | 	data.resize(sdf_size.z * sdf_size.y * sdf_size.x * (int)sizeof(float)); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (bake_step_function) { | 
					
						
							|  |  |  | 		bake_step_function(0, "Baking SDF"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ComputeSDFParams params; | 
					
						
							|  |  |  | 	params.cells = (float *)data.ptrw(); | 
					
						
							|  |  |  | 	params.size = sdf_size; | 
					
						
							|  |  |  | 	params.cell_size = cell_size; | 
					
						
							|  |  |  | 	params.cell_offset = aabb.position + Vector3(cell_size * 0.5, cell_size * 0.5, cell_size * 0.5); | 
					
						
							|  |  |  | 	params.bvh = bvh.ptr(); | 
					
						
							|  |  |  | 	params.triangles = faces.ptr(); | 
					
						
							|  |  |  | 	params.thickness = th; | 
					
						
							|  |  |  | 	_compute_sdf(¶ms); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<Image> ret; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:03:09 -06:00
										 |  |  | 	ret.instantiate(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	ret->create(sdf_size.x, sdf_size.y * sdf_size.z, false, Image::FORMAT_RF, data); | 
					
						
							|  |  |  | 	ret->convert(Image::FORMAT_RH); //convert to half, save space
 | 
					
						
							|  |  |  | 	ret->set_meta("depth", sdf_size.z); //hack, make sure to add to the docs of this function
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (bake_end_function) { | 
					
						
							|  |  |  | 		bake_end_function(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionSDF::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionSDF::set_extents); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionSDF::get_extents); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_resolution", "resolution"), &GPUParticlesCollisionSDF::set_resolution); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_resolution"), &GPUParticlesCollisionSDF::get_resolution); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_texture", "texture"), &GPUParticlesCollisionSDF::set_texture); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_texture"), &GPUParticlesCollisionSDF::get_texture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_thickness", "thickness"), &GPUParticlesCollisionSDF::set_thickness); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_thickness"), &GPUParticlesCollisionSDF::get_thickness); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "16,32,64,128,256,512"), "set_resolution", "get_resolution"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "thickness", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_thickness", "get_thickness"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_16); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_32); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_64); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_128); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_256); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_512); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_MAX); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionSDF::set_thickness(float p_thickness) { | 
					
						
							|  |  |  | 	thickness = p_thickness; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float GPUParticlesCollisionSDF::get_thickness() const { | 
					
						
							|  |  |  | 	return thickness; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionSDF::set_extents(const Vector3 &p_extents) { | 
					
						
							|  |  |  | 	extents = p_extents; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); | 
					
						
							| 
									
										
										
										
											2021-06-23 16:49:50 +02:00
										 |  |  | 	update_gizmos(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vector3 GPUParticlesCollisionSDF::get_extents() const { | 
					
						
							|  |  |  | 	return extents; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionSDF::set_resolution(Resolution p_resolution) { | 
					
						
							|  |  |  | 	resolution = p_resolution; | 
					
						
							| 
									
										
										
										
											2021-06-23 16:49:50 +02:00
										 |  |  | 	update_gizmos(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionSDF::Resolution GPUParticlesCollisionSDF::get_resolution() const { | 
					
						
							|  |  |  | 	return resolution; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionSDF::set_texture(const Ref<Texture3D> &p_texture) { | 
					
						
							|  |  |  | 	texture = p_texture; | 
					
						
							|  |  |  | 	RID tex = texture.is_valid() ? texture->get_rid() : RID(); | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_field_texture(_get_collision(), tex); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ref<Texture3D> GPUParticlesCollisionSDF::get_texture() const { | 
					
						
							|  |  |  | 	return texture; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AABB GPUParticlesCollisionSDF::get_aabb() const { | 
					
						
							|  |  |  | 	return AABB(-extents, extents * 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionSDF::BakeBeginFunc GPUParticlesCollisionSDF::bake_begin_function = nullptr; | 
					
						
							|  |  |  | GPUParticlesCollisionSDF::BakeStepFunc GPUParticlesCollisionSDF::bake_step_function = nullptr; | 
					
						
							|  |  |  | GPUParticlesCollisionSDF::BakeEndFunc GPUParticlesCollisionSDF::bake_end_function = nullptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionSDF::GPUParticlesCollisionSDF() : | 
					
						
							|  |  |  | 		GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionSDF::~GPUParticlesCollisionSDF() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////
 | 
					
						
							|  |  |  | ////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionHeightField::_notification(int p_what) { | 
					
						
							|  |  |  | 	if (p_what == NOTIFICATION_INTERNAL_PROCESS) { | 
					
						
							|  |  |  | 		if (update_mode == UPDATE_MODE_ALWAYS) { | 
					
						
							|  |  |  | 			RS::get_singleton()->particles_collision_height_field_update(_get_collision()); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (follow_camera_mode && get_viewport()) { | 
					
						
							| 
									
										
										
										
											2020-04-28 11:04:07 -04:00
										 |  |  | 			Camera3D *cam = get_viewport()->get_camera_3d(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 			if (cam) { | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | 				Transform3D xform = get_global_transform(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 				Vector3 x_axis = xform.basis.get_axis(Vector3::AXIS_X).normalized(); | 
					
						
							|  |  |  | 				Vector3 z_axis = xform.basis.get_axis(Vector3::AXIS_Z).normalized(); | 
					
						
							|  |  |  | 				float x_len = xform.basis.get_scale().x; | 
					
						
							|  |  |  | 				float z_len = xform.basis.get_scale().z; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				Vector3 cam_pos = cam->get_global_transform().origin; | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | 				Transform3D new_xform = xform; | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				while (x_axis.dot(cam_pos - new_xform.origin) > x_len) { | 
					
						
							|  |  |  | 					new_xform.origin += x_axis * x_len; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				while (x_axis.dot(cam_pos - new_xform.origin) < -x_len) { | 
					
						
							|  |  |  | 					new_xform.origin -= x_axis * x_len; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				while (z_axis.dot(cam_pos - new_xform.origin) > z_len) { | 
					
						
							|  |  |  | 					new_xform.origin += z_axis * z_len; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				while (z_axis.dot(cam_pos - new_xform.origin) < -z_len) { | 
					
						
							|  |  |  | 					new_xform.origin -= z_axis * z_len; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (new_xform != xform) { | 
					
						
							|  |  |  | 					set_global_transform(new_xform); | 
					
						
							|  |  |  | 					RS::get_singleton()->particles_collision_height_field_update(_get_collision()); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { | 
					
						
							|  |  |  | 		RS::get_singleton()->particles_collision_height_field_update(_get_collision()); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionHeightField::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionHeightField::set_extents); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionHeightField::get_extents); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_resolution", "resolution"), &GPUParticlesCollisionHeightField::set_resolution); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_resolution"), &GPUParticlesCollisionHeightField::get_resolution); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_update_mode", "update_mode"), &GPUParticlesCollisionHeightField::set_update_mode); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_update_mode"), &GPUParticlesCollisionHeightField::get_update_mode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_follow_camera_mode", "enabled"), &GPUParticlesCollisionHeightField::set_follow_camera_mode); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("is_follow_camera_mode_enabled"), &GPUParticlesCollisionHeightField::is_follow_camera_mode_enabled); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_follow_camera_push_ratio", "ratio"), &GPUParticlesCollisionHeightField::set_follow_camera_push_ratio); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_follow_camera_push_ratio"), &GPUParticlesCollisionHeightField::get_follow_camera_push_ratio); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096,8192"), "set_resolution", "get_resolution"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "WhenMoved,Always"), "set_update_mode", "get_update_mode"); | 
					
						
							| 
									
										
										
										
											2021-05-20 12:07:26 +02:00
										 |  |  | 	ADD_GROUP("Follow Camera", "follow_camera_"); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_camera_enabled"), "set_follow_camera_mode", "is_follow_camera_mode_enabled"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "follow_camera_push_ratio", PROPERTY_HINT_RANGE, "0.01,1,0.01"), "set_follow_camera_push_ratio", "get_follow_camera_push_ratio"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_256); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_512); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_1024); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_2048); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_4096); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_8192); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESOLUTION_MAX); | 
					
						
							| 
									
										
										
										
											2020-10-12 10:57:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(UPDATE_MODE_WHEN_MOVED); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(UPDATE_MODE_ALWAYS); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionHeightField::set_follow_camera_push_ratio(float p_follow_camera_push_ratio) { | 
					
						
							|  |  |  | 	follow_camera_push_ratio = p_follow_camera_push_ratio; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float GPUParticlesCollisionHeightField::get_follow_camera_push_ratio() const { | 
					
						
							|  |  |  | 	return follow_camera_push_ratio; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionHeightField::set_extents(const Vector3 &p_extents) { | 
					
						
							|  |  |  | 	extents = p_extents; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); | 
					
						
							| 
									
										
										
										
											2021-06-23 16:49:50 +02:00
										 |  |  | 	update_gizmos(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	RS::get_singleton()->particles_collision_height_field_update(_get_collision()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vector3 GPUParticlesCollisionHeightField::get_extents() const { | 
					
						
							|  |  |  | 	return extents; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionHeightField::set_resolution(Resolution p_resolution) { | 
					
						
							|  |  |  | 	resolution = p_resolution; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_height_field_resolution(_get_collision(), RS::ParticlesCollisionHeightfieldResolution(resolution)); | 
					
						
							| 
									
										
										
										
											2021-06-23 16:49:50 +02:00
										 |  |  | 	update_gizmos(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	RS::get_singleton()->particles_collision_height_field_update(_get_collision()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionHeightField::Resolution GPUParticlesCollisionHeightField::get_resolution() const { | 
					
						
							|  |  |  | 	return resolution; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionHeightField::set_update_mode(UpdateMode p_update_mode) { | 
					
						
							|  |  |  | 	update_mode = p_update_mode; | 
					
						
							|  |  |  | 	set_process_internal(follow_camera_mode || update_mode == UPDATE_MODE_ALWAYS); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionHeightField::UpdateMode GPUParticlesCollisionHeightField::get_update_mode() const { | 
					
						
							|  |  |  | 	return update_mode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesCollisionHeightField::set_follow_camera_mode(bool p_enabled) { | 
					
						
							|  |  |  | 	follow_camera_mode = p_enabled; | 
					
						
							|  |  |  | 	set_process_internal(follow_camera_mode || update_mode == UPDATE_MODE_ALWAYS); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool GPUParticlesCollisionHeightField::is_follow_camera_mode_enabled() const { | 
					
						
							|  |  |  | 	return follow_camera_mode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AABB GPUParticlesCollisionHeightField::get_aabb() const { | 
					
						
							|  |  |  | 	return AABB(-extents, extents * 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionHeightField::GPUParticlesCollisionHeightField() : | 
					
						
							|  |  |  | 		GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesCollisionHeightField::~GPUParticlesCollisionHeightField() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////
 | 
					
						
							|  |  |  | ////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesAttractor3D::set_cull_mask(uint32_t p_cull_mask) { | 
					
						
							|  |  |  | 	cull_mask = p_cull_mask; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_cull_mask(collision, p_cull_mask); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint32_t GPUParticlesAttractor3D::get_cull_mask() const { | 
					
						
							|  |  |  | 	return cull_mask; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | void GPUParticlesAttractor3D::set_strength(real_t p_strength) { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	strength = p_strength; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_attractor_strength(collision, p_strength); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | real_t GPUParticlesAttractor3D::get_strength() const { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	return strength; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | void GPUParticlesAttractor3D::set_attenuation(real_t p_attenuation) { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	attenuation = p_attenuation; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_attractor_attenuation(collision, p_attenuation); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | real_t GPUParticlesAttractor3D::get_attenuation() const { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	return attenuation; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | void GPUParticlesAttractor3D::set_directionality(real_t p_directionality) { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	directionality = p_directionality; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_attractor_directionality(collision, p_directionality); | 
					
						
							| 
									
										
										
										
											2021-06-23 16:49:50 +02:00
										 |  |  | 	update_gizmos(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | real_t GPUParticlesAttractor3D::get_directionality() const { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	return directionality; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesAttractor3D::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &GPUParticlesAttractor3D::set_cull_mask); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_cull_mask"), &GPUParticlesAttractor3D::get_cull_mask); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_strength", "strength"), &GPUParticlesAttractor3D::set_strength); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_strength"), &GPUParticlesAttractor3D::get_strength); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_attenuation", "attenuation"), &GPUParticlesAttractor3D::set_attenuation); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_attenuation"), &GPUParticlesAttractor3D::get_attenuation); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_directionality", "amount"), &GPUParticlesAttractor3D::set_directionality); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_directionality"), &GPUParticlesAttractor3D::get_directionality); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "-128,128,0.01,or_greater,or_lesser"), "set_strength", "get_strength"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attenuation", PROPERTY_HINT_EXP_EASING, "0,8,0.01"), "set_attenuation", "get_attenuation"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "directionality", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_directionality", "get_directionality"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesAttractor3D::GPUParticlesAttractor3D(RS::ParticlesCollisionType p_type) { | 
					
						
							|  |  |  | 	collision = RS::get_singleton()->particles_collision_create(); | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_collision_type(collision, p_type); | 
					
						
							|  |  |  | 	set_base(collision); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | GPUParticlesAttractor3D::~GPUParticlesAttractor3D() { | 
					
						
							|  |  |  | 	RS::get_singleton()->free(collision); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesAttractorSphere::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_radius", "radius"), &GPUParticlesAttractorSphere::set_radius); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_radius"), &GPUParticlesAttractorSphere::get_radius); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_radius", "get_radius"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | void GPUParticlesAttractorSphere::set_radius(real_t p_radius) { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	radius = p_radius; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_sphere_radius(_get_collision(), radius); | 
					
						
							| 
									
										
										
										
											2021-06-23 16:49:50 +02:00
										 |  |  | 	update_gizmos(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 09:07:47 -05:00
										 |  |  | real_t GPUParticlesAttractorSphere::get_radius() const { | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | 	return radius; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AABB GPUParticlesAttractorSphere::get_aabb() const { | 
					
						
							|  |  |  | 	return AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2, radius * 2, radius * 2)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesAttractorSphere::GPUParticlesAttractorSphere() : | 
					
						
							|  |  |  | 		GPUParticlesAttractor3D(RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesAttractorSphere::~GPUParticlesAttractorSphere() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ///////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesAttractorBox::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesAttractorBox::set_extents); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesAttractorBox::get_extents); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesAttractorBox::set_extents(const Vector3 &p_extents) { | 
					
						
							|  |  |  | 	extents = p_extents; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); | 
					
						
							| 
									
										
										
										
											2021-06-23 16:49:50 +02:00
										 |  |  | 	update_gizmos(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vector3 GPUParticlesAttractorBox::get_extents() const { | 
					
						
							|  |  |  | 	return extents; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AABB GPUParticlesAttractorBox::get_aabb() const { | 
					
						
							|  |  |  | 	return AABB(-extents, extents * 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesAttractorBox::GPUParticlesAttractorBox() : | 
					
						
							|  |  |  | 		GPUParticlesAttractor3D(RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesAttractorBox::~GPUParticlesAttractorBox() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ///////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesAttractorVectorField::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesAttractorVectorField::set_extents); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesAttractorVectorField::get_extents); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_texture", "texture"), &GPUParticlesAttractorVectorField::set_texture); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_texture"), &GPUParticlesAttractorVectorField::get_texture); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesAttractorVectorField::set_extents(const Vector3 &p_extents) { | 
					
						
							|  |  |  | 	extents = p_extents; | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); | 
					
						
							| 
									
										
										
										
											2021-06-23 16:49:50 +02:00
										 |  |  | 	update_gizmos(); | 
					
						
							| 
									
										
										
										
											2020-10-07 21:29:49 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vector3 GPUParticlesAttractorVectorField::get_extents() const { | 
					
						
							|  |  |  | 	return extents; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GPUParticlesAttractorVectorField::set_texture(const Ref<Texture3D> &p_texture) { | 
					
						
							|  |  |  | 	texture = p_texture; | 
					
						
							|  |  |  | 	RID tex = texture.is_valid() ? texture->get_rid() : RID(); | 
					
						
							|  |  |  | 	RS::get_singleton()->particles_collision_set_field_texture(_get_collision(), tex); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ref<Texture3D> GPUParticlesAttractorVectorField::get_texture() const { | 
					
						
							|  |  |  | 	return texture; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AABB GPUParticlesAttractorVectorField::get_aabb() const { | 
					
						
							|  |  |  | 	return AABB(-extents, extents * 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesAttractorVectorField::GPUParticlesAttractorVectorField() : | 
					
						
							|  |  |  | 		GPUParticlesAttractor3D(RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GPUParticlesAttractorVectorField::~GPUParticlesAttractorVectorField() { | 
					
						
							|  |  |  | } |