Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Portal occlusion culling [3.4] #46130

Merged
merged 1 commit into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions core/bitfield_dynamic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*************************************************************************/
/* bitfield_dynamic.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. */
/*************************************************************************/

#include "bitfield_dynamic.h"

#include "core/os/memory.h"

#include <string.h>

void BitFieldDynamic::copy_from(const BitFieldDynamic &p_source) {
create(p_source.get_num_bits(), false);
memcpy(_data, p_source.get_data(), p_source.get_num_bytes());
}

void BitFieldDynamic::create(uint32_t p_num_bits, bool p_blank) {
// first delete any initial
destroy();

_num_bits = p_num_bits;
if (p_num_bits) {
_num_bytes = (p_num_bits / 8) + 1;
_data = (uint8_t *)memalloc(_num_bytes);

if (p_blank) {
blank(false);
}
}
}

void BitFieldDynamic::destroy() {
if (_data) {
memfree(_data);
_data = nullptr;
}

_num_bytes = 0;
_num_bits = 0;
}

void BitFieldDynamic::blank(bool p_set_or_zero) {
if (p_set_or_zero) {
memset(_data, 255, _num_bytes);
} else {
memset(_data, 0, _num_bytes);
}
}

void BitFieldDynamic::invert() {
for (uint32_t n = 0; n < _num_bytes; n++) {
_data[n] = ~_data[n];
}
}
111 changes: 111 additions & 0 deletions core/bitfield_dynamic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*************************************************************************/
/* bitfield_dynamic.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 BITFIELD_DYNAMIC_H
#define BITFIELD_DYNAMIC_H

#include "core/error_macros.h"

class BitFieldDynamic {
public:
~BitFieldDynamic() { destroy(); }

private:
// prevent copying (see effective C++ scott meyers)
// there is no implementation for copy constructor, hence compiler will complain if you try to copy
// feel free to add one if needed...
BitFieldDynamic &operator=(const BitFieldDynamic &);

public:
// create automatically blanks
void create(uint32_t p_num_bits, bool p_blank = true);
void destroy();

// public funcs
uint32_t get_num_bits() const { return _num_bits; }
uint32_t get_bit(uint32_t p_bit) const;
void set_bit(uint32_t p_bit, uint32_t p_set);
bool check_and_set(uint32_t p_bit);
void blank(bool p_set_or_zero = false);
void invert();
void copy_from(const BitFieldDynamic &p_source);

// loading / saving
uint8_t *get_data() { return _data; }
const uint8_t *get_data() const { return _data; }
uint32_t get_num_bytes() const { return _num_bytes; }

protected:
// member vars
uint8_t *_data = nullptr;
uint32_t _num_bytes = 0;
uint32_t _num_bits = 0;
};

inline uint32_t BitFieldDynamic::get_bit(uint32_t p_bit) const {
DEV_ASSERT(_data);
uint32_t byte_number = p_bit >> 3; // divide by 8
DEV_ASSERT(byte_number < _num_bytes);
uint8_t uc = _data[byte_number];
uint32_t bit_set = uc & (1 << (p_bit & 7));
return bit_set;
}

inline bool BitFieldDynamic::check_and_set(uint32_t p_bit) {
DEV_ASSERT(_data);
uint32_t byte_number = p_bit >> 3; // divide by 8
DEV_ASSERT(byte_number < _num_bytes);
uint8_t &uc = _data[byte_number];
uint32_t mask = (1 << (p_bit & 7));
uint32_t bit_set = uc & mask;
if (bit_set) {
return false;
}

// set
uc = uc | mask;
return true;
}

inline void BitFieldDynamic::set_bit(uint32_t p_bit, uint32_t p_set) {
DEV_ASSERT(_data);
uint32_t byte_number = p_bit >> 3; // divide by 8
DEV_ASSERT(byte_number < _num_bytes);
uint8_t uc = _data[byte_number];
uint32_t mask = 1 << (p_bit & 7);
if (p_set) {
uc = uc | mask;
} else {
uc &= ~mask;
}
_data[byte_number] = uc;
}

#endif
5 changes: 5 additions & 0 deletions core/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ float Engine::get_time_scale() const {
return _time_scale;
}

void Engine::set_portals_active(bool p_active) {
_portals_active = p_active;
}

Dictionary Engine::get_version_info() const {
Dictionary dict;
dict["major"] = VERSION_MAJOR;
Expand Down Expand Up @@ -224,6 +228,7 @@ Engine::Engine() {
_frame_ticks = 0;
_frame_step = 0;
editor_hint = false;
_portals_active = false;
}

Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr) :
Expand Down
3 changes: 3 additions & 0 deletions core/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class Engine {
bool _gpu_pixel_snap;
uint64_t _physics_frames;
float _physics_interpolation_fraction;
bool _portals_active;

uint64_t _idle_frames;
bool _in_physics;
Expand Down Expand Up @@ -106,6 +107,8 @@ class Engine {
Object *get_singleton_object(const String &p_name) const;

_FORCE_INLINE_ bool get_use_gpu_pixel_snap() const { return _gpu_pixel_snap; }
bool are_portals_active() const { return _portals_active; }
void set_portals_active(bool p_active);

#ifdef TOOLS_ENABLED
_FORCE_INLINE_ void set_editor_hint(bool p_enabled) { editor_hint = p_enabled; }
Expand Down
18 changes: 18 additions & 0 deletions core/error_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,24 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
} \
}

/**
* Should assert only if making a build with dev asserts.
* This should be a 'free' check for program flow and should not be needed in any releases,
* only used in dev builds.
*/
// #define DEV_ASSERTS_ENABLED
#ifdef DEV_ASSERTS_ENABLED
#define DEV_ASSERT(m_cond) \
{ \
if (unlikely(!(m_cond))) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: DEV_ASSERT failed \"" _STR(m_cond) "\" is false."); \
GENERATE_TRAP \
} \
}
#else
#define DEV_ASSERT(m_cond)
#endif

