diff options
author | Juan Linietsky <reduzio@gmail.com> | 2021-09-30 14:49:11 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-30 14:49:11 -0300 |
commit | c370b4c4d06694401dda71e033286f5383f9e645 (patch) | |
tree | ba8e8e644e438c2a64a781e81ba36f84b3f5460c /modules/raycast/static_raycaster.cpp | |
parent | d2b8560d7a871a7bab27e68835f86e69e47e79ad (diff) | |
parent | 9e1810695c926286ddfe3e1614a6a54044583ac0 (diff) |
Merge pull request #52544 from JFonS/lod_fixes
Auto LOD fixes and improvements
Diffstat (limited to 'modules/raycast/static_raycaster.cpp')
-rw-r--r-- | modules/raycast/static_raycaster.cpp | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/modules/raycast/static_raycaster.cpp b/modules/raycast/static_raycaster.cpp new file mode 100644 index 0000000000..2ba65eebf8 --- /dev/null +++ b/modules/raycast/static_raycaster.cpp @@ -0,0 +1,137 @@ +/*************************************************************************/ +/* static_raycaster.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +#ifdef TOOLS_ENABLED + +#include "static_raycaster.h" + +#ifdef __SSE2__ +#include <pmmintrin.h> +#endif + +RTCDevice StaticRaycasterEmbree::embree_device; + +StaticRaycaster *StaticRaycasterEmbree::create_embree_raycaster() { + return memnew(StaticRaycasterEmbree); +} + +void StaticRaycasterEmbree::make_default_raycaster() { + create_function = create_embree_raycaster; +} + +void StaticRaycasterEmbree::free() { + if (embree_device) { + rtcReleaseDevice(embree_device); + } +} + +bool StaticRaycasterEmbree::intersect(Ray &r_ray) { + RTCIntersectContext context; + rtcInitIntersectContext(&context); + rtcIntersect1(embree_scene, &context, (RTCRayHit *)&r_ray); + return r_ray.geomID != RTC_INVALID_GEOMETRY_ID; +} + +void StaticRaycasterEmbree::intersect(Vector<Ray> &r_rays) { + Ray *rays = r_rays.ptrw(); + for (int i = 0; i < r_rays.size(); ++i) { + intersect(rays[i]); + } +} + +void StaticRaycasterEmbree::add_mesh(const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices, unsigned int p_id) { + RTCGeometry embree_mesh = rtcNewGeometry(embree_device, RTC_GEOMETRY_TYPE_TRIANGLE); + + int vertex_count = p_vertices.size(); + + Vector3 *embree_vertices = (Vector3 *)rtcSetNewGeometryBuffer(embree_mesh, RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, sizeof(Vector3), vertex_count); + memcpy(embree_vertices, p_vertices.ptr(), sizeof(Vector3) * vertex_count); + + if (p_indices.is_empty()) { + ERR_FAIL_COND(vertex_count % 3 != 0); + uint32_t *embree_triangles = (uint32_t *)rtcSetNewGeometryBuffer(embree_mesh, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(uint32_t) * 3, vertex_count / 3); + for (int i = 0; i < vertex_count; i++) { + embree_triangles[i] = i; + } + } else { + uint32_t *embree_triangles = (uint32_t *)rtcSetNewGeometryBuffer(embree_mesh, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(uint32_t) * 3, p_indices.size() / 3); + memcpy(embree_triangles, p_indices.ptr(), sizeof(uint32_t) * p_indices.size()); + } + + rtcCommitGeometry(embree_mesh); + rtcAttachGeometryByID(embree_scene, embree_mesh, p_id); + rtcReleaseGeometry(embree_mesh); +} + +void StaticRaycasterEmbree::commit() { + rtcCommitScene(embree_scene); +} + +void StaticRaycasterEmbree::set_mesh_filter(const Set<int> &p_mesh_ids) { + for (Set<int>::Element *E = p_mesh_ids.front(); E; E = E->next()) { + rtcDisableGeometry(rtcGetGeometry(embree_scene, E->get())); + } + rtcCommitScene(embree_scene); + filter_meshes = p_mesh_ids; +} + +void StaticRaycasterEmbree::clear_mesh_filter() { + for (Set<int>::Element *E = filter_meshes.front(); E; E = E->next()) { + rtcEnableGeometry(rtcGetGeometry(embree_scene, E->get())); + } + rtcCommitScene(embree_scene); + filter_meshes.clear(); +} + +void embree_error_handler(void *p_user_data, RTCError p_code, const char *p_str) { + print_error("Embree error: " + String(p_str)); +} + +StaticRaycasterEmbree::StaticRaycasterEmbree() { +#ifdef __SSE2__ + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); + _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); +#endif + + if (!embree_device) { + embree_device = rtcNewDevice(nullptr); + rtcSetDeviceErrorFunction(embree_device, &embree_error_handler, nullptr); + } + + embree_scene = rtcNewScene(embree_device); +} + +StaticRaycasterEmbree::~StaticRaycasterEmbree() { + if (embree_scene != nullptr) { + rtcReleaseScene(embree_scene); + } +} + +#endif |