mirror of
https://github.com/Relintai/voxelman.git
synced 2025-01-25 15:09:18 +01:00
Removed the classes that I got from the other voxel module. Moved the stuff that I wrote from VoxelBuffer to VoxelChunk. I'll reimplement the needed stuff myself into the chunk.
This commit is contained in:
parent
d8035c86e9
commit
5b275155c5
4
SCsub
4
SCsub
@ -2,8 +2,6 @@ Import('env')
|
|||||||
|
|
||||||
env.add_source_files(env.modules_sources,"register_types.cpp")
|
env.add_source_files(env.modules_sources,"register_types.cpp")
|
||||||
|
|
||||||
env.add_source_files(env.modules_sources,"collections/vector3i.cpp")
|
|
||||||
|
|
||||||
env.add_source_files(env.modules_sources,"library/voxelman_library.cpp")
|
env.add_source_files(env.modules_sources,"library/voxelman_library.cpp")
|
||||||
env.add_source_files(env.modules_sources,"library/voxelman_library_simple.cpp")
|
env.add_source_files(env.modules_sources,"library/voxelman_library_simple.cpp")
|
||||||
env.add_source_files(env.modules_sources,"library/voxelman_library_merger.cpp")
|
env.add_source_files(env.modules_sources,"library/voxelman_library_merger.cpp")
|
||||||
@ -20,14 +18,12 @@ env.add_source_files(env.modules_sources,"meshers/voxel_mesher_transvoxel.cpp")
|
|||||||
env.add_source_files(env.modules_sources,"meshers/voxel_mesher_transvoxel_terrarin.cpp")
|
env.add_source_files(env.modules_sources,"meshers/voxel_mesher_transvoxel_terrarin.cpp")
|
||||||
env.add_source_files(env.modules_sources,"meshers/transvoxel_tables.cpp")
|
env.add_source_files(env.modules_sources,"meshers/transvoxel_tables.cpp")
|
||||||
|
|
||||||
env.add_source_files(env.modules_sources,"world/voxel_buffer.cpp")
|
|
||||||
env.add_source_files(env.modules_sources,"world/voxel_world.cpp")
|
env.add_source_files(env.modules_sources,"world/voxel_world.cpp")
|
||||||
env.add_source_files(env.modules_sources,"world/voxel_chunk.cpp")
|
env.add_source_files(env.modules_sources,"world/voxel_chunk.cpp")
|
||||||
env.add_source_files(env.modules_sources,"world/voxel_structure.cpp")
|
env.add_source_files(env.modules_sources,"world/voxel_structure.cpp")
|
||||||
env.add_source_files(env.modules_sources,"world/environment_data.cpp")
|
env.add_source_files(env.modules_sources,"world/environment_data.cpp")
|
||||||
env.add_source_files(env.modules_sources,"world/voxel_chunk_prop_data.cpp")
|
env.add_source_files(env.modules_sources,"world/voxel_chunk_prop_data.cpp")
|
||||||
|
|
||||||
|
|
||||||
env.add_source_files(env.modules_sources,"meshers/cubic_mesher/voxel_mesher_cubic.cpp")
|
env.add_source_files(env.modules_sources,"meshers/cubic_mesher/voxel_mesher_cubic.cpp")
|
||||||
env.add_source_files(env.modules_sources,"meshers/cubic_mesher/voxel_cube_points.cpp")
|
env.add_source_files(env.modules_sources,"meshers/cubic_mesher/voxel_cube_points.cpp")
|
||||||
|
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* Voxel Tools for Godot Engine
|
|
||||||
*
|
|
||||||
* Copyright(c) 2016 Marc Gilleron
|
|
||||||
*
|
|
||||||
* 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 RECT3I_H
|
|
||||||
#define RECT3I_H
|
|
||||||
|
|
||||||
#include "vector3i.h"
|
|
||||||
#include <core/variant.h>
|
|
||||||
|
|
||||||
class Rect3i {
|
|
||||||
|
|
||||||
public:
|
|
||||||
Vector3i pos;
|
|
||||||
Vector3i size;
|
|
||||||
|
|
||||||
Rect3i() {}
|
|
||||||
|
|
||||||
Rect3i(Vector3i p_pos, Vector3i p_size) :
|
|
||||||
pos(p_pos),
|
|
||||||
size(p_size) {}
|
|
||||||
|
|
||||||
Rect3i(const Rect3i &other) :
|
|
||||||
pos(other.pos),
|
|
||||||
size(other.size) {}
|
|
||||||
|
|
||||||
static inline Rect3i from_center_extents(Vector3i center, Vector3i extents) {
|
|
||||||
return Rect3i(center - extents, 2 * extents);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Rect3i get_bounding_box(Rect3i a, Rect3i b) {
|
|
||||||
|
|
||||||
Rect3i box;
|
|
||||||
|
|
||||||
box.pos.x = MIN(a.pos.x, b.pos.x);
|
|
||||||
box.pos.y = MIN(a.pos.y, b.pos.y);
|
|
||||||
box.pos.z = MIN(a.pos.z, b.pos.z);
|
|
||||||
|
|
||||||
Vector3i max_a = a.pos + a.size;
|
|
||||||
Vector3i max_b = b.pos + b.size;
|
|
||||||
|
|
||||||
box.size.x = MAX(max_a.x, max_b.x) - box.pos.x;
|
|
||||||
box.size.y = MAX(max_a.y, max_b.y) - box.pos.y;
|
|
||||||
box.size.z = MAX(max_a.z, max_b.z) - box.pos.z;
|
|
||||||
|
|
||||||
return box;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool inline contains(Vector3i p_pos) const {
|
|
||||||
Vector3i end = pos + size;
|
|
||||||
return p_pos.x >= pos.x &&
|
|
||||||
p_pos.y >= pos.y &&
|
|
||||||
p_pos.z >= pos.z &&
|
|
||||||
p_pos.x < end.x &&
|
|
||||||
p_pos.y < end.y &&
|
|
||||||
p_pos.z < end.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
String to_string() const {
|
|
||||||
return String("(o:{0}, s:{1})").format(varray(pos.to_vec3(), size.to_vec3()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool intersects(Rect3i other) {
|
|
||||||
if (pos.x > other.pos.x + other.size.x)
|
|
||||||
return false;
|
|
||||||
if (pos.y > other.pos.y + other.size.y)
|
|
||||||
return false;
|
|
||||||
if (pos.z > other.pos.z + other.size.z)
|
|
||||||
return false;
|
|
||||||
if (other.pos.x > pos.x + size.x)
|
|
||||||
return false;
|
|
||||||
if (other.pos.y > pos.y + size.y)
|
|
||||||
return false;
|
|
||||||
if (other.pos.z > pos.z + size.z)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool operator!=(const Rect3i &a, const Rect3i &b) {
|
|
||||||
return a.pos != b.pos || a.size != b.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // RECT3I_H
|
|
210
math/vector3i.h
210
math/vector3i.h
@ -1,210 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* Voxel Tools for Godot Engine
|
|
||||||
*
|
|
||||||
* Copyright(c) 2016 Marc Gilleron
|
|
||||||
*
|
|
||||||
* 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 VOXEL_VECTOR3I_H
|
|
||||||
#define VOXEL_VECTOR3I_H
|
|
||||||
|
|
||||||
#include <core/hashfuncs.h>
|
|
||||||
#include <core/math/vector3.h>
|
|
||||||
|
|
||||||
struct Vector3i {
|
|
||||||
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
int z;
|
|
||||||
};
|
|
||||||
int coords[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i() :
|
|
||||||
x(0),
|
|
||||||
y(0),
|
|
||||||
z(0) {}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i(int xyz) :
|
|
||||||
x(xyz),
|
|
||||||
y(xyz),
|
|
||||||
z(xyz) {}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i(int px, int py, int pz) :
|
|
||||||
x(px),
|
|
||||||
y(py),
|
|
||||||
z(pz) {}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i(const Vector3i &other) {
|
|
||||||
*this = other;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i(const Vector3 &f) {
|
|
||||||
x = Math::floor(f.x);
|
|
||||||
y = Math::floor(f.y);
|
|
||||||
z = Math::floor(f.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3 to_vec3() const {
|
|
||||||
return Vector3(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ int volume() const {
|
|
||||||
return x * y * z;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ int length_sq() const {
|
|
||||||
return x * x + y * y + z * z;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ real_t length() const {
|
|
||||||
return Math::sqrt((real_t)length_sq());
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ int distance_sq(const Vector3i &other) const;
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i &operator=(const Vector3i &other) {
|
|
||||||
x = other.x;
|
|
||||||
y = other.y;
|
|
||||||
z = other.z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ void operator+=(const Vector3i &other) {
|
|
||||||
x += other.x;
|
|
||||||
y += other.y;
|
|
||||||
z += other.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ void operator-=(const Vector3i &other) {
|
|
||||||
x -= other.x;
|
|
||||||
y -= other.y;
|
|
||||||
z -= other.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i operator-() const {
|
|
||||||
return Vector3i(-x, -y, -z);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ int &operator[](unsigned int i) {
|
|
||||||
return coords[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
void clamp_to(const Vector3i min, const Vector3i max) {
|
|
||||||
if (x < min.x) x = min.x;
|
|
||||||
if (y < min.y) y = min.y;
|
|
||||||
if (z < min.z) z = min.z;
|
|
||||||
|
|
||||||
// TODO Not sure it should clamp like that...
|
|
||||||
if (x >= max.x) x = max.x - 1;
|
|
||||||
if (y >= max.y) y = max.y - 1;
|
|
||||||
if (z >= max.z) z = max.z - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ bool is_contained_in(const Vector3i &min, const Vector3i &max) {
|
|
||||||
return x >= min.x && y >= min.y && z >= min.z && x < max.x && y < max.y && z < max.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i wrap(const Vector3i &size) {
|
|
||||||
return Vector3i(
|
|
||||||
x % size.x,
|
|
||||||
y % size.y,
|
|
||||||
z % size.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sort_min_max(Vector3i &a, Vector3i &b) {
|
|
||||||
sort_min_max(a.x, b.x);
|
|
||||||
sort_min_max(a.y, b.y);
|
|
||||||
sort_min_max(a.z, b.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static _FORCE_INLINE_ void sort_min_max(int &a, int &b) {
|
|
||||||
if (a > b) {
|
|
||||||
int temp = a;
|
|
||||||
a = b;
|
|
||||||
b = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i operator+(const Vector3i a, const Vector3i &b) {
|
|
||||||
return Vector3i(a.x + b.x, a.y + b.y, a.z + b.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i operator-(const Vector3i &a, const Vector3i &b) {
|
|
||||||
return Vector3i(a.x - b.x, a.y - b.y, a.z - b.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i operator*(const Vector3i &a, const Vector3i &b) {
|
|
||||||
return Vector3i(a.x * b.x, a.y * b.y, a.z * b.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i operator*(const Vector3i &a, int n) {
|
|
||||||
return Vector3i(a.x * n, a.y * n, a.z * n);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i operator*(int n, const Vector3i &a) {
|
|
||||||
return Vector3i(a.x * n, a.y * n, a.z * n);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i operator/(const Vector3i &a, int n) {
|
|
||||||
return Vector3i(a.x / n, a.y / n, a.z / n);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ bool operator==(const Vector3i &a, const Vector3i &b) {
|
|
||||||
return a.x == b.x && a.y == b.y && a.z == b.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ bool operator!=(const Vector3i &a, const Vector3i &b) {
|
|
||||||
return a.x != b.x || a.y != b.y || a.z != b.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i operator<<(const Vector3i &a, int b) {
|
|
||||||
return Vector3i(a.x << b, a.y << b, a.z << b);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3i operator>>(const Vector3i &a, int b) {
|
|
||||||
return Vector3i(a.x >> b, a.y >> b, a.z >> b);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ bool operator<(const Vector3i &a, const Vector3i &b) {
|
|
||||||
|
|
||||||
if (a.x == b.x) {
|
|
||||||
if (a.y == b.y) {
|
|
||||||
return a.z < b.z;
|
|
||||||
} else {
|
|
||||||
return a.y < b.y;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return a.x < b.x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ int Vector3i::distance_sq(const Vector3i &other) const {
|
|
||||||
return (other - *this).length_sq();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Vector3iHasher {
|
|
||||||
static _FORCE_INLINE_ uint32_t hash(const Vector3i &v) {
|
|
||||||
uint32_t hash = hash_djb2_one_32(v.x);
|
|
||||||
hash = hash_djb2_one_32(v.y, hash);
|
|
||||||
return hash_djb2_one_32(v.z, hash);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // VOXEL_VECTOR3I_H
|
|
@ -14,7 +14,6 @@
|
|||||||
#include "meshers/voxel_mesher_transvoxel.h"
|
#include "meshers/voxel_mesher_transvoxel.h"
|
||||||
#include "meshers/voxel_mesher_transvoxel_terrarin.h"
|
#include "meshers/voxel_mesher_transvoxel_terrarin.h"
|
||||||
|
|
||||||
#include "world/voxel_buffer.h"
|
|
||||||
#include "world/voxel_world.h"
|
#include "world/voxel_world.h"
|
||||||
#include "world/voxel_chunk.h"
|
#include "world/voxel_chunk.h"
|
||||||
#include "world/voxel_structure.h"
|
#include "world/voxel_structure.h"
|
||||||
@ -56,7 +55,6 @@ void register_voxelman_types() {
|
|||||||
|
|
||||||
ClassDB::register_class<VoxelLight>();
|
ClassDB::register_class<VoxelLight>();
|
||||||
|
|
||||||
ClassDB::register_class<VoxelBuffer>();
|
|
||||||
ClassDB::register_class<VoxelWorld>();
|
ClassDB::register_class<VoxelWorld>();
|
||||||
ClassDB::register_class<VoxelChunk>();
|
ClassDB::register_class<VoxelChunk>();
|
||||||
ClassDB::register_class<VoxelStructure>();
|
ClassDB::register_class<VoxelStructure>();
|
||||||
|
@ -1,482 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* Voxel Tools for Godot Engine
|
|
||||||
*
|
|
||||||
* Copyright(c) 2016 Marc Gilleron
|
|
||||||
*
|
|
||||||
* 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 "voxel_buffer.h"
|
|
||||||
|
|
||||||
#include <core/math/math_funcs.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
const char *VoxelBuffer::CHANNEL_ID_HINT_STRING = "Type,Isolevel,Light Color R,Light Color G,Light Color B,AO,Random AO,Liquid Types,Liquid Fill,Liquid Flow";
|
|
||||||
|
|
||||||
VoxelBuffer::VoxelBuffer() {
|
|
||||||
_margin_start = 0;
|
|
||||||
_margin_end = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
VoxelBuffer::~VoxelBuffer() {
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::create(int sx, int sy, int sz, int margin_start, int margin_end) {
|
|
||||||
if (sx <= 0 || sy <= 0 || sz <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3i new_size(sx + margin_start + margin_end, sy + margin_start + margin_end, sz + margin_start + margin_end);
|
|
||||||
|
|
||||||
if (new_size != _actual_size) {
|
|
||||||
for (unsigned int i = 0; i < MAX_CHANNELS; ++i) {
|
|
||||||
Channel &channel = _channels[i];
|
|
||||||
if (channel.data) {
|
|
||||||
// Channel already contained data
|
|
||||||
// TODO Optimize with realloc
|
|
||||||
delete_channel(i);
|
|
||||||
create_channel(i, new_size, channel.defval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_actual_size = new_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
_size = Vector3i(sx, sy, sz);
|
|
||||||
_margin_start = margin_start;
|
|
||||||
_margin_end = margin_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::clear() {
|
|
||||||
for (unsigned int i = 0; i < MAX_CHANNELS; ++i) {
|
|
||||||
Channel &channel = _channels[i];
|
|
||||||
if (channel.data) {
|
|
||||||
delete_channel(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::clear_channel(unsigned int channel_index, int clear_value) {
|
|
||||||
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
|
|
||||||
if (_channels[channel_index].data) {
|
|
||||||
delete_channel(channel_index);
|
|
||||||
}
|
|
||||||
_channels[channel_index].defval = clear_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::set_default_values(uint8_t values[VoxelBuffer::MAX_CHANNELS]) {
|
|
||||||
for (unsigned int i = 0; i < MAX_CHANNELS; ++i) {
|
|
||||||
_channels[i].defval = values[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int VoxelBuffer::get_voxel(int x, int y, int z, unsigned int channel_index) const {
|
|
||||||
ERR_FAIL_INDEX_V(channel_index, MAX_CHANNELS, 0);
|
|
||||||
|
|
||||||
const Channel &channel = _channels[channel_index];
|
|
||||||
|
|
||||||
x += _margin_start;
|
|
||||||
y += _margin_start;
|
|
||||||
z += _margin_start;
|
|
||||||
|
|
||||||
if (validate_pos(x, y, z) && channel.data) {
|
|
||||||
return channel.data[index(x, y, z)];
|
|
||||||
} else {
|
|
||||||
return channel.defval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::set_voxel(int value, int x, int y, int z, unsigned int channel_index) {
|
|
||||||
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
|
|
||||||
|
|
||||||
x += _margin_start;
|
|
||||||
y += _margin_start;
|
|
||||||
z += _margin_start;
|
|
||||||
|
|
||||||
ERR_FAIL_COND(!validate_pos(x, y, z));
|
|
||||||
|
|
||||||
Channel &channel = _channels[channel_index];
|
|
||||||
|
|
||||||
if (channel.data == NULL) {
|
|
||||||
if (channel.defval != value) {
|
|
||||||
// Allocate channel with same initial values as defval
|
|
||||||
create_channel(channel_index, _actual_size, channel.defval);
|
|
||||||
channel.data[index(x, y, z)] = value;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
channel.data[index(x, y, z)] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This version does not cause errors if out of bounds. Use only if it's okay to be outside.
|
|
||||||
void VoxelBuffer::try_set_voxel(int x, int y, int z, int value, unsigned int channel_index) {
|
|
||||||
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
|
|
||||||
|
|
||||||
x += _margin_start;
|
|
||||||
y += _margin_start;
|
|
||||||
z += _margin_start;
|
|
||||||
|
|
||||||
if (!validate_pos(x, y, z)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Channel &channel = _channels[channel_index];
|
|
||||||
|
|
||||||
if (channel.data == NULL) {
|
|
||||||
if (channel.defval != value) {
|
|
||||||
create_channel(channel_index, _actual_size, channel.defval);
|
|
||||||
channel.data[index(x, y, z)] = value;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
channel.data[index(x, y, z)] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::set_voxel_v(int value, Vector3 pos, unsigned int channel_index) {
|
|
||||||
set_voxel(value, pos.x, pos.y, pos.z, channel_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::fill(int defval, unsigned int channel_index) {
|
|
||||||
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
|
|
||||||
|
|
||||||
Channel &channel = _channels[channel_index];
|
|
||||||
if (channel.data == NULL) {
|
|
||||||
// Channel is already optimized and uniform
|
|
||||||
if (channel.defval == defval) {
|
|
||||||
// No change
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// Just change default value
|
|
||||||
channel.defval = defval;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
create_channel_noinit(channel_index, _actual_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int volume = get_volume();
|
|
||||||
memset(channel.data, defval, volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::fill_area(int defval, Vector3i min, Vector3i max, unsigned int channel_index) {
|
|
||||||
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
|
|
||||||
|
|
||||||
Vector3i::sort_min_max(min, max);
|
|
||||||
|
|
||||||
min.clamp_to(Vector3i(0, 0, 0), _actual_size + Vector3i(1, 1, 1));
|
|
||||||
max.clamp_to(Vector3i(0, 0, 0), _actual_size + Vector3i(1, 1, 1));
|
|
||||||
Vector3i area_size = max - min;
|
|
||||||
|
|
||||||
if (area_size.x == 0 || area_size.y == 0 || area_size.z == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Channel &channel = _channels[channel_index];
|
|
||||||
if (channel.data == NULL) {
|
|
||||||
if (channel.defval == defval) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
create_channel(channel_index, _actual_size, channel.defval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3i pos;
|
|
||||||
int volume = get_volume();
|
|
||||||
for (pos.z = min.z; pos.z < max.z; ++pos.z) {
|
|
||||||
for (pos.x = min.x; pos.x < max.x; ++pos.x) {
|
|
||||||
unsigned int dst_ri = index(pos.x, pos.y + min.y, pos.z);
|
|
||||||
CRASH_COND(dst_ri >= volume);
|
|
||||||
memset(&channel.data[dst_ri], defval, area_size.y * sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VoxelBuffer::is_uniform(unsigned int channel_index) const {
|
|
||||||
ERR_FAIL_INDEX_V(channel_index, MAX_CHANNELS, true);
|
|
||||||
|
|
||||||
const Channel &channel = _channels[channel_index];
|
|
||||||
if (channel.data == NULL) {
|
|
||||||
// Channel has been optimized
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Channel isn't optimized, so must look at each voxel
|
|
||||||
uint8_t voxel = channel.data[0];
|
|
||||||
unsigned int volume = get_volume();
|
|
||||||
for (unsigned int i = 1; i < volume; ++i) {
|
|
||||||
if (channel.data[i] != voxel) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::compress_uniform_channels() {
|
|
||||||
for (unsigned int i = 0; i < MAX_CHANNELS; ++i) {
|
|
||||||
if (_channels[i].data && is_uniform(i)) {
|
|
||||||
clear_channel(i, _channels[i].data[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::copy_from(const VoxelBuffer &other, unsigned int channel_index) {
|
|
||||||
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
|
|
||||||
ERR_FAIL_COND(other._actual_size == _actual_size);
|
|
||||||
|
|
||||||
Channel &channel = _channels[channel_index];
|
|
||||||
const Channel &other_channel = other._channels[channel_index];
|
|
||||||
|
|
||||||
if (other_channel.data) {
|
|
||||||
if (channel.data == NULL) {
|
|
||||||
create_channel_noinit(channel_index, _actual_size);
|
|
||||||
}
|
|
||||||
memcpy(channel.data, other_channel.data, get_volume() * sizeof(uint8_t));
|
|
||||||
} else if (channel.data) {
|
|
||||||
delete_channel(channel_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
channel.defval = other_channel.defval;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::copy_from(const VoxelBuffer &other, Vector3i src_min, Vector3i src_max, Vector3i dst_min, unsigned int channel_index) {
|
|
||||||
|
|
||||||
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
|
|
||||||
|
|
||||||
Channel &channel = _channels[channel_index];
|
|
||||||
const Channel &other_channel = other._channels[channel_index];
|
|
||||||
|
|
||||||
Vector3i::sort_min_max(src_min, src_max);
|
|
||||||
|
|
||||||
src_min.clamp_to(Vector3i(0, 0, 0), other._actual_size);
|
|
||||||
src_max.clamp_to(Vector3i(0, 0, 0), other._actual_size + Vector3i(1, 1, 1));
|
|
||||||
|
|
||||||
dst_min.clamp_to(Vector3i(0, 0, 0), _actual_size);
|
|
||||||
Vector3i area_size = src_max - src_min;
|
|
||||||
//Vector3i dst_max = dst_min + area_size;
|
|
||||||
|
|
||||||
if (area_size == _actual_size) {
|
|
||||||
copy_from(other, channel_index);
|
|
||||||
} else {
|
|
||||||
if (other_channel.data) {
|
|
||||||
if (channel.data == NULL) {
|
|
||||||
create_channel(channel_index, _actual_size, channel.defval);
|
|
||||||
}
|
|
||||||
// Copy row by row
|
|
||||||
Vector3i pos;
|
|
||||||
for (pos.z = 0; pos.z < area_size.z; ++pos.z) {
|
|
||||||
for (pos.x = 0; pos.x < area_size.x; ++pos.x) {
|
|
||||||
// Row direction is Y
|
|
||||||
unsigned int src_ri = other.index(pos.x + src_min.x, pos.y + src_min.y, pos.z + src_min.z);
|
|
||||||
unsigned int dst_ri = index(pos.x + dst_min.x, pos.y + dst_min.y, pos.z + dst_min.z);
|
|
||||||
memcpy(&channel.data[dst_ri], &other_channel.data[src_ri], area_size.y * sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (channel.defval != other_channel.defval) {
|
|
||||||
if (channel.data == NULL) {
|
|
||||||
create_channel(channel_index, _actual_size, channel.defval);
|
|
||||||
}
|
|
||||||
// Set row by row
|
|
||||||
Vector3i pos;
|
|
||||||
for (pos.z = 0; pos.z < area_size.z; ++pos.z) {
|
|
||||||
for (pos.x = 0; pos.x < area_size.x; ++pos.x) {
|
|
||||||
unsigned int dst_ri = index(pos.x + dst_min.x, pos.y + dst_min.y, pos.z + dst_min.z);
|
|
||||||
memset(&channel.data[dst_ri], other_channel.defval, area_size.y * sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *VoxelBuffer::get_channel_raw(unsigned int channel_index) const {
|
|
||||||
ERR_FAIL_INDEX_V(channel_index, MAX_CHANNELS, NULL);
|
|
||||||
const Channel &channel = _channels[channel_index];
|
|
||||||
return channel.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::generate_ao() {
|
|
||||||
unsigned int size_x = _actual_size.x;
|
|
||||||
unsigned int size_y = _actual_size.y;
|
|
||||||
unsigned int size_z = _actual_size.z;
|
|
||||||
|
|
||||||
ERR_FAIL_COND(size_x == 0 || size_y == 0 || size_z == 0);
|
|
||||||
|
|
||||||
for (unsigned int y = 1; y < size_y - 1; ++y) {
|
|
||||||
for (unsigned int z = 1; z < size_z - 1; ++z) {
|
|
||||||
for (unsigned int x = 1; x < size_x - 1; ++x) {
|
|
||||||
int current = get_voxel(x, y, z, CHANNEL_ISOLEVEL);
|
|
||||||
|
|
||||||
int sum = get_voxel(x + 1, y, z, CHANNEL_ISOLEVEL);
|
|
||||||
sum += get_voxel(x - 1, y, z, CHANNEL_ISOLEVEL);
|
|
||||||
sum += get_voxel(x, y + 1, z, CHANNEL_ISOLEVEL);
|
|
||||||
sum += get_voxel(x, y - 1, z, CHANNEL_ISOLEVEL);
|
|
||||||
sum += get_voxel(x, y, z + 1, CHANNEL_ISOLEVEL);
|
|
||||||
sum += get_voxel(x, y, z - 1, CHANNEL_ISOLEVEL);
|
|
||||||
|
|
||||||
sum /= 6;
|
|
||||||
|
|
||||||
sum -= current;
|
|
||||||
|
|
||||||
if (sum < 0)
|
|
||||||
sum = 0;
|
|
||||||
|
|
||||||
set_voxel(sum, x, y, z, CHANNEL_AO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::add_light(int local_x, int local_y, int local_z, int size, Color color) {
|
|
||||||
ERR_FAIL_COND(size < 0);
|
|
||||||
|
|
||||||
int size_x = _actual_size.x;
|
|
||||||
int size_y = _actual_size.y;
|
|
||||||
int size_z = _actual_size.z;
|
|
||||||
|
|
||||||
float sizef = static_cast<float>(size);
|
|
||||||
//float rf = (color.r / sizef);
|
|
||||||
//float gf = (color.g / sizef);
|
|
||||||
//float bf = (color.b / sizef);
|
|
||||||
|
|
||||||
for (int y = local_y - size; y <= local_y + size; ++y) {
|
|
||||||
if (y < 0 || y >= size_y)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (int z = local_z - size; z <= local_z + size; ++z) {
|
|
||||||
if (z < 0 || z >= size_z)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (int x = local_x - size; x <= local_x + size; ++x) {
|
|
||||||
if (x < 0 || x >= size_x)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int lx = x - local_x;
|
|
||||||
int ly = y - local_y;
|
|
||||||
int lz = z - local_z;
|
|
||||||
|
|
||||||
float str = size - (((float)lx * lx + ly * ly + lz * lz));
|
|
||||||
str /= size;
|
|
||||||
|
|
||||||
if (str < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int r = color.r * str * 255.0;
|
|
||||||
int g = color.g * str * 255.0;
|
|
||||||
int b = color.b * str * 255.0;
|
|
||||||
|
|
||||||
r += get_voxel(x, y, z, CHANNEL_LIGHT_COLOR_R);
|
|
||||||
g += get_voxel(x, y, z, CHANNEL_LIGHT_COLOR_G);
|
|
||||||
b += get_voxel(x, y, z, CHANNEL_LIGHT_COLOR_B);
|
|
||||||
|
|
||||||
if (r > 255)
|
|
||||||
r = 255;
|
|
||||||
|
|
||||||
if (g > 255)
|
|
||||||
g = 255;
|
|
||||||
|
|
||||||
if (b > 255)
|
|
||||||
b = 255;
|
|
||||||
|
|
||||||
set_voxel(r, x, y, z, CHANNEL_LIGHT_COLOR_R);
|
|
||||||
set_voxel(g, x, y, z, CHANNEL_LIGHT_COLOR_G);
|
|
||||||
set_voxel(b, x, y, z, CHANNEL_LIGHT_COLOR_B);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void VoxelBuffer::clear_lights() {
|
|
||||||
fill(0, CHANNEL_LIGHT_COLOR_R);
|
|
||||||
fill(0, CHANNEL_LIGHT_COLOR_G);
|
|
||||||
fill(0, CHANNEL_LIGHT_COLOR_B);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::create_channel(int i, Vector3i size, uint8_t defval) {
|
|
||||||
create_channel_noinit(i, size);
|
|
||||||
memset(_channels[i].data, defval, get_volume() * sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::create_channel_noinit(int i, Vector3i size) {
|
|
||||||
Channel &channel = _channels[i];
|
|
||||||
unsigned int volume = size.x * size.y * size.z;
|
|
||||||
channel.data = (uint8_t *)memalloc(volume * sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::delete_channel(int i) {
|
|
||||||
Channel &channel = _channels[i];
|
|
||||||
ERR_FAIL_COND(channel.data == NULL);
|
|
||||||
memfree(channel.data);
|
|
||||||
channel.data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::_bind_methods() {
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("create", "sx", "sy", "sz", "margin_start", "margin_end"), &VoxelBuffer::create, DEFVAL(0), DEFVAL(0));
|
|
||||||
ClassDB::bind_method(D_METHOD("clear"), &VoxelBuffer::clear);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_margin_start"), &VoxelBuffer::get_margin_start);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_margin_end"), &VoxelBuffer::get_margin_end);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_size"), &VoxelBuffer::_get_size_binding);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_size_x"), &VoxelBuffer::get_size_x);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_size_y"), &VoxelBuffer::get_size_y);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_size_z"), &VoxelBuffer::get_size_z);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_actual_size"), &VoxelBuffer::_get_actual_size_binding);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_actual_size_x"), &VoxelBuffer::get_actual_size_x);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_actual_size_y"), &VoxelBuffer::get_actual_size_y);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_actual_size_z"), &VoxelBuffer::get_actual_size_z);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_voxel", "value", "x", "y", "z", "channel"), &VoxelBuffer::_set_voxel_binding, DEFVAL(0));
|
|
||||||
ClassDB::bind_method(D_METHOD("set_voxel_f", "value", "x", "y", "z", "channel"), &VoxelBuffer::_set_voxel_f_binding, DEFVAL(0));
|
|
||||||
ClassDB::bind_method(D_METHOD("set_voxel_v", "value", "pos", "channel"), &VoxelBuffer::set_voxel_v, DEFVAL(0));
|
|
||||||
ClassDB::bind_method(D_METHOD("get_voxel", "x", "y", "z", "channel"), &VoxelBuffer::_get_voxel_binding, DEFVAL(0));
|
|
||||||
ClassDB::bind_method(D_METHOD("get_voxel_f", "x", "y", "z", "channel"), &VoxelBuffer::get_voxel_f, DEFVAL(0));
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("fill", "value", "channel"), &VoxelBuffer::fill, DEFVAL(0));
|
|
||||||
ClassDB::bind_method(D_METHOD("fill_f", "value", "channel"), &VoxelBuffer::fill_f, DEFVAL(0));
|
|
||||||
ClassDB::bind_method(D_METHOD("fill_area", "value", "min", "max", "channel"), &VoxelBuffer::_fill_area_binding, DEFVAL(0));
|
|
||||||
ClassDB::bind_method(D_METHOD("copy_from", "other", "channel"), &VoxelBuffer::_copy_from_binding, DEFVAL(0));
|
|
||||||
ClassDB::bind_method(D_METHOD("copy_from_area", "other", "src_min", "src_max", "dst_min", "channel"), &VoxelBuffer::_copy_from_area_binding, DEFVAL(0));
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("is_uniform", "channel"), &VoxelBuffer::is_uniform);
|
|
||||||
ClassDB::bind_method(D_METHOD("optimize"), &VoxelBuffer::compress_uniform_channels);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("generate_ao"), &VoxelBuffer::generate_ao);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("add_light", "local_x", "local_y", "local_z", "size", "color"), &VoxelBuffer::add_light);
|
|
||||||
ClassDB::bind_method(D_METHOD("clear_lights"), &VoxelBuffer::clear_lights);
|
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(CHANNEL_TYPE);
|
|
||||||
BIND_ENUM_CONSTANT(CHANNEL_ISOLEVEL);
|
|
||||||
BIND_ENUM_CONSTANT(CHANNEL_LIGHT_COLOR_R);
|
|
||||||
BIND_ENUM_CONSTANT(CHANNEL_LIGHT_COLOR_G);
|
|
||||||
BIND_ENUM_CONSTANT(CHANNEL_LIGHT_COLOR_B);
|
|
||||||
BIND_ENUM_CONSTANT(CHANNEL_AO);
|
|
||||||
BIND_ENUM_CONSTANT(CHANNEL_RANDOM_AO);
|
|
||||||
BIND_ENUM_CONSTANT(CHANNEL_LIQUID_TYPES);
|
|
||||||
BIND_ENUM_CONSTANT(CHANNEL_LIQUID_FILL);
|
|
||||||
BIND_ENUM_CONSTANT(CHANNEL_LIQUID_FLOW);
|
|
||||||
BIND_ENUM_CONSTANT(MAX_CHANNELS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::_copy_from_binding(Ref<VoxelBuffer> other, unsigned int channel) {
|
|
||||||
ERR_FAIL_COND(other.is_null());
|
|
||||||
copy_from(**other, channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoxelBuffer::_copy_from_area_binding(Ref<VoxelBuffer> other, Vector3 src_min, Vector3 src_max, Vector3 dst_min, unsigned int channel) {
|
|
||||||
ERR_FAIL_COND(other.is_null());
|
|
||||||
copy_from(**other, Vector3i(src_min), Vector3i(src_max), Vector3i(dst_min), channel);
|
|
||||||
}
|
|
@ -1,190 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* Voxel Tools for Godot Engine
|
|
||||||
*
|
|
||||||
* Copyright(c) 2016 Marc Gilleron
|
|
||||||
*
|
|
||||||
* 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 VOXEL_BUFFER_H
|
|
||||||
#define VOXEL_BUFFER_H
|
|
||||||
|
|
||||||
#include "../math/vector3i.h"
|
|
||||||
#include "core/reference.h"
|
|
||||||
#include "core/vector.h"
|
|
||||||
|
|
||||||
// Dense voxels data storage.
|
|
||||||
// Organized in 8-bit channels like images, all optional.
|
|
||||||
// Note: for float storage (marching cubes for example), you can map [0..256] to [0..1] and save 3 bytes per cell
|
|
||||||
|
|
||||||
class VoxelBuffer : public Reference {
|
|
||||||
GDCLASS(VoxelBuffer, Reference)
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum ChannelId {
|
|
||||||
CHANNEL_TYPE = 0,
|
|
||||||
CHANNEL_ISOLEVEL,
|
|
||||||
CHANNEL_LIGHT_COLOR_R,
|
|
||||||
CHANNEL_LIGHT_COLOR_G,
|
|
||||||
CHANNEL_LIGHT_COLOR_B,
|
|
||||||
CHANNEL_AO,
|
|
||||||
CHANNEL_RANDOM_AO,
|
|
||||||
CHANNEL_LIQUID_TYPES,
|
|
||||||
CHANNEL_LIQUID_FILL,
|
|
||||||
CHANNEL_LIQUID_FLOW,
|
|
||||||
// Arbitrary value, 8 should be enough. Tweak for your needs.
|
|
||||||
MAX_CHANNELS
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO use C++17 inline to initialize right here...
|
|
||||||
static const char *CHANNEL_ID_HINT_STRING;
|
|
||||||
|
|
||||||
// TODO Quantification options
|
|
||||||
// enum ChannelFormat {
|
|
||||||
// FORMAT_I8_Q256U, // 0..255 integer
|
|
||||||
// FORMAT_F8_Q1S, // -1..1 float stored in 8 bits
|
|
||||||
// FORMAT_F16_Q128S // -128..128 float stored in 16 bits
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Converts -1..1 float into 0..255 integer
|
|
||||||
static inline int iso_to_byte(real_t iso) {
|
|
||||||
int v = static_cast<int>(128.f * iso + 128.f);
|
|
||||||
if (v > 255)
|
|
||||||
return 255;
|
|
||||||
else if (v < 0)
|
|
||||||
return 0;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts 0..255 integer into -1..1 float
|
|
||||||
static inline real_t byte_to_iso(int b) {
|
|
||||||
return static_cast<float>(b - 128) / 128.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ int get_margin_start() const { return _margin_start; }
|
|
||||||
_FORCE_INLINE_ int get_margin_end() const { return _margin_end; }
|
|
||||||
|
|
||||||
void create(int sx, int sy, int sz, int margin_start = 0, int margin_end = 0);
|
|
||||||
void clear();
|
|
||||||
void clear_channel(unsigned int channel_index, int clear_value = 0);
|
|
||||||
_FORCE_INLINE_ void clear_channel_f(unsigned int channel_index, float clear_value = 0) { clear_channel(channel_index, iso_to_byte(clear_value)); }
|
|
||||||
|
|
||||||
_FORCE_INLINE_ const Vector3i &get_size() const { return _size; }
|
|
||||||
_FORCE_INLINE_ const Vector3i &get_actual_size() const { return _actual_size; }
|
|
||||||
|
|
||||||
void set_default_values(uint8_t values[MAX_CHANNELS]);
|
|
||||||
|
|
||||||
int get_voxel(int x, int y, int z, unsigned int channel_index = 0) const;
|
|
||||||
void set_voxel(int value, int x, int y, int z, unsigned int channel_index = 0);
|
|
||||||
void set_voxel_v(int value, Vector3 pos, unsigned int channel_index = 0);
|
|
||||||
|
|
||||||
void try_set_voxel(int x, int y, int z, int value, unsigned int channel_index = 0);
|
|
||||||
|
|
||||||
_FORCE_INLINE_ void set_voxel_f(real_t value, int x, int y, int z, unsigned int channel_index = 0) { set_voxel(iso_to_byte(value), x, y, z, channel_index); }
|
|
||||||
_FORCE_INLINE_ real_t get_voxel_f(int x, int y, int z, unsigned int channel_index = 0) const { return byte_to_iso(get_voxel(x, y, z, channel_index)); }
|
|
||||||
|
|
||||||
_FORCE_INLINE_ int get_voxel(const Vector3i pos, unsigned int channel_index = 0) const { return get_voxel(pos.x, pos.y, pos.z, channel_index); }
|
|
||||||
_FORCE_INLINE_ void set_voxel(int value, const Vector3i pos, unsigned int channel_index = 0) { set_voxel(value, pos.x, pos.y, pos.z, channel_index); }
|
|
||||||
|
|
||||||
void fill(int defval, unsigned int channel_index = 0);
|
|
||||||
_FORCE_INLINE_ void fill_f(float value, unsigned int channel = 0) { fill(iso_to_byte(value), channel); }
|
|
||||||
void fill_area(int defval, Vector3i min, Vector3i max, unsigned int channel_index = 0);
|
|
||||||
|
|
||||||
bool is_uniform(unsigned int channel_index) const;
|
|
||||||
|
|
||||||
void compress_uniform_channels();
|
|
||||||
|
|
||||||
void copy_from(const VoxelBuffer &other, unsigned int channel_index = 0);
|
|
||||||
void copy_from(const VoxelBuffer &other, Vector3i src_min, Vector3i src_max, Vector3i dst_min, unsigned int channel_index = 0);
|
|
||||||
|
|
||||||
_FORCE_INLINE_ bool validate_pos(unsigned int x, unsigned int y, unsigned int z) const {
|
|
||||||
return x < _actual_size.x && y < _actual_size.y && z < _actual_size.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ unsigned int index(unsigned int x, unsigned int y, unsigned int z) const {
|
|
||||||
return y + _actual_size.y * (x + _actual_size.x * z);
|
|
||||||
}
|
|
||||||
|
|
||||||
// _FORCE_INLINE_ unsigned int row_index(unsigned int x, unsigned int y, unsigned int z) const {
|
|
||||||
// return _actual_size.y * (x + _actual_size.x * z);
|
|
||||||
// }
|
|
||||||
|
|
||||||
_FORCE_INLINE_ unsigned int get_volume() const {
|
|
||||||
return _actual_size.x * _actual_size.y * _actual_size.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *get_channel_raw(unsigned int channel_index) const;
|
|
||||||
|
|
||||||
void generate_ao();
|
|
||||||
|
|
||||||
void add_light(int local_x, int local_y, int local_z, int size, Color color);
|
|
||||||
void clear_lights();
|
|
||||||
|
|
||||||
VoxelBuffer();
|
|
||||||
~VoxelBuffer();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void create_channel_noinit(int i, Vector3i size);
|
|
||||||
void create_channel(int i, Vector3i size, uint8_t defval);
|
|
||||||
void delete_channel(int i);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
_FORCE_INLINE_ int get_size_x() const { return _size.x; }
|
|
||||||
_FORCE_INLINE_ int get_size_y() const { return _size.y; }
|
|
||||||
_FORCE_INLINE_ int get_size_z() const { return _size.z; }
|
|
||||||
_FORCE_INLINE_ Vector3 _get_size_binding() const { return _size.to_vec3(); }
|
|
||||||
|
|
||||||
_FORCE_INLINE_ int get_actual_size_x() const { return _actual_size.x; }
|
|
||||||
_FORCE_INLINE_ int get_actual_size_y() const { return _actual_size.y; }
|
|
||||||
_FORCE_INLINE_ int get_actual_size_z() const { return _actual_size.z; }
|
|
||||||
_FORCE_INLINE_ Vector3 _get_actual_size_binding() const { return _actual_size.to_vec3(); }
|
|
||||||
|
|
||||||
_FORCE_INLINE_ int _get_voxel_binding(int x, int y, int z, unsigned int channel) const { return get_voxel(x, y, z, channel); }
|
|
||||||
_FORCE_INLINE_ void _set_voxel_binding(int value, int x, int y, int z, unsigned int channel) { set_voxel(value, x, y, z, channel); }
|
|
||||||
void _copy_from_binding(Ref<VoxelBuffer> other, unsigned int channel);
|
|
||||||
void _copy_from_area_binding(Ref<VoxelBuffer> other, Vector3 src_min, Vector3 src_max, Vector3 dst_min, unsigned int channel);
|
|
||||||
_FORCE_INLINE_ void _fill_area_binding(int defval, Vector3 min, Vector3 max, unsigned int channel_index) { fill_area(defval, Vector3i(min), Vector3i(max), channel_index); }
|
|
||||||
_FORCE_INLINE_ void _set_voxel_f_binding(real_t value, int x, int y, int z, unsigned int channel) { set_voxel_f(value, x, y, z, channel); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Channel {
|
|
||||||
// Allocated when the channel is populated.
|
|
||||||
// Flat array, in order [z][x][y] because it allows faster vertical-wise access (the engine is Y-up).
|
|
||||||
uint8_t *data;
|
|
||||||
|
|
||||||
// Default value when data is null
|
|
||||||
uint8_t defval;
|
|
||||||
|
|
||||||
Channel() :
|
|
||||||
data(NULL),
|
|
||||||
defval(0) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Each channel can store arbitary data.
|
|
||||||
// For example, you can decide to store colors (R, G, B, A), gameplay types (type, state, light) or both.
|
|
||||||
Channel _channels[MAX_CHANNELS];
|
|
||||||
|
|
||||||
// How many voxels are there in the three directions. All populated channels have the same size.
|
|
||||||
Vector3i _size;
|
|
||||||
Vector3i _actual_size;
|
|
||||||
|
|
||||||
uint32_t _margin_start;
|
|
||||||
uint32_t _margin_end;
|
|
||||||
};
|
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(VoxelBuffer::ChannelId)
|
|
||||||
|
|
||||||
#endif // VOXEL_BUFFER_H
|
|
@ -2,78 +2,108 @@
|
|||||||
|
|
||||||
#include "voxel_world.h"
|
#include "voxel_world.h"
|
||||||
|
|
||||||
bool VoxelChunk::get_dirty() const {
|
_FORCE_INLINE_ bool VoxelChunk::get_dirty() const {
|
||||||
return _dirty;
|
return _dirty;
|
||||||
}
|
}
|
||||||
void VoxelChunk::set_dirty(bool value) {
|
_FORCE_INLINE_ void VoxelChunk::set_dirty(bool value) {
|
||||||
_dirty = value;
|
_dirty = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelChunk::get_state() const {
|
_FORCE_INLINE_ int VoxelChunk::get_state() const {
|
||||||
return _state;
|
return _state;
|
||||||
}
|
}
|
||||||
void VoxelChunk::set_state(int value) {
|
_FORCE_INLINE_ void VoxelChunk::set_state(int value) {
|
||||||
_state = value;
|
_state = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelChunk::get_chunk_position_x() {
|
_FORCE_INLINE_ int VoxelChunk::get_chunk_position_x() {
|
||||||
return _chunk_position.x;
|
return _chunk_position_x;
|
||||||
}
|
}
|
||||||
void VoxelChunk::set_chunk_position_x(int value) {
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_position_x(int value) {
|
||||||
_chunk_position.x = value;
|
_chunk_position_x = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelChunk::get_chunk_position_y() {
|
_FORCE_INLINE_ int VoxelChunk::get_chunk_position_y() {
|
||||||
return _chunk_position.y;
|
return _chunk_position_y;
|
||||||
}
|
}
|
||||||
void VoxelChunk::set_chunk_position_y(int value) {
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_position_y(int value) {
|
||||||
_chunk_position.y = value;
|
_chunk_position_y = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelChunk::get_chunk_position_z() {
|
_FORCE_INLINE_ int VoxelChunk::get_chunk_position_z() {
|
||||||
return _chunk_position.z;
|
return _chunk_position_z;
|
||||||
}
|
}
|
||||||
void VoxelChunk::set_chunk_position_z(int value) {
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_position_z(int value) {
|
||||||
_chunk_position.z = value;
|
_chunk_position_z = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3i VoxelChunk::get_chunk_position() const {
|
_FORCE_INLINE_ Vector3 VoxelChunk::get_chunk_position() const {
|
||||||
return _chunk_position;
|
return Vector3(_chunk_position_x, _chunk_position_y, _chunk_position_z);
|
||||||
}
|
}
|
||||||
void VoxelChunk::set_chunk_position(int x, int y, int z) {
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_position(int x, int y, int z) {
|
||||||
_chunk_position.x = x;
|
_chunk_position_x = x;
|
||||||
_chunk_position.y = y;
|
_chunk_position_y = y;
|
||||||
_chunk_position.z = z;
|
_chunk_position_z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelChunk::get_chunk_size_x() {
|
_FORCE_INLINE_ int VoxelChunk::get_chunk_size_x() {
|
||||||
return _chunk_size.x;
|
return _chunk_size_x;
|
||||||
}
|
}
|
||||||
void VoxelChunk::set_chunk_size_x(int value) {
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_size_x(int value) {
|
||||||
_chunk_size.x = value;
|
_chunk_size_x = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelChunk::get_chunk_size_y() {
|
_FORCE_INLINE_ int VoxelChunk::get_chunk_size_y() {
|
||||||
return _chunk_size.y;
|
return _chunk_size_y;
|
||||||
}
|
}
|
||||||
void VoxelChunk::set_chunk_size_y(int value) {
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_size_y(int value) {
|
||||||
_chunk_size.y = value;
|
_chunk_size_y = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelChunk::get_chunk_size_z() {
|
_FORCE_INLINE_ int VoxelChunk::get_chunk_size_z() {
|
||||||
return _chunk_size.z;
|
return _chunk_size_z;
|
||||||
}
|
}
|
||||||
void VoxelChunk::set_chunk_size_z(int value) {
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_size_z(int value) {
|
||||||
_chunk_size.z = value;
|
_chunk_size_z = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3i VoxelChunk::get_chunk_size() const {
|
_FORCE_INLINE_ Vector3 VoxelChunk::get_chunk_size() const {
|
||||||
return _chunk_size;
|
return Vector3(_chunk_size_x, _chunk_size_y, _chunk_size_z);
|
||||||
}
|
}
|
||||||
void VoxelChunk::set_chunk_size(int x, int y, int z) {
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_size(int x, int y, int z) {
|
||||||
_chunk_size.x = x;
|
_chunk_size_x = x;
|
||||||
_chunk_size.y = y;
|
_chunk_size_y = y;
|
||||||
_chunk_size.z = z;
|
_chunk_size_z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int VoxelChunk::get_chunk_data_size_x() {
|
||||||
|
return _chunk_data_size_x;
|
||||||
|
}
|
||||||
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_data_size_x(int value) {
|
||||||
|
_chunk_data_size_x = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int VoxelChunk::get_chunk_data_size_y() {
|
||||||
|
return _chunk_data_size_y;
|
||||||
|
}
|
||||||
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_data_size_y(int value) {
|
||||||
|
_chunk_data_size_y = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int VoxelChunk::get_chunk_data_size_z() {
|
||||||
|
return _chunk_data_size_z;
|
||||||
|
}
|
||||||
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_data_size_z(int value) {
|
||||||
|
_chunk_data_size_z = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Vector3 VoxelChunk::get_chunk_data_size() const {
|
||||||
|
return Vector3(_chunk_data_size_x, _chunk_data_size_y, _chunk_data_size_z);
|
||||||
|
}
|
||||||
|
_FORCE_INLINE_ void VoxelChunk::set_chunk_data_size(int x, int y, int z) {
|
||||||
|
_chunk_data_size_x = x;
|
||||||
|
_chunk_data_size_y = y;
|
||||||
|
_chunk_data_size_z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<VoxelmanLibrary> VoxelChunk::get_library() {
|
Ref<VoxelmanLibrary> VoxelChunk::get_library() {
|
||||||
@ -192,6 +222,102 @@ RID VoxelChunk::get_clutter_mesh_instance_rid() {
|
|||||||
return _clutter_mesh_instance_rid;
|
return _clutter_mesh_instance_rid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoxelBuffer::generate_ao() {
|
||||||
|
unsigned int size_x = _actual_size.x;
|
||||||
|
unsigned int size_y = _actual_size.y;
|
||||||
|
unsigned int size_z = _actual_size.z;
|
||||||
|
|
||||||
|
ERR_FAIL_COND(size_x == 0 || size_y == 0 || size_z == 0);
|
||||||
|
|
||||||
|
for (unsigned int y = 1; y < size_y - 1; ++y) {
|
||||||
|
for (unsigned int z = 1; z < size_z - 1; ++z) {
|
||||||
|
for (unsigned int x = 1; x < size_x - 1; ++x) {
|
||||||
|
int current = get_voxel(x, y, z, CHANNEL_ISOLEVEL);
|
||||||
|
|
||||||
|
int sum = get_voxel(x + 1, y, z, CHANNEL_ISOLEVEL);
|
||||||
|
sum += get_voxel(x - 1, y, z, CHANNEL_ISOLEVEL);
|
||||||
|
sum += get_voxel(x, y + 1, z, CHANNEL_ISOLEVEL);
|
||||||
|
sum += get_voxel(x, y - 1, z, CHANNEL_ISOLEVEL);
|
||||||
|
sum += get_voxel(x, y, z + 1, CHANNEL_ISOLEVEL);
|
||||||
|
sum += get_voxel(x, y, z - 1, CHANNEL_ISOLEVEL);
|
||||||
|
|
||||||
|
sum /= 6;
|
||||||
|
|
||||||
|
sum -= current;
|
||||||
|
|
||||||
|
if (sum < 0)
|
||||||
|
sum = 0;
|
||||||
|
|
||||||
|
set_voxel(sum, x, y, z, CHANNEL_AO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelBuffer::add_light(int local_x, int local_y, int local_z, int size, Color color) {
|
||||||
|
ERR_FAIL_COND(size < 0);
|
||||||
|
|
||||||
|
int size_x = _actual_size.x;
|
||||||
|
int size_y = _actual_size.y;
|
||||||
|
int size_z = _actual_size.z;
|
||||||
|
|
||||||
|
float sizef = static_cast<float>(size);
|
||||||
|
//float rf = (color.r / sizef);
|
||||||
|
//float gf = (color.g / sizef);
|
||||||
|
//float bf = (color.b / sizef);
|
||||||
|
|
||||||
|
for (int y = local_y - size; y <= local_y + size; ++y) {
|
||||||
|
if (y < 0 || y >= size_y)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int z = local_z - size; z <= local_z + size; ++z) {
|
||||||
|
if (z < 0 || z >= size_z)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int x = local_x - size; x <= local_x + size; ++x) {
|
||||||
|
if (x < 0 || x >= size_x)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int lx = x - local_x;
|
||||||
|
int ly = y - local_y;
|
||||||
|
int lz = z - local_z;
|
||||||
|
|
||||||
|
float str = size - (((float)lx * lx + ly * ly + lz * lz));
|
||||||
|
str /= size;
|
||||||
|
|
||||||
|
if (str < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int r = color.r * str * 255.0;
|
||||||
|
int g = color.g * str * 255.0;
|
||||||
|
int b = color.b * str * 255.0;
|
||||||
|
|
||||||
|
r += get_voxel(x, y, z, CHANNEL_LIGHT_COLOR_R);
|
||||||
|
g += get_voxel(x, y, z, CHANNEL_LIGHT_COLOR_G);
|
||||||
|
b += get_voxel(x, y, z, CHANNEL_LIGHT_COLOR_B);
|
||||||
|
|
||||||
|
if (r > 255)
|
||||||
|
r = 255;
|
||||||
|
|
||||||
|
if (g > 255)
|
||||||
|
g = 255;
|
||||||
|
|
||||||
|
if (b > 255)
|
||||||
|
b = 255;
|
||||||
|
|
||||||
|
set_voxel(r, x, y, z, CHANNEL_LIGHT_COLOR_R);
|
||||||
|
set_voxel(g, x, y, z, CHANNEL_LIGHT_COLOR_G);
|
||||||
|
set_voxel(b, x, y, z, CHANNEL_LIGHT_COLOR_B);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void VoxelBuffer::clear_lights() {
|
||||||
|
fill(0, CHANNEL_LIGHT_COLOR_R);
|
||||||
|
fill(0, CHANNEL_LIGHT_COLOR_G);
|
||||||
|
fill(0, CHANNEL_LIGHT_COLOR_B);
|
||||||
|
}
|
||||||
|
|
||||||
void VoxelChunk::create_mesher() {
|
void VoxelChunk::create_mesher() {
|
||||||
call("_create_mesher");
|
call("_create_mesher");
|
||||||
|
|
||||||
@ -336,7 +462,7 @@ void VoxelChunk::create_colliders() {
|
|||||||
|
|
||||||
PhysicsServer::get_singleton()->body_add_shape(_body_rid, _shape_rid);
|
PhysicsServer::get_singleton()->body_add_shape(_body_rid, _shape_rid);
|
||||||
|
|
||||||
PhysicsServer::get_singleton()->body_set_state(_body_rid, PhysicsServer::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(_chunk_position.x * _chunk_size.x * _voxel_scale, _chunk_position.y * _chunk_size.y * _voxel_scale, _chunk_position.z * _chunk_size.z * _voxel_scale)));
|
PhysicsServer::get_singleton()->body_set_state(_body_rid, PhysicsServer::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(_chunk_position_x * _chunk_size_x * _voxel_scale, _chunk_position_y * _chunk_size_y * _voxel_scale, _chunk_position_z * _chunk_size_z * _voxel_scale)));
|
||||||
PhysicsServer::get_singleton()->body_set_space(_body_rid, get_voxel_world()->get_world()->get_space());
|
PhysicsServer::get_singleton()->body_set_space(_body_rid, get_voxel_world()->get_world()->get_space());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,9 +573,9 @@ void VoxelChunk::bake_light(Ref<VoxelLight> light) {
|
|||||||
|
|
||||||
Vector3i wp = light->get_world_position();
|
Vector3i wp = light->get_world_position();
|
||||||
|
|
||||||
int wpx = wp.x - (_chunk_position.x * _chunk_size.x);
|
int wpx = wp.x - (_chunk_position_x * _chunk_size_x);
|
||||||
int wpy = wp.y - (_chunk_position.y * _chunk_size.y);
|
int wpy = wp.y - (_chunk_position_y * _chunk_size_y);
|
||||||
int wpz = wp.z - (_chunk_position.z * _chunk_size.z);
|
int wpz = wp.z - (_chunk_position_z * _chunk_size_z);
|
||||||
|
|
||||||
//int wpx = (int)(wp.x / _chunk_size.x) - _chunk_position.x;
|
//int wpx = (int)(wp.x / _chunk_size.x) - _chunk_position.x;
|
||||||
//int wpy = (int)(wp.y / _chunk_size.y) - _chunk_position.y;
|
//int wpy = (int)(wp.y / _chunk_size.y) - _chunk_position.y;
|
||||||
@ -528,7 +654,7 @@ void VoxelChunk::allocate_main_mesh() {
|
|||||||
|
|
||||||
VS::get_singleton()->instance_set_base(_mesh_instance_rid, _mesh_rid);
|
VS::get_singleton()->instance_set_base(_mesh_instance_rid, _mesh_rid);
|
||||||
|
|
||||||
VS::get_singleton()->instance_set_transform(_mesh_instance_rid, Transform(Basis(), Vector3(_chunk_position.x * _chunk_size.x * _voxel_scale, _chunk_position.y * _chunk_size.y * _voxel_scale, _chunk_position.z * _chunk_size.z * _voxel_scale)));
|
VS::get_singleton()->instance_set_transform(_mesh_instance_rid, Transform(Basis(), Vector3(_chunk_position_x * _chunk_size_x * _voxel_scale, _chunk_position_y * _chunk_size_y * _voxel_scale, _chunk_position_z * _chunk_size_z * _voxel_scale)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelChunk::free_main_mesh() {
|
void VoxelChunk::free_main_mesh() {
|
||||||
@ -559,7 +685,7 @@ void VoxelChunk::allocate_prop_mesh() {
|
|||||||
|
|
||||||
VS::get_singleton()->instance_set_base(_prop_mesh_instance_rid, _prop_mesh_rid);
|
VS::get_singleton()->instance_set_base(_prop_mesh_instance_rid, _prop_mesh_rid);
|
||||||
|
|
||||||
VS::get_singleton()->instance_set_transform(_prop_mesh_instance_rid, Transform(Basis(), Vector3(_chunk_position.x * _chunk_size.x * _voxel_scale, _chunk_position.y * _chunk_size.y * _voxel_scale, _chunk_position.z * _chunk_size.z * _voxel_scale)));
|
VS::get_singleton()->instance_set_transform(_prop_mesh_instance_rid, Transform(Basis(), Vector3(_chunk_position_x * _chunk_size_x * _voxel_scale, _chunk_position_y * _chunk_size_y * _voxel_scale, _chunk_position_z * _chunk_size_z * _voxel_scale)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -584,7 +710,7 @@ void VoxelChunk::allocate_prop_colliders() {
|
|||||||
|
|
||||||
PhysicsServer::get_singleton()->body_add_shape(_prop_body_rid, _prop_shape_rid);
|
PhysicsServer::get_singleton()->body_add_shape(_prop_body_rid, _prop_shape_rid);
|
||||||
|
|
||||||
PhysicsServer::get_singleton()->body_set_state(_prop_body_rid, PhysicsServer::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(_chunk_position.x * _chunk_size.x * _voxel_scale, _chunk_position.y * _chunk_size.y * _voxel_scale, _chunk_position.z * _chunk_size.z * _voxel_scale)));
|
PhysicsServer::get_singleton()->body_set_state(_prop_body_rid, PhysicsServer::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(_chunk_position_x * _chunk_size_x * _voxel_scale, _chunk_position_y * _chunk_size_y * _voxel_scale, _chunk_position_z * _chunk_size_z * _voxel_scale)));
|
||||||
PhysicsServer::get_singleton()->body_set_space(_prop_body_rid, get_voxel_world()->get_world()->get_space());
|
PhysicsServer::get_singleton()->body_set_space(_prop_body_rid, get_voxel_world()->get_world()->get_space());
|
||||||
}
|
}
|
||||||
void VoxelChunk::build_prop_collider() {
|
void VoxelChunk::build_prop_collider() {
|
||||||
@ -624,7 +750,7 @@ void VoxelChunk::allocate_liquid_mesh() {
|
|||||||
|
|
||||||
VS::get_singleton()->instance_set_base(_liquid_mesh_instance_rid, _liquid_mesh_rid);
|
VS::get_singleton()->instance_set_base(_liquid_mesh_instance_rid, _liquid_mesh_rid);
|
||||||
|
|
||||||
VS::get_singleton()->instance_set_transform(_liquid_mesh_instance_rid, Transform(Basis(), Vector3(_chunk_position.x * _chunk_size.x * _voxel_scale, _chunk_position.y * _chunk_size.y * _voxel_scale, _chunk_position.z * _chunk_size.z * _voxel_scale)));
|
VS::get_singleton()->instance_set_transform(_liquid_mesh_instance_rid, Transform(Basis(), Vector3(_chunk_position_x * _chunk_size_x * _voxel_scale, _chunk_position_y * _chunk_size_y * _voxel_scale, _chunk_position_z * _chunk_size_z * _voxel_scale)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelChunk::free_liquid_mesh() {
|
void VoxelChunk::free_liquid_mesh() {
|
||||||
@ -657,7 +783,7 @@ void VoxelChunk::allocate_clutter_mesh() {
|
|||||||
|
|
||||||
VS::get_singleton()->instance_set_base(_clutter_mesh_instance_rid, _clutter_mesh_rid);
|
VS::get_singleton()->instance_set_base(_clutter_mesh_instance_rid, _clutter_mesh_rid);
|
||||||
|
|
||||||
VS::get_singleton()->instance_set_transform(_clutter_mesh_instance_rid, Transform(Basis(), Vector3(_chunk_position.x * _chunk_size.x * _voxel_scale, _chunk_position.y * _chunk_size.y * _voxel_scale, _chunk_position.z * _chunk_size.z * _voxel_scale)));
|
VS::get_singleton()->instance_set_transform(_clutter_mesh_instance_rid, Transform(Basis(), Vector3(_chunk_position_x * _chunk_size_x * _voxel_scale, _chunk_position_y * _chunk_size_y * _voxel_scale, _chunk_position_z * _chunk_size_z * _voxel_scale)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelChunk::free_clutter_mesh() {
|
void VoxelChunk::free_clutter_mesh() {
|
||||||
@ -781,9 +907,9 @@ void VoxelChunk::draw_debug_voxel_lights() {
|
|||||||
|
|
||||||
Vector3i pos = v->get_world_position();
|
Vector3i pos = v->get_world_position();
|
||||||
|
|
||||||
int pos_x = pos.x - (_chunk_size.x * _chunk_position.x);
|
int pos_x = pos.x - (_chunk_size_x * _chunk_position_x);
|
||||||
int pos_y = pos.y - (_chunk_size.y * _chunk_position.y);
|
int pos_y = pos.y - (_chunk_size_y * _chunk_position_y);
|
||||||
int pos_z = pos.z - (_chunk_size.z * _chunk_position.z);
|
int pos_z = pos.z - (_chunk_size_z * _chunk_position_z);
|
||||||
|
|
||||||
draw_cross_voxels_fill(Vector3(pos_x, pos_y, pos_z), 1.0);
|
draw_cross_voxels_fill(Vector3(pos_x, pos_y, pos_z), 1.0);
|
||||||
}
|
}
|
||||||
@ -820,6 +946,9 @@ VoxelChunk::VoxelChunk() {
|
|||||||
|
|
||||||
_debug_drawer = NULL;
|
_debug_drawer = NULL;
|
||||||
_voxel_world = NULL;
|
_voxel_world = NULL;
|
||||||
|
|
||||||
|
_margin_start = 0;
|
||||||
|
_margin_end = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelChunk::~VoxelChunk() {
|
VoxelChunk::~VoxelChunk() {
|
||||||
|
@ -62,6 +62,20 @@ public:
|
|||||||
BUILD_PHASE_MAX = 10
|
BUILD_PHASE_MAX = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ChannelId {
|
||||||
|
CHANNEL_TYPE = 0,
|
||||||
|
CHANNEL_ISOLEVEL,
|
||||||
|
CHANNEL_LIGHT_COLOR_R,
|
||||||
|
CHANNEL_LIGHT_COLOR_G,
|
||||||
|
CHANNEL_LIGHT_COLOR_B,
|
||||||
|
CHANNEL_AO,
|
||||||
|
CHANNEL_RANDOM_AO,
|
||||||
|
CHANNEL_LIQUID_TYPES,
|
||||||
|
CHANNEL_LIQUID_FILL,
|
||||||
|
CHANNEL_LIQUID_FLOW,
|
||||||
|
MAX_CHANNELS
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool get_dirty() const;
|
bool get_dirty() const;
|
||||||
void set_dirty(bool value);
|
void set_dirty(bool value);
|
||||||
@ -77,7 +91,7 @@ public:
|
|||||||
int get_chunk_position_z();
|
int get_chunk_position_z();
|
||||||
void set_chunk_position_z(int value);
|
void set_chunk_position_z(int value);
|
||||||
|
|
||||||
Vector3i get_chunk_position() const;
|
Vector3 get_chunk_position() const;
|
||||||
void set_chunk_position(int x, int y, int z);
|
void set_chunk_position(int x, int y, int z);
|
||||||
|
|
||||||
int get_chunk_size_x();
|
int get_chunk_size_x();
|
||||||
@ -87,9 +101,22 @@ public:
|
|||||||
int get_chunk_size_z();
|
int get_chunk_size_z();
|
||||||
void set_chunk_size_z(int value);
|
void set_chunk_size_z(int value);
|
||||||
|
|
||||||
Vector3i get_chunk_size() const;
|
Vector3 get_chunk_size() const;
|
||||||
void set_chunk_size(int x, int y, int z);
|
void set_chunk_size(int x, int y, int z);
|
||||||
|
|
||||||
|
int get_chunk_data_size_x();
|
||||||
|
void set_chunk_data_size_x(int value);
|
||||||
|
int get_chunk_data_size_y();
|
||||||
|
void set_chunk_data_size_y(int value);
|
||||||
|
int get_chunk_data_size_z();
|
||||||
|
void set_chunk_data_size_z(int value);
|
||||||
|
|
||||||
|
Vector3 get_chunk_data_size() const;
|
||||||
|
void set_chunk_data_size(int x, int y, int z);
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int get_margin_start() const { return _margin_start; }
|
||||||
|
_FORCE_INLINE_ int get_margin_end() const { return _margin_end; }
|
||||||
|
|
||||||
Ref<VoxelmanLibrary> get_library();
|
Ref<VoxelmanLibrary> get_library();
|
||||||
void set_library(Ref<VoxelmanLibrary> value);
|
void set_library(Ref<VoxelmanLibrary> value);
|
||||||
|
|
||||||
@ -133,6 +160,23 @@ public:
|
|||||||
RID get_clutter_mesh_rid();
|
RID get_clutter_mesh_rid();
|
||||||
RID get_clutter_mesh_instance_rid();
|
RID get_clutter_mesh_instance_rid();
|
||||||
|
|
||||||
|
//Voxel Data
|
||||||
|
|
||||||
|
void set_size(int size_x, int size_y, int siye_z, int margin_start = 0, int margin_end = 0);
|
||||||
|
void set_channel_count(int value);
|
||||||
|
//validate
|
||||||
|
//get voxel
|
||||||
|
//set voxel
|
||||||
|
//get channel
|
||||||
|
//alloc
|
||||||
|
//fill channel
|
||||||
|
//clear channel
|
||||||
|
|
||||||
|
void generate_ao();
|
||||||
|
|
||||||
|
void add_light(int local_x, int local_y, int local_z, int size, Color color);
|
||||||
|
void clear_lights();
|
||||||
|
|
||||||
//Meshing
|
//Meshing
|
||||||
void create_mesher();
|
void create_mesher();
|
||||||
void _create_mesher();
|
void _create_mesher();
|
||||||
@ -223,8 +267,20 @@ protected:
|
|||||||
|
|
||||||
VoxelWorld *_voxel_world;
|
VoxelWorld *_voxel_world;
|
||||||
|
|
||||||
Vector3i _chunk_position;
|
int _chunk_position_x;
|
||||||
Vector3i _chunk_size;
|
int _chunk_position_y;
|
||||||
|
int _chunk_position_z;
|
||||||
|
|
||||||
|
uint32_t _chunk_size_x;
|
||||||
|
uint32_t _chunk_size_y;
|
||||||
|
uint32_t _chunk_size_z;
|
||||||
|
|
||||||
|
uint32_t _chunk_data_size_x;
|
||||||
|
uint32_t _chunk_data_size_y;
|
||||||
|
uint32_t _chunk_data_size_z;
|
||||||
|
|
||||||
|
uint32_t _margin_start;
|
||||||
|
uint32_t _margin_end;
|
||||||
|
|
||||||
Ref<VoxelBuffer> _buffer;
|
Ref<VoxelBuffer> _buffer;
|
||||||
Vector<Ref<VoxelLight> > _voxel_lights;
|
Vector<Ref<VoxelLight> > _voxel_lights;
|
||||||
|
Loading…
Reference in New Issue
Block a user