/**
* If `m_cond` evaluates to `true`, crashes the engine immediately with a generic error message.
* Only use this if there's no sensible fallback (i.e. the error is unrecoverable).
Expand Down
38 changes: 38 additions & 0 deletions core/math/aabb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,44 @@ bool AABB::operator!=(const AABB &p_rval) const {
return ((position != p_rval.position) || (size != p_rval.size));
}

bool AABB::create_from_points(const Vector<Vector3> &p_points) {
if (!p_points.size()) {
return false;
}

Vector3 begin = p_points[0];
Vector3 end = begin;

for (int n = 1; n < p_points.size(); n++) {
const Vector3 &pt = p_points[n];

if (pt.x < begin.x) {
begin.x = pt.x;
}
if (pt.y < begin.y) {
begin.y = pt.y;
}
if (pt.z < begin.z) {
begin.z = pt.z;
}

if (pt.x > end.x) {
end.x = pt.x;
}
if (pt.y > end.y) {
end.y = pt.y;
}
if (pt.z > end.z) {
end.z = pt.z;
}
}

position = begin;
size = end - begin;

return true;
}

void AABB::merge_with(const AABB &p_aabb) {
Vector3 beg_1, beg_2;
Vector3 end_1, end_2;
Expand Down
2 changes: 2 additions & 0 deletions core/math/aabb.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class AABB {
void set_position(const Vector3 &p_pos) { position = p_pos; }
const Vector3 &get_size() const { return size; }
void set_size(const Vector3 &p_size) { size = p_size; }
Vector3 get_center() const { return position + (size * 0.5); }

bool operator==(const AABB &p_rval) const;
bool operator!=(const AABB &p_rval) const;
Expand Down Expand Up @@ -98,6 +99,7 @@ class AABB {
AABB expand(const Vector3 &p_vector) const;
_FORCE_INLINE_ void project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const;
_FORCE_INLINE_ void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */
bool create_from_points(const Vector<Vector3> &p_points);

_FORCE_INLINE_ AABB abs() const {
return AABB(Vector3(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0), position.z + MIN(size.z, 0)), size.abs());
Expand Down
7 changes: 7 additions & 0 deletions core/math/face3.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class Face3 {

bool is_degenerate() const;
real_t get_area() const;
real_t get_twice_area_squared() const;

Vector3 get_median_point() const;
Vector3 get_closest_point_to(const Vector3 &p_point) const;
Expand Down Expand Up @@ -96,6 +97,12 @@ class Face3 {
}
};

inline real_t Face3::get_twice_area_squared() const {
Vector3 edge1 = vertex[1] - vertex[0];
Vector3 edge2 = vertex[2] - vertex[0];
return edge1.cross(edge2).length_squared();
}

bool Face3::intersects_aabb2(const AABB &p_aabb) const {
Vector3 perp = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]);

Expand Down
Loading