Added baked light support for gridmaps.
This commit is contained in:
parent
4e442b0648
commit
e96c40f94a
5 changed files with 306 additions and 58 deletions
|
@ -101,6 +101,27 @@ bool GridMap::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_recreate_octant_data();
|
_recreate_octant_data();
|
||||||
|
} else if (name == "baked_meshes") {
|
||||||
|
|
||||||
|
clear_baked_meshes();
|
||||||
|
|
||||||
|
Array meshes = p_value;
|
||||||
|
|
||||||
|
for (int i = 0; i < meshes.size(); i++) {
|
||||||
|
BakedMesh bm;
|
||||||
|
bm.mesh = meshes[i];
|
||||||
|
ERR_CONTINUE(!bm.mesh.is_valid());
|
||||||
|
bm.instance = VS::get_singleton()->instance_create();
|
||||||
|
VS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid());
|
||||||
|
VS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id());
|
||||||
|
if (is_inside_tree()) {
|
||||||
|
VS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario());
|
||||||
|
VS::get_singleton()->instance_set_transform(bm.instance, get_global_transform());
|
||||||
|
}
|
||||||
|
baked_meshes.push_back(bm);
|
||||||
|
}
|
||||||
|
|
||||||
|
_recreate_octant_data();
|
||||||
|
|
||||||
} else
|
} else
|
||||||
return false;
|
return false;
|
||||||
|
@ -145,6 +166,15 @@ bool GridMap::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
d["cells"] = cells;
|
d["cells"] = cells;
|
||||||
|
|
||||||
r_ret = d;
|
r_ret = d;
|
||||||
|
} else if (name == "baked_meshes") {
|
||||||
|
|
||||||
|
Array ret;
|
||||||
|
ret.resize(baked_meshes.size());
|
||||||
|
for (int i = 0; i < baked_meshes.size(); i++) {
|
||||||
|
ret.push_back(baked_meshes[i].mesh);
|
||||||
|
}
|
||||||
|
r_ret = ret;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -161,6 +191,9 @@ void GridMap::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
p_list->push_back(PropertyInfo(Variant::BOOL, "cell_center_y"));
|
p_list->push_back(PropertyInfo(Variant::BOOL, "cell_center_y"));
|
||||||
p_list->push_back(PropertyInfo(Variant::BOOL, "cell_center_z"));
|
p_list->push_back(PropertyInfo(Variant::BOOL, "cell_center_z"));
|
||||||
p_list->push_back(PropertyInfo(Variant::REAL, "cell_scale"));
|
p_list->push_back(PropertyInfo(Variant::REAL, "cell_scale"));
|
||||||
|
if (baked_meshes.size()) {
|
||||||
|
p_list->push_back(PropertyInfo(Variant::ARRAY, "baked_meshes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
|
||||||
|
}
|
||||||
|
|
||||||
p_list->push_back(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
|
p_list->push_back(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
|
||||||
}
|
}
|
||||||
|
@ -235,6 +268,12 @@ bool GridMap::get_center_z() const {
|
||||||
|
|
||||||
void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) {
|
void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) {
|
||||||
|
|
||||||
|
if (baked_meshes.size() && !recreating_octants) {
|
||||||
|
//if you set a cell item, baked meshes go good bye
|
||||||
|
clear_baked_meshes();
|
||||||
|
_recreate_octant_data();
|
||||||
|
}
|
||||||
|
|
||||||
ERR_FAIL_INDEX(ABS(p_x), 1 << 20);
|
ERR_FAIL_INDEX(ABS(p_x), 1 << 20);
|
||||||
ERR_FAIL_INDEX(ABS(p_y), 1 << 20);
|
ERR_FAIL_INDEX(ABS(p_y), 1 << 20);
|
||||||
ERR_FAIL_INDEX(ABS(p_z), 1 << 20);
|
ERR_FAIL_INDEX(ABS(p_z), 1 << 20);
|
||||||
|
@ -477,41 +516,44 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//update multimeshes
|
//update multimeshes, only if not baked
|
||||||
for (Map<int, List<Pair<Transform, IndexKey> > >::Element *E = multimesh_items.front(); E; E = E->next()) {
|
if (baked_meshes.size() == 0) {
|
||||||
Octant::MultimeshInstance mmi;
|
|
||||||
|
|
||||||
RID mm = VS::get_singleton()->multimesh_create();
|
for (Map<int, List<Pair<Transform, IndexKey> > >::Element *E = multimesh_items.front(); E; E = E->next()) {
|
||||||
VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_NONE);
|
Octant::MultimeshInstance mmi;
|
||||||
VS::get_singleton()->multimesh_set_mesh(mm, theme->get_item_mesh(E->key())->get_rid());
|
|
||||||
|
|
||||||
int idx = 0;
|
RID mm = VS::get_singleton()->multimesh_create();
|
||||||
for (List<Pair<Transform, IndexKey> >::Element *F = E->get().front(); F; F = F->next()) {
|
VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_NONE);
|
||||||
VS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first);
|
VS::get_singleton()->multimesh_set_mesh(mm, theme->get_item_mesh(E->key())->get_rid());
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for (List<Pair<Transform, IndexKey> >::Element *F = E->get().front(); F; F = F->next()) {
|
||||||
|
VS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first);
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
||||||
Octant::MultimeshInstance::Item it;
|
Octant::MultimeshInstance::Item it;
|
||||||
it.index = idx;
|
it.index = idx;
|
||||||
it.transform = F->get().first;
|
it.transform = F->get().first;
|
||||||
it.key = F->get().second;
|
it.key = F->get().second;
|
||||||
mmi.items.push_back(it);
|
mmi.items.push_back(it);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
RID instance = VS::get_singleton()->instance_create();
|
||||||
|
VS::get_singleton()->instance_set_base(instance, mm);
|
||||||
|
|
||||||
|
if (is_inside_tree()) {
|
||||||
|
VS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario());
|
||||||
|
VS::get_singleton()->instance_set_transform(instance, get_global_transform());
|
||||||
|
}
|
||||||
|
|
||||||
|
mmi.multimesh = mm;
|
||||||
|
mmi.instance = instance;
|
||||||
|
|
||||||
|
g.multimesh_instances.push_back(mmi);
|
||||||
}
|
}
|
||||||
|
|
||||||
RID instance = VS::get_singleton()->instance_create();
|
|
||||||
VS::get_singleton()->instance_set_base(instance, mm);
|
|
||||||
|
|
||||||
if (is_inside_tree()) {
|
|
||||||
VS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario());
|
|
||||||
VS::get_singleton()->instance_set_transform(instance, get_global_transform());
|
|
||||||
}
|
|
||||||
|
|
||||||
mmi.multimesh = mm;
|
|
||||||
mmi.instance = instance;
|
|
||||||
|
|
||||||
g.multimesh_instances.push_back(mmi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (col_debug.size()) {
|
if (col_debug.size()) {
|
||||||
|
@ -642,6 +684,11 @@ void GridMap::_notification(int p_what) {
|
||||||
_octant_enter_world(E->key());
|
_octant_enter_world(E->key());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < baked_meshes.size(); i++) {
|
||||||
|
VS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, get_world()->get_scenario());
|
||||||
|
VS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform());
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||||
|
|
||||||
|
@ -655,6 +702,10 @@ void GridMap::_notification(int p_what) {
|
||||||
|
|
||||||
last_transform = new_xform;
|
last_transform = new_xform;
|
||||||
|
|
||||||
|
for (int i = 0; i < baked_meshes.size(); i++) {
|
||||||
|
VS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform());
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_EXIT_WORLD: {
|
case NOTIFICATION_EXIT_WORLD: {
|
||||||
|
|
||||||
|
@ -667,6 +718,9 @@ void GridMap::_notification(int p_what) {
|
||||||
//_queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS);
|
//_queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS);
|
||||||
//_update_octants_callback();
|
//_update_octants_callback();
|
||||||
//_update_area_instances();
|
//_update_area_instances();
|
||||||
|
for (int i = 0; i < baked_meshes.size(); i++) {
|
||||||
|
VS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, RID());
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||||
|
@ -701,12 +755,14 @@ void GridMap::_queue_octants_dirty() {
|
||||||
|
|
||||||
void GridMap::_recreate_octant_data() {
|
void GridMap::_recreate_octant_data() {
|
||||||
|
|
||||||
|
recreating_octants = true;
|
||||||
Map<IndexKey, Cell> cell_copy = cell_map;
|
Map<IndexKey, Cell> cell_copy = cell_map;
|
||||||
_clear_internal();
|
_clear_internal();
|
||||||
for (Map<IndexKey, Cell>::Element *E = cell_copy.front(); E; E = E->next()) {
|
for (Map<IndexKey, Cell>::Element *E = cell_copy.front(); E; E = E->next()) {
|
||||||
|
|
||||||
set_cell_item(E->key().x, E->key().y, E->key().z, E->get().item, E->get().rot);
|
set_cell_item(E->key().x, E->key().y, E->key().z, E->get().item, E->get().rot);
|
||||||
}
|
}
|
||||||
|
recreating_octants = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridMap::_clear_internal() {
|
void GridMap::_clear_internal() {
|
||||||
|
@ -726,6 +782,7 @@ void GridMap::_clear_internal() {
|
||||||
void GridMap::clear() {
|
void GridMap::clear() {
|
||||||
|
|
||||||
_clear_internal();
|
_clear_internal();
|
||||||
|
clear_baked_meshes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridMap::resource_changed(const RES &p_res) {
|
void GridMap::resource_changed(const RES &p_res) {
|
||||||
|
@ -791,6 +848,11 @@ void GridMap::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_used_cells"), &GridMap::get_used_cells);
|
ClassDB::bind_method(D_METHOD("get_used_cells"), &GridMap::get_used_cells);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_meshes"), &GridMap::get_meshes);
|
ClassDB::bind_method(D_METHOD("get_meshes"), &GridMap::get_meshes);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_bake_meshes"), &GridMap::get_bake_meshes);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_bake_mesh_instance", "idx"), &GridMap::get_bake_mesh_instance);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("clear_baked_meshes"), &GridMap::clear_baked_meshes);
|
||||||
|
ClassDB::bind_method(D_METHOD("make_baked_meshes", "gen_lightmap_uv", "lightmap_uv_texel_size"), &GridMap::make_baked_meshes, DEFVAL(false), DEFVAL(0.1));
|
||||||
|
|
||||||
BIND_CONSTANT(INVALID_CELL_ITEM);
|
BIND_CONSTANT(INVALID_CELL_ITEM);
|
||||||
}
|
}
|
||||||
|
@ -883,10 +945,129 @@ Vector3 GridMap::_get_offset() const {
|
||||||
cell_size.z * 0.5 * int(center_z));
|
cell_size.z * 0.5 * int(center_z));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GridMap::clear_baked_meshes() {
|
||||||
|
|
||||||
|
for (int i = 0; i < baked_meshes.size(); i++) {
|
||||||
|
VS::get_singleton()->free(baked_meshes[i].instance);
|
||||||
|
}
|
||||||
|
baked_meshes.clear();
|
||||||
|
|
||||||
|
_recreate_octant_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texel_size) {
|
||||||
|
|
||||||
|
if (!theme.is_valid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
//generate
|
||||||
|
Map<OctantKey, Map<Ref<Material>, Ref<SurfaceTool> > > surface_map;
|
||||||
|
|
||||||
|
for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
IndexKey key = E->key();
|
||||||
|
|
||||||
|
int item = E->get().item;
|
||||||
|
if (!theme->has_item(item))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Ref<Mesh> mesh = theme->get_item_mesh(item);
|
||||||
|
if (!mesh.is_valid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector3 cellpos = Vector3(key.x, key.y, key.z);
|
||||||
|
Vector3 ofs = _get_offset();
|
||||||
|
|
||||||
|
Transform xform;
|
||||||
|
|
||||||
|
xform.basis.set_orthogonal_index(E->get().rot);
|
||||||
|
xform.set_origin(cellpos * cell_size + ofs);
|
||||||
|
xform.basis.scale(Vector3(cell_scale, cell_scale, cell_scale));
|
||||||
|
|
||||||
|
OctantKey ok;
|
||||||
|
ok.x = key.x / octant_size;
|
||||||
|
ok.y = key.y / octant_size;
|
||||||
|
ok.z = key.z / octant_size;
|
||||||
|
|
||||||
|
if (!surface_map.has(ok)) {
|
||||||
|
surface_map[ok] = Map<Ref<Material>, Ref<SurfaceTool> >();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Ref<Material>, Ref<SurfaceTool> > &mat_map = surface_map[ok];
|
||||||
|
|
||||||
|
for (int i = 0; i < mesh->get_surface_count(); i++) {
|
||||||
|
|
||||||
|
if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Ref<Material> surf_mat = mesh->surface_get_material(i);
|
||||||
|
if (!mat_map.has(surf_mat)) {
|
||||||
|
Ref<SurfaceTool> st;
|
||||||
|
st.instance();
|
||||||
|
st->begin(Mesh::PRIMITIVE_TRIANGLES);
|
||||||
|
st->set_material(surf_mat);
|
||||||
|
mat_map[surf_mat] = st;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat_map[surf_mat]->append_from(mesh, i, xform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ofs = 0;
|
||||||
|
|
||||||
|
for (Map<OctantKey, Map<Ref<Material>, Ref<SurfaceTool> > >::Element *E = surface_map.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
print_line("generating mesh " + itos(ofs++) + "/" + itos(surface_map.size()));
|
||||||
|
Ref<ArrayMesh> mesh;
|
||||||
|
mesh.instance();
|
||||||
|
for (Map<Ref<Material>, Ref<SurfaceTool> >::Element *F = E->get().front(); F; F = F->next()) {
|
||||||
|
F->get()->commit(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
BakedMesh bm;
|
||||||
|
bm.mesh = mesh;
|
||||||
|
bm.instance = VS::get_singleton()->instance_create();
|
||||||
|
VS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid());
|
||||||
|
VS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id());
|
||||||
|
if (is_inside_tree()) {
|
||||||
|
VS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario());
|
||||||
|
VS::get_singleton()->instance_set_transform(bm.instance, get_global_transform());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_gen_lightmap_uv) {
|
||||||
|
mesh->lightmap_unwrap(get_global_transform(), p_lightmap_uv_texel_size);
|
||||||
|
}
|
||||||
|
baked_meshes.push_back(bm);
|
||||||
|
}
|
||||||
|
|
||||||
|
_recreate_octant_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
Array GridMap::get_bake_meshes() {
|
||||||
|
|
||||||
|
if (!baked_meshes.size()) {
|
||||||
|
make_baked_meshes(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Array arr;
|
||||||
|
for (int i = 0; i < baked_meshes.size(); i++) {
|
||||||
|
arr.push_back(baked_meshes[i].mesh);
|
||||||
|
arr.push_back(Transform());
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RID GridMap::get_bake_mesh_instance(int p_idx) {
|
||||||
|
|
||||||
|
ERR_FAIL_INDEX_V(p_idx, baked_meshes.size(), RID());
|
||||||
|
return baked_meshes[p_idx].instance;
|
||||||
|
}
|
||||||
|
|
||||||
GridMap::GridMap() {
|
GridMap::GridMap() {
|
||||||
|
|
||||||
cell_size = Vector3(2, 2, 2);
|
cell_size = Vector3(2, 2, 2);
|
||||||
octant_size = 4;
|
octant_size = 8;
|
||||||
awaiting_update = false;
|
awaiting_update = false;
|
||||||
_in_tree = false;
|
_in_tree = false;
|
||||||
center_x = true;
|
center_x = true;
|
||||||
|
@ -901,6 +1082,7 @@ GridMap::GridMap() {
|
||||||
|
|
||||||
navigation = NULL;
|
navigation = NULL;
|
||||||
set_notify_transform(true);
|
set_notify_transform(true);
|
||||||
|
recreating_octants = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GridMap::~GridMap() {
|
GridMap::~GridMap() {
|
||||||
|
|
|
@ -148,6 +148,9 @@ class GridMap : public Spatial {
|
||||||
bool clip;
|
bool clip;
|
||||||
bool clip_above;
|
bool clip_above;
|
||||||
int clip_floor;
|
int clip_floor;
|
||||||
|
|
||||||
|
bool recreating_octants;
|
||||||
|
|
||||||
Vector3::Axis clip_axis;
|
Vector3::Axis clip_axis;
|
||||||
|
|
||||||
Ref<MeshLibrary> theme;
|
Ref<MeshLibrary> theme;
|
||||||
|
@ -188,9 +191,11 @@ class GridMap : public Spatial {
|
||||||
|
|
||||||
struct BakedMesh {
|
struct BakedMesh {
|
||||||
Ref<Mesh> mesh;
|
Ref<Mesh> mesh;
|
||||||
Transform transform;
|
RID instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Vector<BakedMesh> baked_meshes;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _set(const StringName &p_name, const Variant &p_value);
|
bool _set(const StringName &p_name, const Variant &p_value);
|
||||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||||
|
@ -237,8 +242,14 @@ public:
|
||||||
|
|
||||||
Array get_meshes();
|
Array get_meshes();
|
||||||
|
|
||||||
|
void clear_baked_meshes();
|
||||||
|
void make_baked_meshes(bool p_gen_lightmap_uv = false, float p_lightmap_uv_texel_size = 0.1);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
Array get_bake_meshes();
|
||||||
|
RID get_bake_mesh_instance(int p_idx);
|
||||||
|
|
||||||
GridMap();
|
GridMap();
|
||||||
~GridMap();
|
~GridMap();
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,12 +55,13 @@ float BakedLightmapData::get_energy() const {
|
||||||
return energy;
|
return energy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BakedLightmapData::add_user(const NodePath &p_path, const Ref<Texture> &p_lightmap) {
|
void BakedLightmapData::add_user(const NodePath &p_path, const Ref<Texture> &p_lightmap, int p_instance) {
|
||||||
|
|
||||||
ERR_FAIL_COND(p_lightmap.is_null());
|
ERR_FAIL_COND(p_lightmap.is_null());
|
||||||
User user;
|
User user;
|
||||||
user.path = p_path;
|
user.path = p_path;
|
||||||
user.lightmap = p_lightmap;
|
user.lightmap = p_lightmap;
|
||||||
|
user.instance_index = p_instance;
|
||||||
users.push_back(user);
|
users.push_back(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,16 +80,22 @@ Ref<Texture> BakedLightmapData::get_user_lightmap(int p_user) const {
|
||||||
return users[p_user].lightmap;
|
return users[p_user].lightmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BakedLightmapData::get_user_instance(int p_user) const {
|
||||||
|
|
||||||
|
ERR_FAIL_INDEX_V(p_user, users.size(), -1);
|
||||||
|
return users[p_user].instance_index;
|
||||||
|
}
|
||||||
|
|
||||||
void BakedLightmapData::clear_users() {
|
void BakedLightmapData::clear_users() {
|
||||||
users.clear();
|
users.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BakedLightmapData::_set_user_data(const Array &p_data) {
|
void BakedLightmapData::_set_user_data(const Array &p_data) {
|
||||||
|
|
||||||
ERR_FAIL_COND(p_data.size() & 1);
|
ERR_FAIL_COND((p_data.size() % 3) != 0);
|
||||||
|
|
||||||
for (int i = 0; i < p_data.size(); i += 2) {
|
for (int i = 0; i < p_data.size(); i += 3) {
|
||||||
add_user(p_data[i], p_data[i + 1]);
|
add_user(p_data[i], p_data[i + 1], p_data[i + 2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +105,7 @@ Array BakedLightmapData::_get_user_data() const {
|
||||||
for (int i = 0; i < users.size(); i++) {
|
for (int i = 0; i < users.size(); i++) {
|
||||||
ret.push_back(users[i].path);
|
ret.push_back(users[i].path);
|
||||||
ret.push_back(users[i].lightmap);
|
ret.push_back(users[i].lightmap);
|
||||||
|
ret.push_back(users[i].instance_index);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -209,6 +217,7 @@ void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, List<PlotMesh> &plo
|
||||||
pm.local_xform = xf;
|
pm.local_xform = xf;
|
||||||
pm.mesh = mesh;
|
pm.mesh = mesh;
|
||||||
pm.path = get_path_to(mi);
|
pm.path = get_path_to(mi);
|
||||||
|
pm.instance_idx = -1;
|
||||||
for (int i = 0; i < mesh->get_surface_count(); i++) {
|
for (int i = 0; i < mesh->get_surface_count(); i++) {
|
||||||
pm.instance_materials.push_back(mi->get_surface_material(i));
|
pm.instance_materials.push_back(mi->get_surface_material(i));
|
||||||
}
|
}
|
||||||
|
@ -219,6 +228,26 @@ void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, List<PlotMesh> &plo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spatial *s = Object::cast_to<Spatial>(p_at_node);
|
||||||
|
|
||||||
|
if (!mi && s) {
|
||||||
|
Array meshes = p_at_node->call("get_bake_meshes");
|
||||||
|
if (meshes.size() && (meshes.size() & 1) == 0) {
|
||||||
|
Transform xf = get_global_transform().affine_inverse() * s->get_global_transform();
|
||||||
|
for (int i = 0; i < meshes.size(); i += 2) {
|
||||||
|
PlotMesh pm;
|
||||||
|
Transform mesh_xf = meshes[i + 1];
|
||||||
|
pm.local_xform = xf * mesh_xf;
|
||||||
|
pm.mesh = meshes[i];
|
||||||
|
pm.instance_idx = i / 2;
|
||||||
|
if (!pm.mesh.is_valid())
|
||||||
|
continue;
|
||||||
|
pm.path = get_path_to(s);
|
||||||
|
plot_meshes.push_back(pm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Light *light = Object::cast_to<Light>(p_at_node);
|
Light *light = Object::cast_to<Light>(p_at_node);
|
||||||
|
|
||||||
if (light && light->get_bake_mode() != Light::BAKE_DISABLED) {
|
if (light && light->get_bake_mode() != Light::BAKE_DISABLED) {
|
||||||
|
@ -477,7 +506,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi
|
||||||
if (set_path) {
|
if (set_path) {
|
||||||
tex->set_path(image_path);
|
tex->set_path(image_path);
|
||||||
}
|
}
|
||||||
new_light_data->add_user(E->get().path, tex);
|
new_light_data->add_user(E->get().path, tex, E->get().instance_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,12 +576,21 @@ void BakedLightmap::_assign_lightmaps() {
|
||||||
ERR_FAIL_COND(!light_data.is_valid());
|
ERR_FAIL_COND(!light_data.is_valid());
|
||||||
|
|
||||||
for (int i = 0; i < light_data->get_user_count(); i++) {
|
for (int i = 0; i < light_data->get_user_count(); i++) {
|
||||||
Node *node = get_node(light_data->get_user_path(i));
|
|
||||||
VisualInstance *vi = Object::cast_to<VisualInstance>(node);
|
|
||||||
ERR_CONTINUE(!vi);
|
|
||||||
Ref<Texture> lightmap = light_data->get_user_lightmap(i);
|
Ref<Texture> lightmap = light_data->get_user_lightmap(i);
|
||||||
ERR_CONTINUE(!lightmap.is_valid());
|
ERR_CONTINUE(!lightmap.is_valid());
|
||||||
VS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), lightmap->get_rid());
|
|
||||||
|
Node *node = get_node(light_data->get_user_path(i));
|
||||||
|
int instance_idx = light_data->get_user_instance(i);
|
||||||
|
if (instance_idx >= 0) {
|
||||||
|
RID instance = node->call("get_bake_mesh_instance", instance_idx);
|
||||||
|
if (instance.is_valid()) {
|
||||||
|
VS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), lightmap->get_rid());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VisualInstance *vi = Object::cast_to<VisualInstance>(node);
|
||||||
|
ERR_CONTINUE(!vi);
|
||||||
|
VS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), lightmap->get_rid());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,9 +598,17 @@ void BakedLightmap::_clear_lightmaps() {
|
||||||
ERR_FAIL_COND(!light_data.is_valid());
|
ERR_FAIL_COND(!light_data.is_valid());
|
||||||
for (int i = 0; i < light_data->get_user_count(); i++) {
|
for (int i = 0; i < light_data->get_user_count(); i++) {
|
||||||
Node *node = get_node(light_data->get_user_path(i));
|
Node *node = get_node(light_data->get_user_path(i));
|
||||||
VisualInstance *vi = Object::cast_to<VisualInstance>(node);
|
int instance_idx = light_data->get_user_instance(i);
|
||||||
ERR_CONTINUE(!vi);
|
if (instance_idx >= 0) {
|
||||||
VS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), RID(), RID());
|
RID instance = node->call("get_bake_mesh_instance", instance_idx);
|
||||||
|
if (instance.is_valid()) {
|
||||||
|
VS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), RID());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VisualInstance *vi = Object::cast_to<VisualInstance>(node);
|
||||||
|
ERR_CONTINUE(!vi);
|
||||||
|
VS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), RID());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ class BakedLightmapData : public Resource {
|
||||||
|
|
||||||
NodePath path;
|
NodePath path;
|
||||||
Ref<Texture> lightmap;
|
Ref<Texture> lightmap;
|
||||||
|
int instance_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector<User> users;
|
Vector<User> users;
|
||||||
|
@ -44,10 +45,11 @@ public:
|
||||||
void set_energy(float p_energy);
|
void set_energy(float p_energy);
|
||||||
float get_energy() const;
|
float get_energy() const;
|
||||||
|
|
||||||
void add_user(const NodePath &p_path, const Ref<Texture> &p_lightmap);
|
void add_user(const NodePath &p_path, const Ref<Texture> &p_lightmap, int p_instance = -1);
|
||||||
int get_user_count() const;
|
int get_user_count() const;
|
||||||
NodePath get_user_path(int p_user) const;
|
NodePath get_user_path(int p_user) const;
|
||||||
Ref<Texture> get_user_lightmap(int p_user) const;
|
Ref<Texture> get_user_lightmap(int p_user) const;
|
||||||
|
int get_user_instance(int p_user) const;
|
||||||
void clear_users();
|
void clear_users();
|
||||||
|
|
||||||
virtual RID get_rid() const;
|
virtual RID get_rid() const;
|
||||||
|
@ -111,6 +113,7 @@ private:
|
||||||
Ref<Mesh> mesh;
|
Ref<Mesh> mesh;
|
||||||
Transform local_xform;
|
Transform local_xform;
|
||||||
NodePath path;
|
NodePath path;
|
||||||
|
int instance_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlotLight {
|
struct PlotLight {
|
||||||
|
|
|
@ -833,11 +833,13 @@ void VoxelLightBaker::plot_light_directional(const Vector3 &p_direction, const C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
if (p_direct) {
|
||||||
float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct
|
for (int i = 0; i < 6; i++) {
|
||||||
light->direct_accum[i][0] += light_energy.x * s;
|
float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct
|
||||||
light->direct_accum[i][1] += light_energy.y * s;
|
light->direct_accum[i][0] += light_energy.x * s;
|
||||||
light->direct_accum[i][2] += light_energy.z * s;
|
light->direct_accum[i][1] += light_energy.y * s;
|
||||||
|
light->direct_accum[i][2] += light_energy.z * s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
success_count++;
|
success_count++;
|
||||||
}
|
}
|
||||||
|
@ -962,11 +964,13 @@ void VoxelLightBaker::plot_light_omni(const Vector3 &p_pos, const Color &p_color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
if (p_direct) {
|
||||||
float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct
|
for (int i = 0; i < 6; i++) {
|
||||||
light->direct_accum[i][0] += light_energy.x * s * att;
|
float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct
|
||||||
light->direct_accum[i][1] += light_energy.y * s * att;
|
light->direct_accum[i][0] += light_energy.x * s * att;
|
||||||
light->direct_accum[i][2] += light_energy.z * s * att;
|
light->direct_accum[i][1] += light_energy.y * s * att;
|
||||||
|
light->direct_accum[i][2] += light_energy.z * s * att;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1095,11 +1099,13 @@ void VoxelLightBaker::plot_light_spot(const Vector3 &p_pos, const Vector3 &p_axi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
if (p_direct) {
|
||||||
float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct
|
for (int i = 0; i < 6; i++) {
|
||||||
light->direct_accum[i][0] += light_energy.x * s * att;
|
float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct
|
||||||
light->direct_accum[i][1] += light_energy.y * s * att;
|
light->direct_accum[i][0] += light_energy.x * s * att;
|
||||||
light->direct_accum[i][2] += light_energy.z * s * att;
|
light->direct_accum[i][1] += light_energy.y * s * att;
|
||||||
|
light->direct_accum[i][2] += light_energy.z * s * att;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue