diff options
Diffstat (limited to 'scene/3d/gpu_particles_collision_3d.h')
-rw-r--r-- | scene/3d/gpu_particles_collision_3d.h | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h new file mode 100644 index 0000000000..fbf68ed6df --- /dev/null +++ b/scene/3d/gpu_particles_collision_3d.h @@ -0,0 +1,340 @@ +/*************************************************************************/ +/* gpu_particles_collision_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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. */ +/*************************************************************************/ + +#ifndef GPU_PARTICLES_COLLISION_3D_H +#define GPU_PARTICLES_COLLISION_3D_H + +#include "core/templates/local_vector.h" +#include "scene/3d/visual_instance_3d.h" + +class GPUParticlesCollision3D : public VisualInstance3D { + GDCLASS(GPUParticlesCollision3D, VisualInstance3D); + + uint32_t cull_mask = 0xFFFFFFFF; + RID collision; + +protected: + _FORCE_INLINE_ RID _get_collision() { return collision; } + static void _bind_methods(); + + GPUParticlesCollision3D(RS::ParticlesCollisionType p_type); + +public: + void set_cull_mask(uint32_t p_cull_mask); + uint32_t get_cull_mask() const; + + virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); } + + ~GPUParticlesCollision3D(); +}; + +class GPUParticlesCollisionSphere : public GPUParticlesCollision3D { + GDCLASS(GPUParticlesCollisionSphere, GPUParticlesCollision3D); + + real_t radius = 1.0; + +protected: + static void _bind_methods(); + +public: + void set_radius(real_t p_radius); + real_t get_radius() const; + + virtual AABB get_aabb() const override; + + GPUParticlesCollisionSphere(); + ~GPUParticlesCollisionSphere(); +}; + +class GPUParticlesCollisionBox : public GPUParticlesCollision3D { + GDCLASS(GPUParticlesCollisionBox, GPUParticlesCollision3D); + + Vector3 extents = Vector3(1, 1, 1); + +protected: + static void _bind_methods(); + +public: + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + virtual AABB get_aabb() const override; + + GPUParticlesCollisionBox(); + ~GPUParticlesCollisionBox(); +}; + +class GPUParticlesCollisionSDF : public GPUParticlesCollision3D { + GDCLASS(GPUParticlesCollisionSDF, GPUParticlesCollision3D); + +public: + enum Resolution { + RESOLUTION_16, + RESOLUTION_32, + RESOLUTION_64, + RESOLUTION_128, + RESOLUTION_256, + RESOLUTION_512, + RESOLUTION_MAX, + }; + + typedef void (*BakeBeginFunc)(int); + typedef void (*BakeStepFunc)(int, const String &); + typedef void (*BakeEndFunc)(); + +private: + Vector3 extents = Vector3(1, 1, 1); + Resolution resolution = RESOLUTION_64; + Ref<Texture3D> texture; + float thickness = 1.0; + + struct PlotMesh { + Ref<Mesh> mesh; + Transform3D local_xform; + }; + + void _find_meshes(const AABB &p_aabb, Node *p_at_node, List<PlotMesh> &plot_meshes); + + struct BVH { + enum { + LEAF_BIT = 1 << 30, + LEAF_MASK = LEAF_BIT - 1 + }; + AABB bounds; + uint32_t children[2] = {}; + }; + + struct FacePos { + Vector3 center; + uint32_t index = 0; + }; + + struct FaceSort { + uint32_t axis = 0; + bool operator()(const FacePos &p_left, const FacePos &p_right) const { + return p_left.center[axis] < p_right.center[axis]; + } + }; + + uint32_t _create_bvh(LocalVector<BVH> &bvh_tree, FacePos *p_faces, uint32_t p_face_count, const Face3 *p_triangles, float p_thickness); + + struct ComputeSDFParams { + float *cells = nullptr; + Vector3i size; + float cell_size = 0.0; + Vector3 cell_offset; + const BVH *bvh = nullptr; + const Face3 *triangles = nullptr; + float thickness = 0.0; + }; + + void _find_closest_distance(const Vector3 &p_pos, const BVH *bvh, uint32_t p_bvh_cell, const Face3 *triangles, float thickness, float &closest_distance); + void _compute_sdf_z(uint32_t p_z, ComputeSDFParams *params); + void _compute_sdf(ComputeSDFParams *params); + +protected: + static void _bind_methods(); + +public: + void set_thickness(float p_thickness); + float get_thickness() const; + + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + void set_resolution(Resolution p_resolution); + Resolution get_resolution() const; + + void set_texture(const Ref<Texture3D> &p_texture); + Ref<Texture3D> get_texture() const; + + Vector3i get_estimated_cell_size() const; + Ref<Image> bake(); + + virtual AABB get_aabb() const override; + + static BakeBeginFunc bake_begin_function; + static BakeStepFunc bake_step_function; + static BakeEndFunc bake_end_function; + + GPUParticlesCollisionSDF(); + ~GPUParticlesCollisionSDF(); +}; + +VARIANT_ENUM_CAST(GPUParticlesCollisionSDF::Resolution) + +class GPUParticlesCollisionHeightField : public GPUParticlesCollision3D { + GDCLASS(GPUParticlesCollisionHeightField, GPUParticlesCollision3D); + +public: + enum Resolution { + RESOLUTION_256, + RESOLUTION_512, + RESOLUTION_1024, + RESOLUTION_2048, + RESOLUTION_4096, + RESOLUTION_8192, + RESOLUTION_MAX, + }; + + enum UpdateMode { + UPDATE_MODE_WHEN_MOVED, + UPDATE_MODE_ALWAYS, + }; + +private: + Vector3 extents = Vector3(1, 1, 1); + Resolution resolution = RESOLUTION_1024; + bool follow_camera_mode = false; + float follow_camera_push_ratio = 0.1; + + UpdateMode update_mode = UPDATE_MODE_WHEN_MOVED; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + void set_resolution(Resolution p_resolution); + Resolution get_resolution() const; + + void set_update_mode(UpdateMode p_update_mode); + UpdateMode get_update_mode() const; + + void set_follow_camera_mode(bool p_enabled); + bool is_follow_camera_mode_enabled() const; + + void set_follow_camera_push_ratio(float p_ratio); + float get_follow_camera_push_ratio() const; + + virtual AABB get_aabb() const override; + + GPUParticlesCollisionHeightField(); + ~GPUParticlesCollisionHeightField(); +}; + +VARIANT_ENUM_CAST(GPUParticlesCollisionHeightField::Resolution) +VARIANT_ENUM_CAST(GPUParticlesCollisionHeightField::UpdateMode) + +class GPUParticlesAttractor3D : public VisualInstance3D { + GDCLASS(GPUParticlesAttractor3D, VisualInstance3D); + + uint32_t cull_mask = 0xFFFFFFFF; + RID collision; + real_t strength = 1.0; + real_t attenuation = 1.0; + real_t directionality = 0.0; + +protected: + _FORCE_INLINE_ RID _get_collision() { return collision; } + static void _bind_methods(); + + GPUParticlesAttractor3D(RS::ParticlesCollisionType p_type); + +public: + void set_cull_mask(uint32_t p_cull_mask); + uint32_t get_cull_mask() const; + + void set_strength(real_t p_strength); + real_t get_strength() const; + + void set_attenuation(real_t p_attenuation); + real_t get_attenuation() const; + + void set_directionality(real_t p_directionality); + real_t get_directionality() const; + + virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); } + + ~GPUParticlesAttractor3D(); +}; + +class GPUParticlesAttractorSphere : public GPUParticlesAttractor3D { + GDCLASS(GPUParticlesAttractorSphere, GPUParticlesAttractor3D); + + real_t radius = 1.0; + +protected: + static void _bind_methods(); + +public: + void set_radius(real_t p_radius); + real_t get_radius() const; + + virtual AABB get_aabb() const override; + + GPUParticlesAttractorSphere(); + ~GPUParticlesAttractorSphere(); +}; + +class GPUParticlesAttractorBox : public GPUParticlesAttractor3D { + GDCLASS(GPUParticlesAttractorBox, GPUParticlesAttractor3D); + + Vector3 extents = Vector3(1, 1, 1); + +protected: + static void _bind_methods(); + +public: + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + virtual AABB get_aabb() const override; + + GPUParticlesAttractorBox(); + ~GPUParticlesAttractorBox(); +}; + +class GPUParticlesAttractorVectorField : public GPUParticlesAttractor3D { + GDCLASS(GPUParticlesAttractorVectorField, GPUParticlesAttractor3D); + + Vector3 extents = Vector3(1, 1, 1); + Ref<Texture3D> texture; + +protected: + static void _bind_methods(); + +public: + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + void set_texture(const Ref<Texture3D> &p_texture); + Ref<Texture3D> get_texture() const; + + virtual AABB get_aabb() const override; + + GPUParticlesAttractorVectorField(); + ~GPUParticlesAttractorVectorField(); +}; + +#endif // GPU_PARTICLES_COLLISION_3D_H |