mirror of
https://github.com/Relintai/godot_voxel.git
synced 2024-11-11 20:35:08 +01:00
Added VoxelLibrary, texture coordinates and random stuff
This commit is contained in:
parent
1acabf1307
commit
d1d685124f
@ -1,12 +1,14 @@
|
||||
#include "register_types.h"
|
||||
#include "voxel_buffer.h"
|
||||
#include "voxel_mesh_builder.h"
|
||||
#include "voxel_library.h"
|
||||
|
||||
void register_voxel_types() {
|
||||
|
||||
ObjectTypeDB::register_type<Voxel>();
|
||||
ObjectTypeDB::register_type<VoxelBuffer>();
|
||||
ObjectTypeDB::register_type<VoxelMeshBuilder>();
|
||||
ObjectTypeDB::register_type<VoxelLibrary>();
|
||||
|
||||
}
|
||||
|
||||
|
127
voxel.cpp
127
voxel.cpp
@ -1,15 +1,28 @@
|
||||
#include "voxel.h"
|
||||
#include "voxel_library.h"
|
||||
#include "voxel_mesh_builder.h"
|
||||
|
||||
Voxel::Voxel() : Reference(), _id(0), _material_id(0), _is_transparent(false), _color(1.f, 1.f, 1.f) {
|
||||
Voxel::Voxel() : Reference(),
|
||||
_id(0),
|
||||
_material_id(0),
|
||||
_is_transparent(false),
|
||||
_library(NULL),
|
||||
_color(1.f, 1.f, 1.f)
|
||||
{}
|
||||
|
||||
}
|
||||
|
||||
void Voxel::set_id(int id) {
|
||||
ERR_FAIL_COND(id < 0 || id >= 256);
|
||||
Ref<Voxel> Voxel::set_id(int id) {
|
||||
ERR_FAIL_COND_V(id < 0 || id >= 256, Ref<Voxel>(this));
|
||||
_id = id;
|
||||
return Ref<Voxel>(this);
|
||||
}
|
||||
|
||||
void Voxel::set_cube_geometry(float sy) {
|
||||
Ref<Voxel> Voxel::set_material_id(unsigned int id) {
|
||||
ERR_FAIL_COND_V(id >= VoxelMeshBuilder::MAX_MATERIALS, Ref<Voxel>(this));
|
||||
_material_id = id;
|
||||
return Ref<Voxel>(this);
|
||||
}
|
||||
|
||||
Ref<Voxel> Voxel::set_cube_geometry(float sy) {
|
||||
const Vector3 vertices[SIDE_COUNT][6] = {
|
||||
{
|
||||
// LEFT
|
||||
@ -74,29 +87,113 @@ void Voxel::set_cube_geometry(float sy) {
|
||||
w[i] = vertices[side][i];
|
||||
}
|
||||
}
|
||||
|
||||
return Ref<Voxel>(this);
|
||||
}
|
||||
|
||||
void Voxel::set_cube_uv_all_sides(Vector3 atlas_pos) {
|
||||
// TODO
|
||||
Ref<Voxel> Voxel::_set_cube_uv_sides(const Vector2 atlas_pos[6]) {
|
||||
ERR_FAIL_COND_V(_library == NULL, Ref<Voxel>());
|
||||
|
||||
float e = 0.001;
|
||||
const Vector2 uv[4] = {
|
||||
Vector2(e, e),
|
||||
Vector2(1.f - e, e),
|
||||
Vector2(e, 1.f - e),
|
||||
Vector2(1.f - e, 1.f - e),
|
||||
};
|
||||
|
||||
const int uv6[SIDE_COUNT][6] = {
|
||||
{
|
||||
// LEFT
|
||||
//0,1,3,0,1,2
|
||||
2,0,1,2,1,3
|
||||
},
|
||||
{
|
||||
// RIGHT
|
||||
//0,3,1,0,2,3
|
||||
2,1,0,2,3,1
|
||||
},
|
||||
{
|
||||
// BOTTOM
|
||||
//0,3,1,0,2,3
|
||||
0,3,1,0,2,3
|
||||
},
|
||||
{
|
||||
// TOP
|
||||
//0,1,3,0,3,2
|
||||
0,1,3,0,3,2
|
||||
},
|
||||
{
|
||||
// BACK
|
||||
//0,1,3,0,3,2
|
||||
2,3,1,2,1,0
|
||||
},
|
||||
{
|
||||
// FRONT
|
||||
//1,0,3,0,2,3
|
||||
3,2,1,2,0,1
|
||||
}
|
||||
};
|
||||
|
||||
float s = 1.0 / (float)_library->get_atlas_size();
|
||||
|
||||
for (unsigned int side = 0; side < SIDE_COUNT; ++side) {
|
||||
_model_side_uv[side].resize(6);
|
||||
DVector<Vector2>::Write w = _model_side_uv[side].write();
|
||||
for (unsigned int i = 0; i < 6; ++i) {
|
||||
w[i] = (atlas_pos[side] + uv[uv6[side][i]]) * s;
|
||||
}
|
||||
}
|
||||
|
||||
return Ref<Voxel>(this);
|
||||
}
|
||||
|
||||
void Voxel::set_cube_uv_tbs_sides(Vector3 top_atlas_pos, Vector3 side_atlas_pos, Vector3 bottom_atlas_pos) {
|
||||
// TODO
|
||||
Ref<Voxel> Voxel::set_cube_uv_all_sides(Vector2 atlas_pos) {
|
||||
const Vector2 positions[6] = {
|
||||
atlas_pos,
|
||||
atlas_pos,
|
||||
atlas_pos,
|
||||
atlas_pos,
|
||||
atlas_pos,
|
||||
atlas_pos
|
||||
};
|
||||
return _set_cube_uv_sides(positions);
|
||||
}
|
||||
|
||||
Ref<Voxel> Voxel::set_cube_uv_tbs_sides(Vector2 top_atlas_pos, Vector2 side_atlas_pos, Vector2 bottom_atlas_pos) {
|
||||
const Vector2 positions[6] = {
|
||||
side_atlas_pos,
|
||||
side_atlas_pos,
|
||||
bottom_atlas_pos,
|
||||
top_atlas_pos,
|
||||
side_atlas_pos,
|
||||
side_atlas_pos,
|
||||
};
|
||||
return _set_cube_uv_sides(positions);
|
||||
}
|
||||
|
||||
//Ref<Voxel> Voxel::set_xquad_geometry(Vector2 atlas_pos) {
|
||||
// // TODO
|
||||
// return Ref<Voxel>(this);
|
||||
//}
|
||||
|
||||
void Voxel::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_name", "name"), &Voxel::set_name);
|
||||
ObjectTypeDB::bind_method(_MD("set_name:Voxel", "name"), &Voxel::set_name);
|
||||
ObjectTypeDB::bind_method(_MD("get_name"), &Voxel::get_name);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_id", "id"), &Voxel::set_id);
|
||||
ObjectTypeDB::bind_method(_MD("set_id:Voxel", "id"), &Voxel::set_id);
|
||||
ObjectTypeDB::bind_method(_MD("get_id"), &Voxel::get_id);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_color", "color"), &Voxel::set_color);
|
||||
ObjectTypeDB::bind_method(_MD("set_color:Voxel", "color"), &Voxel::set_color);
|
||||
ObjectTypeDB::bind_method(_MD("get_color"), &Voxel::get_color);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_cube_geometry", "height"), &Voxel::set_cube_geometry, DEFVAL(1.f));
|
||||
// TODO
|
||||
ObjectTypeDB::bind_method(_MD("set_transparent:Voxel", "color"), &Voxel::set_transparent, DEFVAL(true));
|
||||
ObjectTypeDB::bind_method(_MD("is_transparent"), &Voxel::is_transparent);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_cube_geometry:Voxel", "height"), &Voxel::set_cube_geometry, DEFVAL(1.f));
|
||||
ObjectTypeDB::bind_method(_MD("set_cube_uv_all_sides:Voxel", "atlas_pos"), &Voxel::set_cube_uv_all_sides);
|
||||
ObjectTypeDB::bind_method(_MD("set_cube_uv_tbs_sides:Voxel", "top_atlas_pos", "side_atlas_pos", "bottom_atlas_pos"), &Voxel::set_cube_uv_tbs_sides);
|
||||
|
||||
}
|
||||
|
||||
|
38
voxel.h
38
voxel.h
@ -3,8 +3,11 @@
|
||||
|
||||
#include <reference.h>
|
||||
|
||||
class VoxelLibrary;
|
||||
|
||||
// Definition of one type of voxel.
|
||||
// A voxel can be a simple coloured cube, or a more complex model.
|
||||
// Important: it is recommended that you create voxels from a library rather than using new().
|
||||
class Voxel : public Reference {
|
||||
OBJ_TYPE(Voxel, Reference)
|
||||
|
||||
@ -21,11 +24,17 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
VoxelLibrary * _library;
|
||||
|
||||
// Identifiers
|
||||
int _id;
|
||||
String _name;
|
||||
|
||||
// Properties
|
||||
int _material_id;
|
||||
bool _is_transparent;
|
||||
|
||||
// Model
|
||||
Color _color;
|
||||
DVector<Vector3> _model_vertices;
|
||||
DVector<Vector3> _model_normals;
|
||||
@ -36,24 +45,33 @@ private:
|
||||
// TODO Child voxel types
|
||||
|
||||
public:
|
||||
|
||||
Voxel();
|
||||
|
||||
_FORCE_INLINE_ void set_name(String name) { _name = name; }
|
||||
// Properties
|
||||
|
||||
_FORCE_INLINE_ Ref<Voxel> set_name(String name) { _name = name; return Ref<Voxel>(this); }
|
||||
_FORCE_INLINE_ String get_name() const { return _name; }
|
||||
|
||||
void set_id(int id);
|
||||
Ref<Voxel> set_id(int id);
|
||||
_FORCE_INLINE_ int get_id() const { return _id; }
|
||||
|
||||
_FORCE_INLINE_ void set_color(Color color) { _color = color; }
|
||||
_FORCE_INLINE_ Ref<Voxel> set_color(Color color) { _color = color; return Ref<Voxel>(this); }
|
||||
_FORCE_INLINE_ Color get_color() const { return _color; }
|
||||
|
||||
_FORCE_INLINE_ void set_material_id(unsigned int id) { _material_id = id; }
|
||||
Ref<Voxel> set_material_id(unsigned int id);
|
||||
_FORCE_INLINE_ unsigned int get_material_id() const { return _material_id; }
|
||||
|
||||
void set_cube_geometry(float sy = 1);
|
||||
void set_cube_uv_all_sides(Vector3 atlas_pos);
|
||||
void set_cube_uv_tbs_sides(Vector3 top_atlas_pos, Vector3 side_atlas_pos, Vector3 bottom_atlas_pos);
|
||||
_FORCE_INLINE_ Ref<Voxel> set_transparent(bool t = true) { _is_transparent = t; return Ref<Voxel>(this); }
|
||||
_FORCE_INLINE_ bool is_transparent() const { return _is_transparent; }
|
||||
|
||||
// Built-in geometry generators
|
||||
|
||||
Ref<Voxel> set_cube_geometry(float sy = 1);
|
||||
Ref<Voxel> set_cube_uv_all_sides(Vector2 atlas_pos);
|
||||
Ref<Voxel> set_cube_uv_tbs_sides(Vector2 top_atlas_pos, Vector2 side_atlas_pos, Vector2 bottom_atlas_pos);
|
||||
//Ref<Voxel> set_xquad_geometry(Vector2 atlas_pos);
|
||||
|
||||
// Getters for native usage only
|
||||
|
||||
const DVector<Vector3> & get_model_vertices() const { return _model_vertices; }
|
||||
const DVector<Vector3> & get_model_normals() const { return _model_normals; }
|
||||
@ -61,7 +79,11 @@ public:
|
||||
const DVector<Vector3> & get_model_side_vertices(unsigned int side) const { return _model_side_vertices[side]; }
|
||||
const DVector<Vector2> & get_model_side_uv(unsigned int side) const { return _model_side_uv[side]; }
|
||||
|
||||
void set_library_ptr(VoxelLibrary * lib) { _library = lib; }
|
||||
|
||||
protected:
|
||||
Ref<Voxel> _set_cube_uv_sides(const Vector2 atlas_pos[6]);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
};
|
||||
|
@ -18,6 +18,7 @@ class VoxelBuffer : public Reference {
|
||||
struct Channel {
|
||||
// Allocated when the channel is populated.
|
||||
// Array of array of arrays, in order [z][x][y] because it makes vertical-wise access faster (the engine is Y-up).
|
||||
// SUGG: move to flat storage?
|
||||
uint8_t *** data;
|
||||
|
||||
uint8_t defval; // Default value when data is null
|
||||
@ -60,6 +61,7 @@ public:
|
||||
void set_voxel_v(int value, Vector3 pos, unsigned int channel_index = 0);
|
||||
|
||||
void fill(int defval, unsigned int channel_index = 0);
|
||||
//void fill_min_max(int value, int x0, int y0, int z0, int x1, int y1, int z1, unsigned int channel_index = 0);
|
||||
|
||||
bool is_uniform(unsigned int channel_index = 0);
|
||||
|
||||
|
36
voxel_library.cpp
Normal file
36
voxel_library.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "voxel_library.h"
|
||||
|
||||
VoxelLibrary::VoxelLibrary() : Reference(), _atlas_size(1) {
|
||||
|
||||
}
|
||||
|
||||
VoxelLibrary::~VoxelLibrary() {
|
||||
for (unsigned int i = 0; i < MAX_VOXEL_TYPES; ++i) {
|
||||
if (_voxel_types[i].is_valid()) {
|
||||
_voxel_types[i]->set_library_ptr(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelLibrary::set_atlas_size(int s) {
|
||||
ERR_FAIL_COND(s <= 0);
|
||||
_atlas_size = s;
|
||||
}
|
||||
|
||||
Ref<Voxel> VoxelLibrary::create_voxel(int id, String name) {
|
||||
ERR_FAIL_COND_V(id < 0 || id >= MAX_VOXEL_TYPES, Ref<Voxel>());
|
||||
Ref<Voxel> voxel(memnew(Voxel));
|
||||
voxel->set_library_ptr(this);
|
||||
voxel->set_id(id);
|
||||
voxel->set_name(name);
|
||||
_voxel_types[id] = voxel;
|
||||
return voxel;
|
||||
}
|
||||
|
||||
void VoxelLibrary::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("create_voxel:Voxel", "id", "name"), &VoxelLibrary::create_voxel);
|
||||
ObjectTypeDB::bind_method(_MD("set_atlas_size", "square_size"), &VoxelLibrary::set_atlas_size);
|
||||
|
||||
}
|
||||
|
37
voxel_library.h
Normal file
37
voxel_library.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef VOXEL_LIBRARY_H
|
||||
#define VOXEL_LIBRARY_H
|
||||
|
||||
#include <reference.h>
|
||||
#include "voxel.h"
|
||||
|
||||
class VoxelLibrary : public Reference {
|
||||
OBJ_TYPE(VoxelLibrary, Reference)
|
||||
|
||||
public:
|
||||
static const unsigned int MAX_VOXEL_TYPES = 256; // Required limit because voxel types are stored in 8 bits
|
||||
|
||||
VoxelLibrary();
|
||||
~VoxelLibrary();
|
||||
|
||||
int get_atlas_size() const { return _atlas_size; }
|
||||
void set_atlas_size(int s);
|
||||
|
||||
// Use this factory rather than creating voxels from scratch
|
||||
Ref<Voxel> create_voxel(int id, String name);
|
||||
|
||||
// Internal getters
|
||||
|
||||
_FORCE_INLINE_ bool has_voxel(int id) const { return _voxel_types[id].is_valid(); }
|
||||
_FORCE_INLINE_ const Voxel & get_voxel_const(int id) const { return **_voxel_types[id]; }
|
||||
|
||||
private:
|
||||
Ref<Voxel> _voxel_types[MAX_VOXEL_TYPES];
|
||||
int _atlas_size;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
};
|
||||
|
||||
#endif // VOXEL_LIBRARY_H
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "voxel_mesh_builder.h"
|
||||
#include "voxel_library.h"
|
||||
|
||||
static const Vector3i g_side_normals[Voxel::SIDE_COUNT] = {
|
||||
Vector3i(-1, 0, 0),
|
||||
@ -13,12 +14,9 @@ VoxelMeshBuilder::VoxelMeshBuilder() {
|
||||
|
||||
}
|
||||
|
||||
void VoxelMeshBuilder::add_voxel_type(Ref<Voxel> voxel) {
|
||||
ERR_FAIL_COND(voxel.is_null());
|
||||
ERR_FAIL_COND(voxel->get_id() >= MAX_VOXEL_TYPES);
|
||||
ERR_FAIL_COND(voxel->get_material_id() >= MAX_MATERIALS);
|
||||
unsigned int id = voxel->get_id();
|
||||
_voxel_types[id] = voxel;
|
||||
void VoxelMeshBuilder::set_library(Ref<VoxelLibrary> library) {
|
||||
ERR_FAIL_COND(library.is_null());
|
||||
_library = library;
|
||||
}
|
||||
|
||||
void VoxelMeshBuilder::set_material(Ref<Material> material, unsigned int id) {
|
||||
@ -29,8 +27,10 @@ void VoxelMeshBuilder::set_material(Ref<Material> material, unsigned int id) {
|
||||
|
||||
Ref<Mesh> VoxelMeshBuilder::build(Ref<VoxelBuffer> buffer_ref) {
|
||||
ERR_FAIL_COND_V(buffer_ref.is_null(), Ref<Mesh>());
|
||||
ERR_FAIL_COND_V(_library.is_null(), Ref<Mesh>());
|
||||
|
||||
const VoxelBuffer & buffer = **buffer_ref;
|
||||
const VoxelLibrary & library = **_library;
|
||||
|
||||
for (unsigned int i = 0; i < MAX_MATERIALS; ++i) {
|
||||
_surface_tool[i].begin(Mesh::PRIMITIVE_TRIANGLES);
|
||||
@ -44,9 +44,9 @@ Ref<Mesh> VoxelMeshBuilder::build(Ref<VoxelBuffer> buffer_ref) {
|
||||
|
||||
int voxel_id = buffer.get_voxel_local(x, y, z, 0);
|
||||
|
||||
if (voxel_id != 0 && !_voxel_types[voxel_id].is_null()) {
|
||||
if (voxel_id != 0 && library.has_voxel(voxel_id)) {
|
||||
|
||||
const Voxel & voxel = **_voxel_types[voxel_id];
|
||||
const Voxel & voxel = library.get_voxel_const(voxel_id);
|
||||
|
||||
SurfaceTool & st = _surface_tool[voxel.get_material_id()];
|
||||
|
||||
@ -68,12 +68,14 @@ Ref<Mesh> VoxelMeshBuilder::build(Ref<VoxelBuffer> buffer_ref) {
|
||||
// TODO Better face visibility test
|
||||
if (neighbor_voxel_id == 0) {
|
||||
|
||||
DVector<Vector3>::Read r = vertices.read();
|
||||
DVector<Vector3>::Read rv = vertices.read();
|
||||
DVector<Vector2>::Read rt = voxel.get_model_side_uv(side).read();
|
||||
Vector3 pos(x - 1, y - 1, z - 1);
|
||||
|
||||
for (unsigned int i = 0; i < vertices.size(); ++i) {
|
||||
st.add_normal(Vector3(normal.x, normal.y, normal.z));
|
||||
st.add_vertex(r[i] + pos);
|
||||
st.add_uv(rt[i]);
|
||||
st.add_vertex(rv[i] + pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,10 +87,12 @@ Ref<Mesh> VoxelMeshBuilder::build(Ref<VoxelBuffer> buffer_ref) {
|
||||
const DVector<Vector3> & vertices = voxel.get_model_vertices();
|
||||
DVector<Vector3>::Read rv = voxel.get_model_vertices().read();
|
||||
DVector<Vector3>::Read rn = voxel.get_model_normals().read();
|
||||
DVector<Vector2>::Read rt = voxel.get_model_uv().read();
|
||||
Vector3 pos(x - 1, y - 1, z - 1);
|
||||
|
||||
for (unsigned int i = 0; i < vertices.size(); ++i) {
|
||||
st.add_normal(rn[i]);
|
||||
st.add_uv(rt[i]);
|
||||
st.add_vertex(rv[i] + pos);
|
||||
}
|
||||
}
|
||||
@ -115,8 +119,8 @@ Ref<Mesh> VoxelMeshBuilder::build(Ref<VoxelBuffer> buffer_ref) {
|
||||
|
||||
void VoxelMeshBuilder::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("add_voxel_type", "voxel"), &VoxelMeshBuilder::add_voxel_type);
|
||||
ObjectTypeDB::bind_method(_MD("set_material", "material", "id"), &VoxelMeshBuilder::set_material);
|
||||
ObjectTypeDB::bind_method(_MD("set_library", "voxel_library"), &VoxelMeshBuilder::set_library);
|
||||
ObjectTypeDB::bind_method(_MD("build", "voxel_buffer"), &VoxelMeshBuilder::build);
|
||||
|
||||
}
|
||||
|
@ -7,23 +7,26 @@
|
||||
#include "voxel.h"
|
||||
#include "voxel_buffer.h"
|
||||
|
||||
class VoxelLibrary;
|
||||
|
||||
class VoxelMeshBuilder : public Reference {
|
||||
OBJ_TYPE(VoxelMeshBuilder, Reference);
|
||||
|
||||
static const unsigned int MAX_VOXEL_TYPES = 256; // Required limit because voxel types are stored in 8 bits
|
||||
public:
|
||||
static const unsigned int MAX_MATERIALS = 8; // Arbitrary. Tweak if needed.
|
||||
|
||||
Ref<Voxel> _voxel_types[MAX_VOXEL_TYPES];
|
||||
private:
|
||||
Ref<VoxelLibrary> _library;
|
||||
Ref<Material> _materials[MAX_MATERIALS];
|
||||
SurfaceTool _surface_tool[MAX_MATERIALS];
|
||||
|
||||
public:
|
||||
|
||||
VoxelMeshBuilder();
|
||||
|
||||
void add_voxel_type(Ref<Voxel> voxel);
|
||||
void set_material(Ref<Material> material, unsigned int id);
|
||||
|
||||
void set_library(Ref<VoxelLibrary> library);
|
||||
|
||||
Ref<Mesh> build(Ref<VoxelBuffer> buffer_ref);
|
||||
|
||||
protected:
|
||||
|
Loading…
Reference in New Issue
Block a user