1/**************************************************************************/
2/* world_3d.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "world_3d.h"
32
33#include "core/config/project_settings.h"
34#include "scene/3d/camera_3d.h"
35#include "scene/3d/visible_on_screen_notifier_3d.h"
36#include "scene/resources/camera_attributes.h"
37#include "scene/resources/environment.h"
38#include "scene/scene_string_names.h"
39#include "servers/navigation_server_3d.h"
40
41void World3D::_register_camera(Camera3D *p_camera) {
42#ifndef _3D_DISABLED
43 cameras.insert(p_camera);
44#endif
45}
46
47void World3D::_remove_camera(Camera3D *p_camera) {
48#ifndef _3D_DISABLED
49 cameras.erase(p_camera);
50#endif
51}
52
53RID World3D::get_space() const {
54 if (space.is_null()) {
55 space = PhysicsServer3D::get_singleton()->space_create();
56 PhysicsServer3D::get_singleton()->space_set_active(space, true);
57 PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY, GLOBAL_GET("physics/3d/default_gravity"));
58 PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_GET("physics/3d/default_gravity_vector"));
59 PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, GLOBAL_GET("physics/3d/default_linear_damp"));
60 PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_GET("physics/3d/default_angular_damp"));
61 }
62 return space;
63}
64
65RID World3D::get_navigation_map() const {
66 if (navigation_map.is_null()) {
67 navigation_map = NavigationServer3D::get_singleton()->map_create();
68 NavigationServer3D::get_singleton()->map_set_active(navigation_map, true);
69 NavigationServer3D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_GET("navigation/3d/default_cell_size"));
70 NavigationServer3D::get_singleton()->map_set_cell_height(navigation_map, GLOBAL_GET("navigation/3d/default_cell_height"));
71 NavigationServer3D::get_singleton()->map_set_up(navigation_map, GLOBAL_GET("navigation/3d/default_up"));
72 NavigationServer3D::get_singleton()->map_set_use_edge_connections(navigation_map, GLOBAL_GET("navigation/3d/use_edge_connections"));
73 NavigationServer3D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_GET("navigation/3d/default_edge_connection_margin"));
74 NavigationServer3D::get_singleton()->map_set_link_connection_radius(navigation_map, GLOBAL_GET("navigation/3d/default_link_connection_radius"));
75 }
76 return navigation_map;
77}
78
79RID World3D::get_scenario() const {
80 return scenario;
81}
82
83void World3D::set_environment(const Ref<Environment> &p_environment) {
84 if (environment == p_environment) {
85 return;
86 }
87
88 environment = p_environment;
89 if (environment.is_valid()) {
90 RS::get_singleton()->scenario_set_environment(scenario, environment->get_rid());
91 } else {
92 RS::get_singleton()->scenario_set_environment(scenario, RID());
93 }
94
95 emit_changed();
96}
97
98Ref<Environment> World3D::get_environment() const {
99 return environment;
100}
101
102void World3D::set_fallback_environment(const Ref<Environment> &p_environment) {
103 if (fallback_environment == p_environment) {
104 return;
105 }
106
107 fallback_environment = p_environment;
108 if (fallback_environment.is_valid()) {
109 RS::get_singleton()->scenario_set_fallback_environment(scenario, p_environment->get_rid());
110 } else {
111 RS::get_singleton()->scenario_set_fallback_environment(scenario, RID());
112 }
113
114 emit_changed();
115}
116
117Ref<Environment> World3D::get_fallback_environment() const {
118 return fallback_environment;
119}
120
121void World3D::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) {
122 camera_attributes = p_camera_attributes;
123 if (camera_attributes.is_valid()) {
124 RS::get_singleton()->scenario_set_camera_attributes(scenario, camera_attributes->get_rid());
125 } else {
126 RS::get_singleton()->scenario_set_camera_attributes(scenario, RID());
127 }
128}
129
130Ref<CameraAttributes> World3D::get_camera_attributes() const {
131 return camera_attributes;
132}
133
134PhysicsDirectSpaceState3D *World3D::get_direct_space_state() {
135 return PhysicsServer3D::get_singleton()->space_get_direct_state(get_space());
136}
137
138void World3D::_bind_methods() {
139 ClassDB::bind_method(D_METHOD("get_space"), &World3D::get_space);
140 ClassDB::bind_method(D_METHOD("get_navigation_map"), &World3D::get_navigation_map);
141 ClassDB::bind_method(D_METHOD("get_scenario"), &World3D::get_scenario);
142 ClassDB::bind_method(D_METHOD("set_environment", "env"), &World3D::set_environment);
143 ClassDB::bind_method(D_METHOD("get_environment"), &World3D::get_environment);
144 ClassDB::bind_method(D_METHOD("set_fallback_environment", "env"), &World3D::set_fallback_environment);
145 ClassDB::bind_method(D_METHOD("get_fallback_environment"), &World3D::get_fallback_environment);
146 ClassDB::bind_method(D_METHOD("set_camera_attributes", "attributes"), &World3D::set_camera_attributes);
147 ClassDB::bind_method(D_METHOD("get_camera_attributes"), &World3D::get_camera_attributes);
148 ClassDB::bind_method(D_METHOD("get_direct_space_state"), &World3D::get_direct_space_state);
149 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
150 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_fallback_environment", "get_fallback_environment");
151 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes");
152 ADD_PROPERTY(PropertyInfo(Variant::RID, "space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_space");
153 ADD_PROPERTY(PropertyInfo(Variant::RID, "navigation_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_navigation_map");
154 ADD_PROPERTY(PropertyInfo(Variant::RID, "scenario", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_scenario");
155 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState3D", PROPERTY_USAGE_NONE), "", "get_direct_space_state");
156}
157
158World3D::World3D() {
159 scenario = RenderingServer::get_singleton()->scenario_create();
160}
161
162World3D::~World3D() {
163 ERR_FAIL_NULL(RenderingServer::get_singleton());
164 ERR_FAIL_NULL(PhysicsServer3D::get_singleton());
165 ERR_FAIL_NULL(NavigationServer3D::get_singleton());
166
167 RenderingServer::get_singleton()->free(scenario);
168 if (space.is_valid()) {
169 PhysicsServer3D::get_singleton()->free(space);
170 }
171 if (navigation_map.is_valid()) {
172 NavigationServer3D::get_singleton()->free(navigation_map);
173 }
174}
175