mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-23 12:26:59 +01:00
422 lines
14 KiB
C++
422 lines
14 KiB
C++
/*************************************************************************/
|
|
/* vertex_lights_3d.cpp */
|
|
/*************************************************************************/
|
|
/* This file is part of: */
|
|
/* PANDEMONIUM ENGINE */
|
|
/* https://github.com/Relintai/pandemonium_engine */
|
|
/*************************************************************************/
|
|
/* Copyright (c) 2022-present Péter Magyar. */
|
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
|
/* */
|
|
/* 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 "vertex_lights_3d_server.h"
|
|
|
|
#include "core/config/project_settings.h"
|
|
|
|
#include "scene/main/scene_tree.h"
|
|
|
|
// Defaults
|
|
Vector3i VertexLights3DServer::get_default_octant_size() const {
|
|
return _default_octant_size;
|
|
}
|
|
void VertexLights3DServer::set_default_octant_size(const Vector3i &p_size) {
|
|
_default_octant_size = p_size;
|
|
}
|
|
|
|
// Maps
|
|
RID VertexLights3DServer::map_create() {
|
|
VertexLightMap3D *map = memnew(VertexLightMap3D);
|
|
RID rid = map_owner.make_rid(map);
|
|
map->self = rid;
|
|
map->octant_size = _default_octant_size;
|
|
return rid;
|
|
}
|
|
|
|
Vector3i VertexLights3DServer::map_get_octant_size(RID p_map) const {
|
|
const VertexLightMap3D *map = map_owner.getornull(p_map);
|
|
ERR_FAIL_COND_V(map == NULL, Vector3i());
|
|
|
|
return map->octant_size;
|
|
}
|
|
void VertexLights3DServer::map_set_octant_size(RID p_map, const Vector3i &p_size) {
|
|
VertexLightMap3D *map = map_owner.getornull(p_map);
|
|
ERR_FAIL_COND(map == NULL);
|
|
|
|
map->octant_size = p_size;
|
|
map->recreate_octants();
|
|
|
|
_map_changed(map);
|
|
}
|
|
|
|
Color VertexLights3DServer::map_get_base_color(RID p_map) const {
|
|
const VertexLightMap3D *map = map_owner.getornull(p_map);
|
|
ERR_FAIL_COND_V(map == NULL, Color());
|
|
|
|
return map->base_color;
|
|
}
|
|
void VertexLights3DServer::map_set_base_color(RID p_map, const Color &p_base_color) {
|
|
VertexLightMap3D *map = map_owner.getornull(p_map);
|
|
ERR_FAIL_COND(map == NULL);
|
|
|
|
map->base_color = p_base_color;
|
|
|
|
_map_changed(map);
|
|
}
|
|
|
|
Array VertexLights3DServer::map_get_lights(RID p_map) const {
|
|
VertexLightMap3D *map = map_owner.getornull(p_map);
|
|
ERR_FAIL_COND_V(map == NULL, Array());
|
|
|
|
List<VertexLightData3D *> lights;
|
|
map->get_lights(&lights);
|
|
|
|
Array arr;
|
|
|
|
arr.resize(lights.size());
|
|
|
|
int i = 0;
|
|
for (List<VertexLightData3D *>::Element *E = lights.front(); E; E = E->next()) {
|
|
arr[i++] = E->get()->self;
|
|
}
|
|
|
|
return arr;
|
|
}
|
|
|
|
void VertexLights3DServer::map_clear(RID p_map) {
|
|
VertexLightMap3D *map = map_owner.getornull(p_map);
|
|
ERR_FAIL_COND(map == NULL);
|
|
|
|
map->clear();
|
|
|
|
_map_changed(map);
|
|
}
|
|
|
|
// Lights
|
|
RID VertexLights3DServer::light_create() {
|
|
VertexLightData3D *light = memnew(VertexLightData3D);
|
|
RID rid = light_owner.make_rid(light);
|
|
light->self = rid;
|
|
return rid;
|
|
}
|
|
|
|
RID VertexLights3DServer::light_get_map(RID p_light) {
|
|
const VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND_V(light == NULL, RID());
|
|
|
|
if (!light->map) {
|
|
return RID();
|
|
}
|
|
|
|
return light->map->self;
|
|
}
|
|
void VertexLights3DServer::light_set_map(RID p_light, RID p_map) {
|
|
VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND(light == NULL);
|
|
|
|
VertexLightMap3D *map = map_owner.getornull(p_map);
|
|
|
|
if (light->map) {
|
|
_light_changed(light);
|
|
light->map->remove_light(light);
|
|
}
|
|
|
|
if (map) {
|
|
map->add_light(light);
|
|
_light_changed(light);
|
|
}
|
|
}
|
|
|
|
bool VertexLights3DServer::light_get_is_enabled(RID p_light) {
|
|
const VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND_V(light == NULL, false);
|
|
|
|
return light->enabled;
|
|
}
|
|
void VertexLights3DServer::light_set_enabled(RID p_light, const bool p_enabled) {
|
|
VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND(light == NULL);
|
|
|
|
if (light->enabled == p_enabled) {
|
|
return;
|
|
}
|
|
|
|
light->enabled = p_enabled;
|
|
|
|
_light_enabled_changed(light);
|
|
}
|
|
|
|
Vector3 VertexLights3DServer::light_get_position(RID p_light) {
|
|
const VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND_V(light == NULL, Vector3());
|
|
|
|
return light->position;
|
|
}
|
|
void VertexLights3DServer::light_set_position(RID p_light, const Vector3 &p_position) {
|
|
VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND(light == NULL);
|
|
|
|
if (light->map) {
|
|
// This ensure the light gets moved to the proper octant
|
|
light->map->set_light_position(light, p_position);
|
|
_light_changed(light);
|
|
return;
|
|
}
|
|
|
|
light->position = p_position;
|
|
|
|
_light_changed(light);
|
|
}
|
|
|
|
real_t VertexLights3DServer::light_get_range(RID p_light) {
|
|
const VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND_V(light == NULL, 0);
|
|
|
|
return light->range;
|
|
}
|
|
void VertexLights3DServer::light_set_range(RID p_light, const real_t p_range) {
|
|
VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND(light == NULL);
|
|
|
|
light->range = p_range;
|
|
|
|
_light_changed(light);
|
|
}
|
|
|
|
real_t VertexLights3DServer::light_get_attenuation(RID p_light) {
|
|
const VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND_V(light == NULL, 0);
|
|
|
|
return light->attenuation;
|
|
}
|
|
void VertexLights3DServer::light_set_attenuation(RID p_light, const real_t p_attenuation) {
|
|
VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND(light == NULL);
|
|
|
|
light->attenuation = p_attenuation;
|
|
|
|
_light_changed(light);
|
|
}
|
|
|
|
Color VertexLights3DServer::light_get_color(RID p_light) {
|
|
const VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND_V(light == NULL, Color());
|
|
|
|
return light->color;
|
|
}
|
|
void VertexLights3DServer::light_set_color(RID p_light, const Color &p_color) {
|
|
VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND(light == NULL);
|
|
|
|
light->color = p_color;
|
|
|
|
_light_changed(light);
|
|
}
|
|
|
|
VertexLights3DServer::VertexLight3DMode VertexLights3DServer::light_get_mode(RID p_light) {
|
|
const VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND_V(light == NULL, VertexLights3DServer::VERTEX_LIGHT_3D_MODE_ADD);
|
|
|
|
return light->mode;
|
|
}
|
|
void VertexLights3DServer::light_set_mode(RID p_light, const VertexLights3DServer::VertexLight3DMode p_mode) {
|
|
VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND(light == NULL);
|
|
|
|
light->mode = p_mode;
|
|
|
|
_light_changed(light);
|
|
}
|
|
|
|
int VertexLights3DServer::light_get_item_cull_mask(RID p_light) {
|
|
const VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND_V(light == NULL, 0);
|
|
|
|
return light->item_cull_mask;
|
|
}
|
|
void VertexLights3DServer::light_set_item_cull_mask(RID p_light, const int p_item_cull_mask) {
|
|
VertexLightData3D *light = light_owner.getornull(p_light);
|
|
ERR_FAIL_COND(light == NULL);
|
|
|
|
light->item_cull_mask = p_item_cull_mask;
|
|
|
|
_light_changed(light);
|
|
}
|
|
|
|
// Sampling
|
|
|
|
Color VertexLights3DServer::sample_light_value(RID p_map, const Vector3 &p_position, const int p_item_cull_mask) {
|
|
VertexLightMap3D *map = map_owner.getornull(p_map);
|
|
ERR_FAIL_COND_V(map == NULL, Color());
|
|
|
|
return map->sample_light_value(p_position, p_item_cull_mask);
|
|
}
|
|
|
|
Color VertexLights3DServer::sample_light(RID p_map, const Vector3 &p_position, const Vector3 &p_normal, const int p_item_cull_mask) {
|
|
VertexLightMap3D *map = map_owner.getornull(p_map);
|
|
ERR_FAIL_COND_V(map == NULL, Color());
|
|
|
|
return map->sample_light(p_position, p_normal, p_item_cull_mask);
|
|
}
|
|
|
|
// Rest
|
|
|
|
void VertexLights3DServer::free(RID p_rid) {
|
|
if (!p_rid.is_valid()) {
|
|
ERR_FAIL_MSG("Invalid RID.");
|
|
return;
|
|
}
|
|
|
|
if (map_owner.owns(p_rid)) {
|
|
VertexLightMap3D *map = map_owner.get(p_rid);
|
|
|
|
map->clear();
|
|
map->self = RID();
|
|
|
|
map_owner.free(p_rid);
|
|
memdelete(map);
|
|
} else if (light_owner.owns(p_rid)) {
|
|
VertexLightData3D *light = light_owner.get(p_rid);
|
|
|
|
if (light->map) {
|
|
_light_changed(light);
|
|
light->map->remove_light(light);
|
|
}
|
|
|
|
light->self = RID();
|
|
|
|
light_owner.free(p_rid);
|
|
memdelete(light);
|
|
|
|
} else {
|
|
ERR_FAIL_MSG("Invalid RID.");
|
|
}
|
|
}
|
|
|
|
void VertexLights3DServer::init() {
|
|
call_deferred("_register_update");
|
|
}
|
|
|
|
void VertexLights3DServer::register_update() {
|
|
if (SceneTree::get_singleton()) {
|
|
if (!SceneTree::get_singleton()->is_connected("idle_frame", this, "flush_notifications")) {
|
|
SceneTree::get_singleton()->connect("idle_frame", this, "flush_notifications");
|
|
}
|
|
}
|
|
}
|
|
|
|
void VertexLights3DServer::unregister_update() {
|
|
if (SceneTree::get_singleton()) {
|
|
if (SceneTree::get_singleton()->is_connected("idle_frame", this, "flush_notifications")) {
|
|
SceneTree::get_singleton()->disconnect("idle_frame", this, "flush_notifications");
|
|
}
|
|
}
|
|
}
|
|
|
|
void VertexLights3DServer::flush_notifications() {
|
|
for (HashSet<RID>::Iterator iter = _changed_maps.begin(); iter; ++iter) {
|
|
emit_signal(_map_changed_name, iter.key());
|
|
}
|
|
|
|
_changed_maps.clear();
|
|
}
|
|
|
|
VertexLights3DServer::VertexLights3DServer() {
|
|
ERR_FAIL_COND(_self);
|
|
|
|
_self = this;
|
|
|
|
GLOBAL_DEF("vertex_lights_3d/default_octant_size", Vector3i(32, 32, 32));
|
|
_default_octant_size = GLOBAL_GET("vertex_lights_3d/default_octant_size");
|
|
|
|
_map_changed_name = "map_changed";
|
|
}
|
|
|
|
VertexLights3DServer::~VertexLights3DServer() {
|
|
_self = NULL;
|
|
}
|
|
|
|
void VertexLights3DServer::_bind_methods() {
|
|
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
|
|
|
|
ClassDB::bind_method(D_METHOD("get_default_octant_size"), &VertexLights3DServer::get_default_octant_size);
|
|
ClassDB::bind_method(D_METHOD("set_default_octant_size", "size"), &VertexLights3DServer::set_default_octant_size);
|
|
|
|
ClassDB::bind_method(D_METHOD("map_create"), &VertexLights3DServer::map_create);
|
|
|
|
ClassDB::bind_method(D_METHOD("map_get_octant_size", "map"), &VertexLights3DServer::map_get_octant_size);
|
|
ClassDB::bind_method(D_METHOD("map_set_octant_size", "map", "size"), &VertexLights3DServer::map_set_octant_size);
|
|
|
|
ClassDB::bind_method(D_METHOD("map_get_base_color", "map"), &VertexLights3DServer::map_get_base_color);
|
|
ClassDB::bind_method(D_METHOD("map_set_base_color", "map", "base_color"), &VertexLights3DServer::map_set_base_color);
|
|
|
|
ClassDB::bind_method(D_METHOD("map_get_lights", "map"), &VertexLights3DServer::map_get_lights);
|
|
|
|
ClassDB::bind_method(D_METHOD("map_clear", "map"), &VertexLights3DServer::map_clear);
|
|
|
|
// Lights
|
|
|
|
ClassDB::bind_method(D_METHOD("light_create"), &VertexLights3DServer::light_create);
|
|
|
|
ClassDB::bind_method(D_METHOD("light_get_map", "light"), &VertexLights3DServer::light_get_map);
|
|
ClassDB::bind_method(D_METHOD("light_set_map", "light", "map"), &VertexLights3DServer::light_set_map);
|
|
|
|
ClassDB::bind_method(D_METHOD("light_get_is_enabled", "light"), &VertexLights3DServer::light_get_is_enabled);
|
|
ClassDB::bind_method(D_METHOD("light_set_enabled", "light", "enabled"), &VertexLights3DServer::light_set_enabled);
|
|
|
|
ClassDB::bind_method(D_METHOD("light_get_position", "light"), &VertexLights3DServer::light_get_position);
|
|
ClassDB::bind_method(D_METHOD("light_set_position", "light", "position"), &VertexLights3DServer::light_set_position);
|
|
|
|
ClassDB::bind_method(D_METHOD("light_get_range", "light"), &VertexLights3DServer::light_get_range);
|
|
ClassDB::bind_method(D_METHOD("light_set_range", "light", "range"), &VertexLights3DServer::light_set_range);
|
|
|
|
ClassDB::bind_method(D_METHOD("light_get_attenuation", "light"), &VertexLights3DServer::light_get_attenuation);
|
|
ClassDB::bind_method(D_METHOD("light_set_attenuation", "light", "attenuation"), &VertexLights3DServer::light_set_attenuation);
|
|
|
|
ClassDB::bind_method(D_METHOD("light_get_color", "light"), &VertexLights3DServer::light_get_color);
|
|
ClassDB::bind_method(D_METHOD("light_set_color", "light", "color"), &VertexLights3DServer::light_set_color);
|
|
|
|
ClassDB::bind_method(D_METHOD("light_get_mode", "light"), &VertexLights3DServer::light_get_mode);
|
|
ClassDB::bind_method(D_METHOD("light_set_mode", "light", "mode"), &VertexLights3DServer::light_set_mode);
|
|
|
|
ClassDB::bind_method(D_METHOD("light_get_item_cull_mask", "light"), &VertexLights3DServer::light_get_item_cull_mask);
|
|
ClassDB::bind_method(D_METHOD("light_set_item_cull_mask", "light", "item_cull_mask"), &VertexLights3DServer::light_set_item_cull_mask);
|
|
|
|
// Sampling
|
|
|
|
ClassDB::bind_method(D_METHOD("sample_light_value", "map", "position", "item_cull_mask"), &VertexLights3DServer::sample_light_value, DEFVAL(1));
|
|
ClassDB::bind_method(D_METHOD("sample_light", "map", "position", "normal", "item_cull_mask"), &VertexLights3DServer::sample_light, DEFVAL(1));
|
|
|
|
// Rest, DEFVAL(0)
|
|
|
|
ClassDB::bind_method(D_METHOD("free", "rid"), &VertexLights3DServer::free);
|
|
|
|
ClassDB::bind_method(D_METHOD("_register_update"), &VertexLights3DServer::register_update);
|
|
ClassDB::bind_method(D_METHOD("flush_notifications"), &VertexLights3DServer::flush_notifications);
|
|
|
|
BIND_ENUM_CONSTANT(VERTEX_LIGHT_3D_MODE_ADD);
|
|
BIND_ENUM_CONSTANT(VERTEX_LIGHT_3D_MODE_SUB);
|
|
BIND_ENUM_CONSTANT(VERTEX_LIGHT_3D_MODE_MIX);
|
|
}
|
|
|
|
VertexLights3DServer *VertexLights3DServer::_self = NULL;
|