summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/arvr/arvr_interface.cpp5
-rw-r--r--servers/arvr/arvr_interface.h1
-rw-r--r--servers/arvr/arvr_positional_tracker.cpp15
-rw-r--r--servers/arvr/arvr_positional_tracker.h7
-rw-r--r--servers/audio/audio_stream.cpp32
-rw-r--r--servers/audio/reverb_sw.cpp3
-rw-r--r--servers/audio_server.cpp28
-rw-r--r--servers/physics/body_sw.cpp2
-rw-r--r--servers/physics/collision_object_sw.h2
-rw-r--r--servers/physics/collision_solver_sat.cpp8
-rw-r--r--servers/physics/joints/cone_twist_joint_sw.cpp4
-rw-r--r--servers/physics/physics_server_sw.cpp18
-rw-r--r--servers/physics/shape_sw.cpp2
-rw-r--r--servers/physics/space_sw.cpp39
-rw-r--r--servers/physics/space_sw.h1
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp4
-rw-r--r--servers/physics_2d/joints_2d_sw.cpp4
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp21
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp33
-rw-r--r--servers/physics_2d/space_2d_sw.cpp68
-rw-r--r--servers/physics_2d/space_2d_sw.h1
-rw-r--r--servers/physics_2d_server.cpp3
-rw-r--r--servers/physics_2d_server.h13
-rw-r--r--servers/physics_server.cpp8
-rw-r--r--servers/physics_server.h12
-rw-r--r--servers/register_server_types.cpp24
-rw-r--r--servers/visual/rasterizer.h17
-rw-r--r--servers/visual/shader_language.cpp114
-rw-r--r--servers/visual/shader_language.h144
-rw-r--r--servers/visual/visual_server_canvas.cpp55
-rw-r--r--servers/visual/visual_server_canvas.h9
-rw-r--r--servers/visual/visual_server_globals.cpp (renamed from servers/visual/visual_server_global.cpp)4
-rw-r--r--servers/visual/visual_server_globals.h (renamed from servers/visual/visual_server_global.h)8
-rw-r--r--servers/visual/visual_server_raster.cpp5
-rw-r--r--servers/visual/visual_server_raster.h6
-rw-r--r--servers/visual/visual_server_scene.cpp35
-rw-r--r--servers/visual/visual_server_scene.h2
-rw-r--r--servers/visual/visual_server_viewport.cpp88
-rw-r--r--servers/visual/visual_server_viewport.h4
-rw-r--r--servers/visual/visual_server_wrap_mt.h3
-rw-r--r--servers/visual_server.cpp20
-rw-r--r--servers/visual_server.h4
42 files changed, 566 insertions, 310 deletions
diff --git a/servers/arvr/arvr_interface.cpp b/servers/arvr/arvr_interface.cpp
index 3e59daff6c..686ad0ba9b 100644
--- a/servers/arvr/arvr_interface.cpp
+++ b/servers/arvr/arvr_interface.cpp
@@ -123,6 +123,11 @@ ARVRInterface::ARVRInterface() {
ARVRInterface::~ARVRInterface(){};
+// optional render to external texture which enhances performance on those platforms that require us to submit our end result into special textures.
+unsigned int ARVRInterface::get_external_texture_for_eye(ARVRInterface::Eyes p_eye) {
+ return 0;
+};
+
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
bool ARVRInterface::get_anchor_detection_is_enabled() const {
return false;
diff --git a/servers/arvr/arvr_interface.h b/servers/arvr/arvr_interface.h
index 6908f3006a..8459a82388 100644
--- a/servers/arvr/arvr_interface.h
+++ b/servers/arvr/arvr_interface.h
@@ -108,6 +108,7 @@ public:
virtual bool is_stereo() = 0; /* returns true if this interface requires stereo rendering (for VR HMDs) or mono rendering (for mobile AR) */
virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) = 0; /* get each eyes camera transform, also implement EYE_MONO */
virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) = 0; /* get each eyes projection matrix */
+ virtual unsigned int get_external_texture_for_eye(ARVRInterface::Eyes p_eye); /* if applicable return external texture to render to */
virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) = 0; /* output the left or right eye */
virtual void process() = 0;
diff --git a/servers/arvr/arvr_positional_tracker.cpp b/servers/arvr/arvr_positional_tracker.cpp
index b96e9596f3..aabe617a8a 100644
--- a/servers/arvr/arvr_positional_tracker.cpp
+++ b/servers/arvr/arvr_positional_tracker.cpp
@@ -46,6 +46,7 @@ void ARVRPositionalTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_position"), &ARVRPositionalTracker::get_position);
ClassDB::bind_method(D_METHOD("get_hand"), &ARVRPositionalTracker::get_hand);
ClassDB::bind_method(D_METHOD("get_transform", "adjust_by_reference_frame"), &ARVRPositionalTracker::get_transform);
+ ClassDB::bind_method(D_METHOD("get_mesh"), &ARVRPositionalTracker::get_mesh);
// these functions we don't want to expose to normal users but do need to be callable from GDNative
ClassDB::bind_method(D_METHOD("_set_type", "type"), &ARVRPositionalTracker::set_type);
@@ -53,7 +54,7 @@ void ARVRPositionalTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_joy_id", "joy_id"), &ARVRPositionalTracker::set_joy_id);
ClassDB::bind_method(D_METHOD("_set_orientation", "orientation"), &ARVRPositionalTracker::set_orientation);
ClassDB::bind_method(D_METHOD("_set_rw_position", "rw_position"), &ARVRPositionalTracker::set_rw_position);
-
+ ClassDB::bind_method(D_METHOD("_set_mesh", "mesh"), &ARVRPositionalTracker::set_mesh);
ClassDB::bind_method(D_METHOD("get_rumble"), &ARVRPositionalTracker::get_rumble);
ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &ARVRPositionalTracker::set_rumble);
@@ -154,6 +155,18 @@ Vector3 ARVRPositionalTracker::get_rw_position() const {
return rw_position;
};
+void ARVRPositionalTracker::set_mesh(const Ref<Mesh> &p_mesh) {
+ _THREAD_SAFE_METHOD_
+
+ mesh = p_mesh;
+};
+
+Ref<Mesh> ARVRPositionalTracker::get_mesh() const {
+ _THREAD_SAFE_METHOD_
+
+ return mesh;
+};
+
ARVRPositionalTracker::TrackerHand ARVRPositionalTracker::get_hand() const {
return hand;
};
diff --git a/servers/arvr/arvr_positional_tracker.h b/servers/arvr/arvr_positional_tracker.h
index 7cb9486f59..0d6a69540f 100644
--- a/servers/arvr/arvr_positional_tracker.h
+++ b/servers/arvr/arvr_positional_tracker.h
@@ -32,6 +32,7 @@
#define ARVR_POSITIONAL_TRACKER_H
#include "core/os/thread_safe.h"
+#include "scene/resources/mesh.h"
#include "servers/arvr_server.h"
/**
@@ -40,9 +41,6 @@
The positional tracker object as an object that represents the position and orientation of a tracked object like a controller or headset.
An AR/VR Interface will registered the trackers it manages with our AR/VR server and update its position and orientation.
This is where potentially additional AR/VR interfaces may be active as there are AR/VR SDKs that solely deal with positional tracking.
-
- @TODO:
- - create subclass of spatial node that uses one of our positional trackers to automatically determine its position
*/
class ARVRPositionalTracker : public Object {
@@ -65,6 +63,7 @@ private:
Basis orientation; // our orientation
bool tracks_position; // do we track position?
Vector3 rw_position; // our position "in the real world, so without world_scale applied"
+ Ref<Mesh> mesh; // when available, a mesh that can be used to render this tracker
TrackerHand hand; // if known, the hand this tracker is held in
real_t rumble; // rumble strength, 0.0 is off, 1.0 is maximum, note that we only record here, arvr_interface is responsible for execution
@@ -91,6 +90,8 @@ public:
void set_hand(const ARVRPositionalTracker::TrackerHand p_hand);
real_t get_rumble() const;
void set_rumble(real_t p_rumble);
+ void set_mesh(const Ref<Mesh> &p_mesh);
+ Ref<Mesh> get_mesh() const;
Transform get_transform(bool p_adjust_by_reference_frame) const;
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 51b9d5a4a2..1a6430c499 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -83,8 +83,8 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
_mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN);
} else {
//fill with silence, not playing
- for (int i = 0; i < INTERNAL_BUFFER_LEN; ++i) {
- internal_buffer[i + 4] = AudioFrame(0, 0);
+ for (int j = 0; j < INTERNAL_BUFFER_LEN; ++j) {
+ internal_buffer[j + 4] = AudioFrame(0, 0);
}
}
mix_offset -= (INTERNAL_BUFFER_LEN << FP_BITS);
@@ -138,7 +138,7 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer();
unsigned int input_size = AudioDriver::get_singleton()->get_input_size();
int mix_rate = AudioDriver::get_singleton()->get_mix_rate();
- int playback_delay = MIN(((50 * mix_rate) / 1000) * 2, buf.size() >> 1);
+ unsigned int playback_delay = MIN(((50 * mix_rate) / 1000) * 2, buf.size() >> 1);
#ifdef DEBUG_ENABLED
unsigned int input_position = AudioDriver::get_singleton()->get_input_position();
#endif
@@ -150,13 +150,13 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
input_ofs = 0;
} else {
for (int i = 0; i < p_frames; i++) {
- if (input_size > input_ofs) {
+ if (input_size > input_ofs && (int)input_ofs < buf.size()) {
float l = (buf[input_ofs++] >> 16) / 32768.f;
- if (input_ofs >= buf.size()) {
+ if ((int)input_ofs >= buf.size()) {
input_ofs = 0;
}
float r = (buf[input_ofs++] >> 16) / 32768.f;
- if (input_ofs >= buf.size()) {
+ if ((int)input_ofs >= buf.size()) {
input_ofs = 0;
}
@@ -168,7 +168,7 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
}
#ifdef DEBUG_ENABLED
- if (input_ofs > input_position && (input_ofs - input_position) < (p_frames * 2)) {
+ if (input_ofs > input_position && (int)(input_ofs - input_position) < (p_frames * 2)) {
print_verbose(String(get_class_name()) + " buffer underrun: input_position=" + itos(input_position) + " input_ofs=" + itos(input_ofs) + " input_size=" + itos(input_size));
}
#endif
@@ -186,6 +186,10 @@ float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() {
void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
+ if (active) {
+ return;
+ }
+
if (!GLOBAL_GET("audio/enable_audio_input")) {
WARN_PRINTS("Need to enable Project settings > Audio > Enable Audio Input option to use capturing.");
return;
@@ -193,15 +197,17 @@ void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
input_ofs = 0;
- AudioDriver::get_singleton()->capture_start();
-
- active = true;
- _begin_resample();
+ if (AudioDriver::get_singleton()->capture_start() == OK) {
+ active = true;
+ _begin_resample();
+ }
}
void AudioStreamPlaybackMicrophone::stop() {
- AudioDriver::get_singleton()->capture_stop();
- active = false;
+ if (active) {
+ AudioDriver::get_singleton()->capture_stop();
+ active = false;
+ }
}
bool AudioStreamPlaybackMicrophone::is_playing() const {
diff --git a/servers/audio/reverb_sw.cpp b/servers/audio/reverb_sw.cpp
index 8adc21b406..63bf1a7eaa 100644
--- a/servers/audio/reverb_sw.cpp
+++ b/servers/audio/reverb_sw.cpp
@@ -39,9 +39,6 @@
#define rangeloop(c, min, max) \
for ((c) = (min); (c) < (max); (c)++)
-#define ABSDIFF(x, y) \
- (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
-
#define MULSHIFT_S32(Factor1, Factor2, Bits) \
((int)(((int64_t)(Factor1) * (Factor2)) >> (Bits)))
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 3b1734287a..8c092a02a2 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -90,12 +90,16 @@ void AudioDriver::input_buffer_init(int driver_buffer_frames) {
void AudioDriver::input_buffer_write(int32_t sample) {
- input_buffer.write[input_position++] = sample;
- if (input_position >= input_buffer.size()) {
- input_position = 0;
- }
- if (input_size < input_buffer.size()) {
- input_size++;
+ if ((int)input_position < input_buffer.size()) {
+ input_buffer.write[input_position++] = sample;
+ if ((int)input_position >= input_buffer.size()) {
+ input_position = 0;
+ }
+ if ((int)input_size < input_buffer.size()) {
+ input_size++;
+ }
+ } else {
+ WARN_PRINTS("input_buffer_write: Invalid input_position=" + itos(input_position) + " input_buffer.size()=" + itos(input_buffer.size()));
}
}
@@ -145,6 +149,8 @@ AudioDriver::AudioDriver() {
_last_mix_time = 0;
_mix_amount = 0;
+ input_position = 0;
+ input_size = 0;
#ifdef DEBUG_ENABLED
prof_time = 0;
@@ -253,11 +259,13 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
float l = CLAMP(buf[from + j].l, -1.0, 1.0);
int32_t vl = l * ((1 << 20) - 1);
- p_buffer[(from_buf + j) * (cs * 2) + k * 2 + 0] = vl << 11;
+ int32_t vl2 = (vl < 0 ? -1 : 1) * (ABS(vl) << 11);
+ p_buffer[(from_buf + j) * (cs * 2) + k * 2 + 0] = vl2;
float r = CLAMP(buf[from + j].r, -1.0, 1.0);
int32_t vr = r * ((1 << 20) - 1);
- p_buffer[(from_buf + j) * (cs * 2) + k * 2 + 1] = vr << 11;
+ int32_t vr2 = (vr < 0 ? -1 : 1) * (ABS(vr) << 11);
+ p_buffer[(from_buf + j) * (cs * 2) + k * 2 + 1] = vr2;
}
} else {
@@ -977,7 +985,7 @@ void AudioServer::update() {
uint64_t driver_time = AudioDriver::get_singleton()->get_profiling_time();
uint64_t server_time = prof_time;
- // Substract the server time from the driver time
+ // Subtract the server time from the driver time
if (driver_time > server_time)
driver_time -= server_time;
@@ -995,7 +1003,7 @@ void AudioServer::update() {
values.push_back(String(bus->name) + bus->effects[j].effect->get_name());
values.push_back(USEC_TO_SEC(bus->effects[j].prof_time));
- // Substract the effect time from the driver and server times
+ // Subtract the effect time from the driver and server times
if (driver_time > bus->effects[j].prof_time)
driver_time -= bus->effects[j].prof_time;
if (server_time > bus->effects[j].prof_time)
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index 23f16c246e..f0fbbafe1c 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -652,7 +652,7 @@ void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) {
linear_velocity=(p_xform.origin - get_transform().origin)/p_step;
//compute a FAKE angular velocity, not so easy
- Matrix3 rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized();
+ Basis rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized();
Vector3 axis;
real_t angle;
diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h
index 6e6b66dac2..5c14d5aaf9 100644
--- a/servers/physics/collision_object_sw.h
+++ b/servers/physics/collision_object_sw.h
@@ -130,7 +130,7 @@ public:
_FORCE_INLINE_ const Transform &get_shape_transform(int p_index) const { return shapes[p_index].xform; }
_FORCE_INLINE_ const Transform &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
_FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
- _FORCE_INLINE_ const real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; }
+ _FORCE_INLINE_ real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; }
_FORCE_INLINE_ Transform get_transform() const { return transform; }
_FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; }
diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp
index fd919343f0..baf7431e28 100644
--- a/servers/physics/collision_solver_sat.cpp
+++ b/servers/physics/collision_solver_sat.cpp
@@ -821,9 +821,9 @@ static void _collision_box_capsule(const ShapeSW *p_a, const Transform &p_transf
// test edges of A
- for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
- Vector3 axis = point_axis.cross(p_transform_a.basis.get_axis(i)).cross(p_transform_a.basis.get_axis(i)).normalized();
+ Vector3 axis = point_axis.cross(p_transform_a.basis.get_axis(j)).cross(p_transform_a.basis.get_axis(j)).normalized();
if (!separator.test_axis(axis))
return;
@@ -1337,7 +1337,7 @@ static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a, const T
return;
}
}
- //edge-vertex( hsell)
+ //edge-vertex (shell)
for (int i = 0; i < edge_count_A; i++) {
@@ -1438,7 +1438,7 @@ static void _collision_convex_polygon_face(const ShapeSW *p_a, const Transform &
return;
}
}
- //edge-vertex( hsell)
+ //edge-vertex (shell)
for (int i = 0; i < edge_count; i++) {
diff --git a/servers/physics/joints/cone_twist_joint_sw.cpp b/servers/physics/joints/cone_twist_joint_sw.cpp
index 05778ee9b0..268b9eefeb 100644
--- a/servers/physics/joints/cone_twist_joint_sw.cpp
+++ b/servers/physics/joints/cone_twist_joint_sw.cpp
@@ -205,9 +205,9 @@ bool ConeTwistJointSW::setup(real_t p_timestep) {
// Twist limits
if (m_twistSpan >= real_t(0.)) {
- Vector3 b2Axis2 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(1));
+ Vector3 b2Axis22 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(1));
Quat rotationArc = Quat(b2Axis1, b1Axis1);
- Vector3 TwistRef = rotationArc.xform(b2Axis2);
+ Vector3 TwistRef = rotationArc.xform(b2Axis22);
real_t twist = atan2fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2));
real_t lockedFreeFactor = (m_twistSpan > real_t(0.05f)) ? m_limitSoftness : real_t(0.);
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 2975ae9453..36d18e8901 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -40,10 +40,10 @@
#include "joints/pin_joint_sw.h"
#include "joints/slider_joint_sw.h"
-#define FLUSH_QUERY_CHECK \
- if (flushing_queries) { \
- ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred()/set_deferred() to change monitoring state instead"); \
- ERR_FAIL(); \
+#define FLUSH_QUERY_CHECK(m_object) \
+ if (m_object->get_space() && flushing_queries) { \
+ ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead"); \
+ ERR_FAIL(); \
}
RID PhysicsServerSW::shape_create(ShapeType p_shape) {
@@ -358,11 +358,10 @@ void PhysicsServerSW::area_clear_shapes(RID p_area) {
void PhysicsServerSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
- FLUSH_QUERY_CHECK
-
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count());
+ FLUSH_QUERY_CHECK(area);
area->set_shape_as_disabled(p_shape_idx, p_disabled);
}
@@ -443,10 +442,9 @@ void PhysicsServerSW::area_set_collision_mask(RID p_area, uint32_t p_mask) {
void PhysicsServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
- FLUSH_QUERY_CHECK
-
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
+ FLUSH_QUERY_CHECK(area);
area->set_monitorable(p_monitorable);
}
@@ -592,11 +590,11 @@ RID PhysicsServerSW::body_get_shape(RID p_body, int p_shape_idx) const {
void PhysicsServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
- FLUSH_QUERY_CHECK
-
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
+
body->set_shape_as_disabled(p_shape_idx, p_disabled);
}
diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp
index fdc5eccc5a..d40de669fd 100644
--- a/servers/physics/shape_sw.cpp
+++ b/servers/physics/shape_sw.cpp
@@ -32,7 +32,7 @@
#include "core/math/geometry.h"
#include "core/math/quick_hull.h"
-#include "core/sort.h"
+#include "core/sort_array.h"
#define _POINT_SNAP 0.001953125
#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.0002
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index 1087cd2483..4ab92715f4 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -277,7 +277,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform
real_t hi = 1;
Vector3 mnormal = p_motion.normalized();
- for (int i = 0; i < 8; i++) { //steps should be customizable..
+ for (int j = 0; j < 8; j++) { //steps should be customizable..
real_t ofs = (low + hi) * 0.5;
@@ -387,6 +387,7 @@ struct _RestCallbackData {
Vector3 best_contact;
Vector3 best_normal;
real_t best_len;
+ real_t min_allowed_depth;
};
static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) {
@@ -395,6 +396,8 @@ static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B,
Vector3 contact_rel = p_point_B - p_point_A;
real_t len = contact_rel.length();
+ if (len < rd->min_allowed_depth)
+ return;
if (len <= rd->best_len)
return;
@@ -418,6 +421,7 @@ bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_
rcd.best_len = 0;
rcd.best_object = NULL;
rcd.best_shape = 0;
+ rcd.min_allowed_depth = space->test_motion_min_contact_depth;
for (int i = 0; i < amount; i++) {
@@ -593,7 +597,6 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
bool collided = false;
int amount = _cull_aabb_for_body(p_body, body_aabb);
- int ray_index = 0;
for (int j = 0; j < p_body->get_shape_count(); j++) {
if (p_body->is_shape_set_as_disabled(j))
@@ -627,7 +630,19 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
collided = true;
}
- if (ray_index < p_result_max) {
+ int ray_index = -1; //reuse shape
+ for (int k = 0; k < rays_found; k++) {
+ if (r_results[ray_index].collision_local_shape == j) {
+ ray_index = k;
+ }
+ }
+
+ if (ray_index == -1 && rays_found < p_result_max) {
+ ray_index = rays_found;
+ rays_found++;
+ }
+
+ if (ray_index != -1) {
PhysicsServer::SeparationResult &result = r_results[ray_index];
for (int k = 0; k < cbk.amount; k++) {
@@ -642,9 +657,10 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
result.collision_depth = depth;
result.collision_point = b;
result.collision_normal = (b - a).normalized();
- result.collision_local_shape = shape_idx;
+ result.collision_local_shape = j;
result.collider = col_obj->get_self();
result.collider_id = col_obj->get_instance_id();
+ result.collider_shape = shape_idx;
//result.collider_metadata = col_obj->get_shape_metadata(shape_idx);
if (col_obj->get_type() == CollisionObjectSW::TYPE_BODY) {
BodySW *body = (BodySW *)col_obj;
@@ -658,12 +674,8 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
}
}
}
-
- ray_index++;
}
- rays_found = MAX(ray_index, rays_found);
-
if (!collided || recover_motion == Vector3()) {
break;
}
@@ -717,6 +729,11 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
}
if (!shapes_found) {
+ if (r_result) {
+ *r_result = PhysicsServer::MotionResult();
+ r_result->motion = p_motion;
+ }
+
return false;
}
@@ -855,7 +872,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
real_t hi = 1;
Vector3 mnormal = p_motion.normalized();
- for (int i = 0; i < 8; i++) { //steps should be customizable..
+ for (int k = 0; k < 8; k++) { //steps should be customizable..
real_t ofs = (low + hi) * 0.5;
@@ -924,6 +941,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
rcd.best_len = 0;
rcd.best_object = NULL;
rcd.best_shape = 0;
+ rcd.min_allowed_depth = test_motion_min_contact_depth;
Transform body_shape_xform = ugt * p_body->get_shape_transform(best_shape);
ShapeSW *body_shape = p_body->get_shape(best_shape);
@@ -1148,6 +1166,7 @@ void SpaceSW::set_param(PhysicsServer::SpaceParameter p_param, real_t p_value) {
case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep = p_value; break;
case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: body_angular_velocity_damp_ratio = p_value; break;
case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias = p_value; break;
+ case PhysicsServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: test_motion_min_contact_depth = p_value; break;
}
}
@@ -1163,6 +1182,7 @@ real_t SpaceSW::get_param(PhysicsServer::SpaceParameter p_param) const {
case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep;
case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: return body_angular_velocity_damp_ratio;
case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias;
+ case PhysicsServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: return test_motion_min_contact_depth;
}
return 0;
}
@@ -1198,6 +1218,7 @@ SpaceSW::SpaceSW() {
contact_recycle_radius = 0.01;
contact_max_separation = 0.05;
contact_max_allowed_penetration = 0.01;
+ test_motion_min_contact_depth = 0.00001;
constraint_bias = 0.01;
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1);
diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h
index ae6f349e51..3aaa552845 100644
--- a/servers/physics/space_sw.h
+++ b/servers/physics/space_sw.h
@@ -96,6 +96,7 @@ private:
real_t contact_max_separation;
real_t contact_max_allowed_penetration;
real_t constraint_bias;
+ real_t test_motion_min_contact_depth;
enum {
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index ccdaf0b508..46ea0fd65d 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -303,7 +303,7 @@ bool BodyPair2DSW::setup(real_t p_step) {
Contact &c = contacts[i];
if (!c.reused)
continue;
- if (c.normal.dot(direction) < 0)
+ if (c.normal.dot(direction) > 0) //greater (normal inverted)
continue;
valid = true;
@@ -326,7 +326,7 @@ bool BodyPair2DSW::setup(real_t p_step) {
Contact &c = contacts[i];
if (!c.reused)
continue;
- if (c.normal.dot(direction) < 0)
+ if (c.normal.dot(direction) < 0) //less (normal ok)
continue;
valid = true;
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp
index 5c2242c4c5..954b0fa3ea 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/joints_2d_sw.cpp
@@ -299,9 +299,7 @@ bool GrooveJoint2DSW::setup(real_t p_step) {
Vector2 delta = (B->get_transform().get_origin() + rB) - (A->get_transform().get_origin() + rA);
- // FIXME: We used to do this assignment and then override it with 0.001 right after. Investigate why.
- //real_t _b = get_bias();
- real_t _b = 0.001;
+ real_t _b = get_bias();
gbias = (delta * -(_b == 0 ? space->get_constraint_bias() : _b) * (1.0 / p_step)).clamped(get_max_bias());
// apply accumulated impulse
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index 4d1c56b843..283d20876d 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -36,8 +36,8 @@
#include "core/project_settings.h"
#include "core/script_language.h"
-#define FLUSH_QUERY_CHECK \
- if (flushing_queries) { \
+#define FLUSH_QUERY_CHECK(m_object) \
+ if (m_object->get_space() && flushing_queries) { \
ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead"); \
ERR_FAIL(); \
}
@@ -410,12 +410,11 @@ void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, co
void Physics2DServerSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) {
- FLUSH_QUERY_CHECK
-
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
-
ERR_FAIL_INDEX(p_shape, area->get_shape_count());
+ FLUSH_QUERY_CHECK(area);
+
area->set_shape_as_disabled(p_shape, p_disabled);
}
@@ -550,10 +549,9 @@ void Physics2DServerSW::area_set_pickable(RID p_area, bool p_pickable) {
void Physics2DServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
- FLUSH_QUERY_CHECK
-
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
+ FLUSH_QUERY_CHECK(area);
area->set_monitorable(p_monitorable);
}
@@ -630,10 +628,9 @@ RID Physics2DServerSW::body_get_space(RID p_body) const {
void Physics2DServerSW::body_set_mode(RID p_body, BodyMode p_mode) {
- FLUSH_QUERY_CHECK
-
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
+ FLUSH_QUERY_CHECK(body);
body->set_mode(p_mode);
};
@@ -734,12 +731,10 @@ void Physics2DServerSW::body_clear_shapes(RID p_body) {
void Physics2DServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
- FLUSH_QUERY_CHECK
-
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
-
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
body->set_shape_as_disabled(p_shape_idx, p_disabled);
}
@@ -747,8 +742,8 @@ void Physics2DServerSW::body_set_shape_as_one_way_collision(RID p_body, int p_sh
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
-
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
body->set_shape_as_one_way_collision(p_shape_idx, p_enable, p_margin);
}
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index 558700f400..56b87f620c 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -31,7 +31,7 @@
#include "shape_2d_sw.h"
#include "core/math/geometry.h"
-#include "core/sort.h"
+#include "core/sort_array.h"
void Shape2DSW::configure(const Rect2 &p_aabb) {
aabb = p_aabb;
@@ -369,8 +369,11 @@ void RectangleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_suppor
}
bool RectangleShape2DSW::contains_point(const Vector2 &p_point) const {
-
- return Math::abs(p_point.x) < half_extents.x && Math::abs(p_point.y) < half_extents.y;
+ float x = p_point.x;
+ float y = p_point.y;
+ float edge_x = half_extents.x;
+ float edge_y = half_extents.y;
+ return (x >= -edge_x) && (x < edge_x) && (y >= -edge_y) && (y < edge_y);
}
bool RectangleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
@@ -775,22 +778,22 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Ve
while (true) {
uint32_t node = stack[level] & NODE_IDX_MASK;
- const BVH &b = bvhptr[node];
+ const BVH &bvh = bvhptr[node];
bool done = false;
switch (stack[level] >> VISITED_BIT_SHIFT) {
case TEST_AABB_BIT: {
- bool valid = b.aabb.intersects_segment(p_begin, p_end);
+ bool valid = bvh.aabb.intersects_segment(p_begin, p_end);
if (!valid) {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
} else {
- if (b.left < 0) {
+ if (bvh.left < 0) {
- const Segment &s = segmentptr[b.right];
+ const Segment &s = segmentptr[bvh.right];
Vector2 a = pointptr[s.points[0]];
Vector2 b = pointptr[s.points[1]];
@@ -820,14 +823,14 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Ve
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.left | TEST_AABB_BIT;
+ stack[level + 1] = bvh.left | TEST_AABB_BIT;
level++;
}
continue;
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.right | TEST_AABB_BIT;
+ stack[level + 1] = bvh.right | TEST_AABB_BIT;
level++;
}
continue;
@@ -1025,21 +1028,21 @@ void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, Callback p_callbac
while (true) {
uint32_t node = stack[level] & NODE_IDX_MASK;
- const BVH &b = bvhptr[node];
+ const BVH &bvh = bvhptr[node];
switch (stack[level] >> VISITED_BIT_SHIFT) {
case TEST_AABB_BIT: {
- bool valid = p_local_aabb.intersects(b.aabb);
+ bool valid = p_local_aabb.intersects(bvh.aabb);
if (!valid) {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
} else {
- if (b.left < 0) {
+ if (bvh.left < 0) {
- const Segment &s = segmentptr[b.right];
+ const Segment &s = segmentptr[bvh.right];
Vector2 a = pointptr[s.points[0]];
Vector2 b = pointptr[s.points[1]];
@@ -1058,14 +1061,14 @@ void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, Callback p_callbac
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.left | TEST_AABB_BIT;
+ stack[level + 1] = bvh.left | TEST_AABB_BIT;
level++;
}
continue;
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.right | TEST_AABB_BIT;
+ stack[level + 1] = bvh.right | TEST_AABB_BIT;
level++;
}
continue;
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 5ed70803ed..831764b40c 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -280,7 +280,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor
real_t hi = 1;
Vector2 mnormal = p_motion.normalized();
- for (int i = 0; i < 8; i++) { //steps should be customizable..
+ for (int j = 0; j < 8; j++) { //steps should be customizable..
real_t ofs = (low + hi) * 0.5;
@@ -375,6 +375,7 @@ struct _RestCallbackData2D {
real_t best_len;
Vector2 valid_dir;
real_t valid_depth;
+ real_t min_allowed_depth;
};
static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) {
@@ -390,6 +391,10 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B,
Vector2 contact_rel = p_point_B - p_point_A;
real_t len = contact_rel.length();
+
+ if (len < rd->min_allowed_depth)
+ return;
+
if (len <= rd->best_len)
return;
@@ -416,6 +421,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh
rcd.best_len = 0;
rcd.best_object = NULL;
rcd.best_shape = 0;
+ rcd.min_allowed_depth = space->test_motion_min_contact_depth;
for (int i = 0; i < amount; i++) {
@@ -512,6 +518,9 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
if (p_body->is_shape_set_as_disabled(i))
continue;
+ if (p_body->get_shape(i)->get_type() != Physics2DServer::SHAPE_RAY)
+ continue;
+
if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
shapes_found = true;
@@ -555,7 +564,6 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
bool collided = false;
int amount = _cull_aabb_for_body(p_body, body_aabb);
- int ray_index = 0;
for (int j = 0; j < p_body->get_shape_count(); j++) {
if (p_body->is_shape_set_as_disabled(j))
@@ -587,6 +595,10 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+ /*
+ * There is no point in supporting one way collisions with ray shapes, as they will always collide in the desired
+ * direction. Use a short ray shape if you want to achieve a similar effect.
+ *
if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
@@ -594,10 +606,15 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
cbk.invalid_by_dir = 0;
} else {
- cbk.valid_dir = Vector2();
- cbk.valid_depth = 0;
- cbk.invalid_by_dir = 0;
+*/
+
+ cbk.valid_dir = Vector2();
+ cbk.valid_depth = 0;
+ cbk.invalid_by_dir = 0;
+
+ /*
}
+ */
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, NULL, p_margin)) {
@@ -605,7 +622,20 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
collided = true;
}
- if (ray_index < p_result_max) {
+ int ray_index = -1; //reuse shape
+ for (int k = 0; k < rays_found; k++) {
+ if (r_results[ray_index].collision_local_shape == j) {
+ ray_index = k;
+ }
+ }
+
+ if (ray_index == -1 && rays_found < p_result_max) {
+ ray_index = rays_found;
+ rays_found++;
+ }
+
+ if (ray_index != -1) {
+
Physics2DServer::SeparationResult &result = r_results[ray_index];
for (int k = 0; k < cbk.amount; k++) {
@@ -620,7 +650,8 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
result.collision_depth = depth;
result.collision_point = b;
result.collision_normal = (b - a).normalized();
- result.collision_local_shape = shape_idx;
+ result.collision_local_shape = j;
+ result.collider_shape = shape_idx;
result.collider = col_obj->get_self();
result.collider_id = col_obj->get_instance_id();
result.collider_metadata = col_obj->get_shape_metadata(shape_idx);
@@ -635,12 +666,8 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
}
}
}
-
- ray_index++;
}
- rays_found = MAX(ray_index, rays_found);
-
if (!collided || recover_motion == Vector2()) {
break;
}
@@ -686,6 +713,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (p_body->is_shape_set_as_disabled(i))
continue;
+ if (p_exclude_raycast_shapes && p_body->get_shape(i)->get_type() == Physics2DServer::SHAPE_RAY)
+ continue;
+
if (!shapes_found) {
body_aabb = p_body->get_shape_aabb(i);
shapes_found = true;
@@ -695,6 +725,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
if (!shapes_found) {
+ if (r_result) {
+ *r_result = Physics2DServer::MotionResult();
+ r_result->motion = p_motion;
+ }
return false;
}
@@ -990,15 +1024,24 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
rcd.best_len = 0;
rcd.best_object = NULL;
rcd.best_shape = 0;
+ rcd.min_allowed_depth = test_motion_min_contact_depth;
//optimization
int from_shape = best_shape != -1 ? best_shape : 0;
int to_shape = best_shape != -1 ? best_shape + 1 : p_body->get_shape_count();
for (int j = from_shape; j < to_shape; j++) {
+
+ if (p_body->is_shape_set_as_disabled(j))
+ continue;
+
Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j);
Shape2DSW *body_shape = p_body->get_shape(j);
+ if (p_exclude_raycast_shapes && body_shape->get_type() == Physics2DServer::SHAPE_RAY) {
+ continue;
+ }
+
body_aabb.position += p_motion * unsafe;
int amount = _cull_aabb_for_body(p_body, body_aabb);
@@ -1249,6 +1292,7 @@ void Space2DSW::set_param(Physics2DServer::SpaceParameter p_param, real_t p_valu
case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: body_angular_velocity_sleep_threshold = p_value; break;
case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep = p_value; break;
case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias = p_value; break;
+ case Physics2DServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: test_motion_min_contact_depth = p_value; break;
}
}
@@ -1263,6 +1307,7 @@ real_t Space2DSW::get_param(Physics2DServer::SpaceParameter p_param) const {
case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: return body_angular_velocity_sleep_threshold;
case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep;
case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias;
+ case Physics2DServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: return test_motion_min_contact_depth;
}
return 0;
}
@@ -1299,6 +1344,7 @@ Space2DSW::Space2DSW() {
contact_recycle_radius = 1.0;
contact_max_separation = 1.5;
contact_max_allowed_penetration = 0.3;
+ test_motion_min_contact_depth = 0.005;
constraint_bias = 0.2;
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0);
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index 64f8c9e156..14c24959b7 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -104,6 +104,7 @@ private:
real_t contact_max_separation;
real_t contact_max_allowed_penetration;
real_t constraint_bias;
+ real_t test_motion_min_contact_depth;
enum {
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index 99f539ea86..3a05791f17 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -620,7 +620,7 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_clear_shapes", "body"), &Physics2DServer::body_clear_shapes);
ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disable"), &Physics2DServer::body_set_shape_disabled);
- ClassDB::bind_method(D_METHOD("body_set_shape_as_one_way_collision", "body", "shape_idx", "enable"), &Physics2DServer::body_set_shape_as_one_way_collision);
+ ClassDB::bind_method(D_METHOD("body_set_shape_as_one_way_collision", "body", "shape_idx", "enable", "margin"), &Physics2DServer::body_set_shape_as_one_way_collision);
ClassDB::bind_method(D_METHOD("body_attach_object_instance_id", "body", "id"), &Physics2DServer::body_attach_object_instance_id);
ClassDB::bind_method(D_METHOD("body_get_object_instance_id", "body"), &Physics2DServer::body_get_object_instance_id);
@@ -693,6 +693,7 @@ void Physics2DServer::_bind_methods() {
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
+ BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH);
BIND_ENUM_CONSTANT(SHAPE_LINE);
BIND_ENUM_CONSTANT(SHAPE_RAY);
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index df7fe46f76..0ba8a6605d 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -289,6 +289,7 @@ public:
SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD,
SPACE_PARAM_BODY_TIME_TO_SLEEP,
SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,
+ SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH,
};
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0;
@@ -504,6 +505,12 @@ public:
RID collider;
int collider_shape;
Variant collider_metadata;
+
+ MotionResult() {
+ collision_local_shape = 0;
+ collider_shape = 0;
+ collider_id = 0;
+ }
};
virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0;
@@ -646,6 +653,12 @@ class Physics2DServerManager {
ClassInfo(const ClassInfo &p_ci) :
name(p_ci.name),
create_callback(p_ci.create_callback) {}
+
+ ClassInfo operator=(const ClassInfo &p_ci) {
+ name = p_ci.name;
+ create_callback = p_ci.create_callback;
+ return *this;
+ }
};
static Vector<ClassInfo> physics_2d_servers;
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index 967e74d322..0629af663e 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -709,6 +709,8 @@ void PhysicsServer::_bind_methods() {
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
+ BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH);
+
BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_X);
BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Y);
BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Z);
@@ -737,11 +739,11 @@ const String PhysicsServerManager::setting_property_name("physics/3d/physics_eng
void PhysicsServerManager::on_servers_changed() {
- String physics_servers("DEFAULT");
+ String physics_servers2("DEFAULT");
for (int i = get_servers_count() - 1; 0 <= i; --i) {
- physics_servers += "," + get_server_name(i);
+ physics_servers2 += "," + get_server_name(i);
}
- ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers));
+ ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers2));
}
void PhysicsServerManager::register_server(const String &p_name, CreatePhysicsServerCallback p_creat_callback) {
diff --git a/servers/physics_server.h b/servers/physics_server.h
index 4ba096a994..9895ef2455 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -274,6 +274,7 @@ public:
SPACE_PARAM_BODY_TIME_TO_SLEEP,
SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO,
SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,
+ SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH
};
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0;
@@ -492,6 +493,11 @@ public:
RID collider;
int collider_shape;
Variant collider_metadata;
+ MotionResult() {
+ collision_local_shape = 0;
+ collider_id = 0;
+ collider_shape = 0;
+ }
};
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0;
@@ -788,6 +794,12 @@ class PhysicsServerManager {
ClassInfo(const ClassInfo &p_ci) :
name(p_ci.name),
create_callback(p_ci.create_callback) {}
+
+ ClassInfo operator=(const ClassInfo &p_ci) {
+ name = p_ci.name;
+ create_callback = p_ci.create_callback;
+ return *this;
+ }
};
static Vector<ClassInfo> physics_servers;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 0c43000186..0cc1cc119c 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -73,7 +73,11 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag
usage.vram = E->get().bytes;
usage.id = E->get().texture;
usage.type = "Texture";
- usage.format = itos(E->get().width) + "x" + itos(E->get().height) + " " + Image::get_format_name(E->get().format);
+ if (E->get().depth == 0) {
+ usage.format = itos(E->get().width) + "x" + itos(E->get().height) + " " + Image::get_format_name(E->get().format);
+ } else {
+ usage.format = itos(E->get().width) + "x" + itos(E->get().height) + "x" + itos(E->get().depth) + " " + Image::get_format_name(E->get().format);
+ }
r_usage->push_back(usage);
}
}
@@ -81,7 +85,6 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag
ShaderTypes *shader_types = NULL;
PhysicsServer *_createGodotPhysicsCallback() {
- WARN_PRINT("The GodotPhysics 3D physics engine is deprecated and will be removed in Godot 3.2. You should use the Bullet physics engine instead (configurable in your project settings).");
return memnew(PhysicsServerSW);
}
@@ -89,8 +92,21 @@ Physics2DServer *_createGodotPhysics2DCallback() {
return Physics2DServerWrapMT::init_server<Physics2DServerSW>();
}
+static bool has_server_feature_callback(const String &p_feature) {
+
+ if (VisualServer::get_singleton()) {
+ if (VisualServer::get_singleton()->has_os_feature(p_feature)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void register_server_types() {
+ OS::get_singleton()->set_has_server_feature_callback(has_server_feature_callback);
+
ClassDB::register_virtual_class<VisualServer>();
ClassDB::register_class<AudioServer>();
ClassDB::register_virtual_class<PhysicsServer>();
@@ -167,8 +183,8 @@ void register_server_types() {
GLOBAL_DEF(PhysicsServerManager::setting_property_name, "DEFAULT");
ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServerManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServerManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT"));
- PhysicsServerManager::register_server("GodotPhysics - deprecated", &_createGodotPhysicsCallback);
- PhysicsServerManager::set_default_server("GodotPhysics - deprecated");
+ PhysicsServerManager::register_server("GodotPhysics", &_createGodotPhysicsCallback);
+ PhysicsServerManager::set_default_server("GodotPhysics");
}
void unregister_server_types() {
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 6f8a30070a..39530bbbee 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -221,6 +221,7 @@ public:
virtual void textures_keep_original(bool p_enable) = 0;
virtual void texture_set_proxy(RID p_proxy, RID p_base) = 0;
+ virtual Size2 texture_size_with_proxy(RID p_texture) const = 0;
virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0;
/* SKY API */
@@ -354,6 +355,7 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
+ virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform) = 0;
/* Light API */
@@ -552,6 +554,7 @@ public:
virtual RID render_target_create() = 0;
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0;
virtual RID render_target_get_texture(RID p_render_target) const = 0;
+ virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
virtual bool render_target_was_used(RID p_render_target) = 0;
virtual void render_target_clear_used(RID p_render_target) = 0;
@@ -869,7 +872,7 @@ public:
Rect2 global_rect_cache;
const Rect2 &get_rect() const {
- if (custom_rect || !rect_dirty)
+ if (custom_rect || (!rect_dirty && !update_when_visible))
return rect;
//must update rect
@@ -939,9 +942,8 @@ public:
const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c);
r.position = primitive->points[0];
- for (int i = 1; i < primitive->points.size(); i++) {
-
- r.expand_to(primitive->points[i]);
+ for (int j = 1; j < primitive->points.size(); j++) {
+ r.expand_to(primitive->points[j]);
}
} break;
case Item::Command::TYPE_POLYGON: {
@@ -950,9 +952,8 @@ public:
int l = polygon->points.size();
const Point2 *pp = &polygon->points[0];
r.position = pp[0];
- for (int i = 1; i < l; i++) {
-
- r.expand_to(pp[i]);
+ for (int j = 1; j < l; j++) {
+ r.expand_to(pp[j]);
}
} break;
case Item::Command::TYPE_MESH: {
@@ -1101,7 +1102,7 @@ public:
virtual void initialize() = 0;
virtual void begin_frame(double frame_step) = 0;
virtual void set_current_render_target(RID p_render_target) = 0;
- virtual void restore_render_target() = 0;
+ virtual void restore_render_target(bool p_3d) = 0;
virtual void clear_render_target(const Color &p_color) = 0;
virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0) = 0;
virtual void output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) = 0;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index c2dae7c2d5..1f9d263354 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -2075,7 +2075,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
for (int i = 0; i < argcount; i++) {
if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) {
- //all good
+ //all good, but needs implicit conversion later
} else if (args[i] != builtin_func_defs[idx].args[i]) {
fail = true;
break;
@@ -2121,6 +2121,24 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
outarg_idx++;
}
+ //implicitly convert values if possible
+ for (int i = 0; i < argcount; i++) {
+
+ if (get_scalar_type(args[i]) != args[i] || args[i] == builtin_func_defs[idx].args[i] || p_func->arguments[i + 1]->type != Node::TYPE_CONSTANT) {
+ //can't do implicit conversion here
+ continue;
+ }
+
+ //this is an implicit conversion
+ ConstantNode *constant = static_cast<ConstantNode *>(p_func->arguments[i + 1]);
+ ConstantNode *conversion = alloc_node<ConstantNode>();
+
+ conversion->datatype = builtin_func_defs[idx].args[i];
+ conversion->values.resize(1);
+
+ convert_constant(constant, builtin_func_defs[idx].args[i], conversion->values.ptrw());
+ p_func->arguments.write[i + 1] = conversion;
+ }
if (r_ret_type)
*r_ret_type = builtin_func_defs[idx].rettype;
@@ -2184,17 +2202,37 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
bool fail = false;
- for (int i = 0; i < args.size(); i++) {
+ for (int j = 0; j < args.size(); j++) {
- if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), pfunc->arguments[i].type)) {
- //all good
- } else if (args[i] != pfunc->arguments[i].type) {
+ if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) {
+ //all good, but it needs implicit conversion later
+ } else if (args[j] != pfunc->arguments[j].type) {
fail = true;
break;
}
}
if (!fail) {
+
+ //implicitly convert values if possible
+ for (int k = 0; k < args.size(); k++) {
+
+ if (get_scalar_type(args[k]) != args[k] || args[k] == pfunc->arguments[k].type || p_func->arguments[k + 1]->type != Node::TYPE_CONSTANT) {
+ //can't do implicit conversion here
+ continue;
+ }
+
+ //this is an implicit conversion
+ ConstantNode *constant = static_cast<ConstantNode *>(p_func->arguments[k + 1]);
+ ConstantNode *conversion = alloc_node<ConstantNode>();
+
+ conversion->datatype = pfunc->arguments[k].type;
+ conversion->values.resize(1);
+
+ convert_constant(constant, pfunc->arguments[k].type, conversion->values.ptrw());
+ p_func->arguments.write[k + 1] = conversion;
+ }
+
if (r_ret_type)
*r_ret_type = pfunc->return_type;
return true;
@@ -2897,7 +2935,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
/* OK now see what's NEXT to the operator.. */
while (true) {
- TkPos pos = _get_tkpos();
+ TkPos pos2 = _get_tkpos();
tk = _get_token();
if (tk.type == TK_CURSOR) {
@@ -3181,7 +3219,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = op;
} else {
- _set_tkpos(pos);
+ _set_tkpos(pos2);
break;
}
}
@@ -3374,10 +3412,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!_validate_operator(op, &op->return_cache)) {
String at;
- for (int i = 0; i < op->arguments.size(); i++) {
- if (i > 0)
+ for (int j = 0; j < op->arguments.size(); j++) {
+ if (j > 0)
at += " and ";
- at += get_datatype_name(op->arguments[i]->get_datatype());
+ at += get_datatype_name(op->arguments[j]->get_datatype());
}
_set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
return NULL;
@@ -4103,17 +4141,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (uniform) {
- ShaderNode::Uniform uniform;
+ ShaderNode::Uniform uniform2;
if (is_sampler_type(type)) {
- uniform.texture_order = texture_uniforms++;
- uniform.order = -1;
+ uniform2.texture_order = texture_uniforms++;
+ uniform2.order = -1;
} else {
- uniform.texture_order = -1;
- uniform.order = uniforms++;
+ uniform2.texture_order = -1;
+ uniform2.order = uniforms++;
}
- uniform.type = type;
- uniform.precission = precision;
+ uniform2.type = type;
+ uniform2.precision = precision;
//todo parse default value
@@ -4124,26 +4162,26 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_HINT_WHITE_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_WHITE;
+ uniform2.hint = ShaderNode::Uniform::HINT_WHITE;
} else if (tk.type == TK_HINT_BLACK_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_BLACK;
+ uniform2.hint = ShaderNode::Uniform::HINT_BLACK;
} else if (tk.type == TK_HINT_NORMAL_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_NORMAL;
+ uniform2.hint = ShaderNode::Uniform::HINT_NORMAL;
} else if (tk.type == TK_HINT_ANISO_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_ANISO;
+ uniform2.hint = ShaderNode::Uniform::HINT_ANISO;
} else if (tk.type == TK_HINT_ALBEDO_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_ALBEDO;
+ uniform2.hint = ShaderNode::Uniform::HINT_ALBEDO;
} else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) {
- uniform.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO;
+ uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO;
} else if (tk.type == TK_HINT_COLOR) {
if (type != TYPE_VEC4) {
_set_error("Color hint is for vec4 only");
return ERR_PARSE_ERROR;
}
- uniform.hint = ShaderNode::Uniform::HINT_COLOR;
+ uniform2.hint = ShaderNode::Uniform::HINT_COLOR;
} else if (tk.type == TK_HINT_RANGE) {
- uniform.hint = ShaderNode::Uniform::HINT_RANGE;
+ uniform2.hint = ShaderNode::Uniform::HINT_RANGE;
if (type != TYPE_FLOAT && type != TYPE_INT) {
_set_error("Range hint is for float and int only");
return ERR_PARSE_ERROR;
@@ -4169,8 +4207,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- uniform.hint_range[0] = tk.constant;
- uniform.hint_range[0] *= sign;
+ uniform2.hint_range[0] = tk.constant;
+ uniform2.hint_range[0] *= sign;
tk = _get_token();
@@ -4193,8 +4231,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- uniform.hint_range[1] = tk.constant;
- uniform.hint_range[1] *= sign;
+ uniform2.hint_range[1] = tk.constant;
+ uniform2.hint_range[1] *= sign;
tk = _get_token();
@@ -4206,13 +4244,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- uniform.hint_range[2] = tk.constant;
+ uniform2.hint_range[2] = tk.constant;
tk = _get_token();
} else {
if (type == TYPE_INT) {
- uniform.hint_range[2] = 1;
+ uniform2.hint_range[2] = 1;
} else {
- uniform.hint_range[2] = 0.001;
+ uniform2.hint_range[2] = 0.001;
}
}
@@ -4225,7 +4263,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("Expected valid type hint after ':'.");
}
- if (uniform.hint != ShaderNode::Uniform::HINT_RANGE && uniform.hint != ShaderNode::Uniform::HINT_NONE && uniform.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
+ if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
_set_error("This hint is only for sampler types");
return ERR_PARSE_ERROR;
}
@@ -4245,16 +4283,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ConstantNode *cn = static_cast<ConstantNode *>(expr);
- uniform.default_value.resize(cn->values.size());
+ uniform2.default_value.resize(cn->values.size());
- if (!convert_constant(cn, uniform.type, uniform.default_value.ptrw())) {
- _set_error("Can't convert constant to " + get_datatype_name(uniform.type));
+ if (!convert_constant(cn, uniform2.type, uniform2.default_value.ptrw())) {
+ _set_error("Can't convert constant to " + get_datatype_name(uniform2.type));
return ERR_PARSE_ERROR;
}
tk = _get_token();
}
- shader->uniforms[name] = uniform;
+ shader->uniforms[name] = uniform2;
if (tk.type != TK_SEMICOLON) {
_set_error("Expected ';'");
@@ -4264,7 +4302,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ShaderNode::Varying varying;
varying.type = type;
- varying.precission = precision;
+ varying.precision = precision;
varying.interpolation = interpolation;
shader->varyings[name] = varying;
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index b908f9539b..67c273d267 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -33,7 +33,7 @@
#include "core/list.h"
#include "core/map.h"
-#include "core/string_db.h"
+#include "core/string_name.h"
#include "core/typedefs.h"
#include "core/ustring.h"
#include "core/variant.h"
@@ -42,7 +42,6 @@ class ShaderLanguage {
public:
enum TokenType {
-
TK_EMPTY,
TK_IDENTIFIER,
TK_TRUE,
@@ -267,18 +266,15 @@ public:
FLOW_OP_SWITCH,
FLOW_OP_CONTINUE,
FLOW_OP_DISCARD
-
};
enum ArgumentQualifier {
ARGUMENT_QUALIFIER_IN,
ARGUMENT_QUALIFIER_OUT,
ARGUMENT_QUALIFIER_INOUT,
-
};
struct Node {
-
Node *next;
enum Type {
@@ -296,7 +292,9 @@ public:
Type type;
virtual DataType get_datatype() const { return TYPE_VOID; }
-
+ Node(Type t) :
+ next(NULL),
+ type(t) {}
virtual ~Node() {}
};
@@ -311,18 +309,17 @@ public:
Node *nodes;
struct OperatorNode : public Node {
-
DataType return_cache;
DataPrecision return_precision_cache;
Operator op;
Vector<Node *> arguments;
virtual DataType get_datatype() const { return return_cache; }
- OperatorNode() {
- type = TYPE_OPERATOR;
- return_cache = TYPE_VOID;
- return_precision_cache = PRECISION_DEFAULT;
- }
+ OperatorNode() :
+ Node(TYPE_OPERATOR),
+ return_cache(TYPE_VOID),
+ return_precision_cache(PRECISION_DEFAULT),
+ op(OP_EQUAL) {}
};
struct VariableNode : public Node {
@@ -330,20 +327,16 @@ public:
StringName name;
virtual DataType get_datatype() const { return datatype_cache; }
- VariableNode() {
-
- type = TYPE_VARIABLE;
- datatype_cache = TYPE_VOID;
- }
+ VariableNode() :
+ Node(TYPE_VARIABLE),
+ datatype_cache(TYPE_VOID) {}
};
struct VariableDeclarationNode : public Node {
-
DataPrecision precision;
DataType datatype;
struct Declaration {
-
StringName name;
Node *initializer;
};
@@ -351,13 +344,13 @@ public:
Vector<Declaration> declarations;
virtual DataType get_datatype() const { return datatype; }
- VariableDeclarationNode() {
- type = TYPE_VARIABLE_DECLARATION;
- }
+ VariableDeclarationNode() :
+ Node(TYPE_VARIABLE_DECLARATION),
+ precision(PRECISION_DEFAULT),
+ datatype(TYPE_VOID) {}
};
struct ConstantNode : public Node {
-
DataType datatype;
union Value {
@@ -370,7 +363,9 @@ public:
Vector<Value> values;
virtual DataType get_datatype() const { return datatype; }
- ConstantNode() { type = TYPE_CONSTANT; }
+ ConstantNode() :
+ Node(TYPE_CONSTANT),
+ datatype(TYPE_VOID) {}
};
struct FunctionNode;
@@ -388,39 +383,41 @@ public:
Map<StringName, Variable> variables;
List<Node *> statements;
bool single_statement;
- BlockNode() {
- type = TYPE_BLOCK;
- parent_block = NULL;
- parent_function = NULL;
- single_statement = false;
- }
+
+ BlockNode() :
+ Node(TYPE_BLOCK),
+ parent_function(NULL),
+ parent_block(NULL),
+ single_statement(false) {}
};
struct ControlFlowNode : public Node {
-
FlowOperation flow_op;
Vector<Node *> expressions;
Vector<BlockNode *> blocks;
- ControlFlowNode() {
- type = TYPE_CONTROL_FLOW;
- flow_op = FLOW_OP_IF;
- }
+
+ ControlFlowNode() :
+ Node(TYPE_CONTROL_FLOW),
+ flow_op(FLOW_OP_IF) {}
};
struct MemberNode : public Node {
-
DataType basetype;
DataType datatype;
StringName name;
Node *owner;
+
virtual DataType get_datatype() const { return datatype; }
- MemberNode() { type = TYPE_MEMBER; }
+
+ MemberNode() :
+ Node(TYPE_MEMBER),
+ basetype(TYPE_VOID),
+ datatype(TYPE_VOID),
+ owner(NULL) {}
};
struct FunctionNode : public Node {
-
struct Argument {
-
ArgumentQualifier qualifier;
StringName name;
DataType type;
@@ -434,16 +431,15 @@ public:
BlockNode *body;
bool can_discard;
- FunctionNode() {
- type = TYPE_FUNCTION;
- return_type = TYPE_VOID;
- return_precision = PRECISION_DEFAULT;
- can_discard = false;
- }
+ FunctionNode() :
+ Node(TYPE_FUNCTION),
+ return_type(TYPE_VOID),
+ return_precision(PRECISION_DEFAULT),
+ body(NULL),
+ can_discard(false) {}
};
struct ShaderNode : public Node {
-
struct Function {
StringName name;
FunctionNode *function;
@@ -454,7 +450,12 @@ public:
struct Varying {
DataType type;
DataInterpolation interpolation;
- DataPrecision precission;
+ DataPrecision precision;
+
+ Varying() :
+ type(TYPE_VOID),
+ interpolation(INTERPOLATION_FLAT),
+ precision(PRECISION_DEFAULT) {}
};
struct Uniform {
@@ -474,16 +475,20 @@ public:
int order;
int texture_order;
DataType type;
- DataPrecision precission;
+ DataPrecision precision;
Vector<ConstantNode::Value> default_value;
Hint hint;
float hint_range[3];
- Uniform() {
- hint = HINT_NONE;
- hint_range[0] = 0;
- hint_range[1] = 1;
- hint_range[2] = 0.001;
+ Uniform() :
+ order(0),
+ texture_order(0),
+ type(TYPE_VOID),
+ precision(PRECISION_DEFAULT),
+ hint(HINT_NONE) {
+ hint_range[0] = 0.0f;
+ hint_range[1] = 1.0f;
+ hint_range[2] = 0.001f;
}
};
@@ -493,11 +498,11 @@ public:
Vector<Function> functions;
- ShaderNode() { type = TYPE_SHADER; }
+ ShaderNode() :
+ Node(TYPE_SHADER) {}
};
struct Expression {
-
bool is_op;
union {
Operator op;
@@ -506,7 +511,6 @@ public:
};
struct VarInfo {
-
StringName name;
DataType type;
};
@@ -522,7 +526,6 @@ public:
};
struct Token {
-
TokenType type;
StringName text;
double constant;
@@ -556,11 +559,14 @@ public:
struct BuiltInInfo {
DataType type;
bool constant;
- BuiltInInfo() {}
- BuiltInInfo(DataType p_type, bool p_constant = false) {
- type = p_type;
- constant = p_constant;
- }
+
+ BuiltInInfo() :
+ type(TYPE_VOID),
+ constant(false) {}
+
+ BuiltInInfo(DataType p_type, bool p_constant = false) :
+ type(p_type),
+ constant(p_constant) {}
};
struct FunctionInfo {
@@ -573,6 +579,7 @@ private:
TokenType token;
const char *text;
};
+
static const KeyWord keyword_list[];
bool error_set;
@@ -628,22 +635,18 @@ private:
};
bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL);
-
bool _is_operator_assign(Operator p_op) const;
bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL);
-
bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL);
struct BuiltinFuncDef {
-
enum { MAX_ARGS = 5 };
const char *name;
DataType rettype;
const DataType args[MAX_ARGS];
};
- struct BuiltinFuncOutArgs { //arguments used as out in built in funcions
-
+ struct BuiltinFuncOutArgs { //arguments used as out in built in functions
const char *name;
int argument;
};
@@ -656,20 +659,17 @@ private:
int completion_argument;
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
-
static const BuiltinFuncDef builtin_func_defs[];
static const BuiltinFuncOutArgs builtin_func_out_args[];
- bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
+ bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
-
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
- Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
+ Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false);
-
Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
public:
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index bb02027479..4adf53c183 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "visual_server_canvas.h"
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
#include "visual_server_raster.h"
#include "visual_server_viewport.h"
@@ -267,24 +267,24 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr
for (int i = 0; i < l; i++) {
- const Canvas::ChildItem &ci = p_canvas->child_items[i];
- _render_canvas_item_tree(ci.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights);
+ const Canvas::ChildItem &ci2 = p_canvas->child_items[i];
+ _render_canvas_item_tree(ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights);
//mirroring (useful for scrolling backgrounds)
- if (ci.mirror.x != 0) {
+ if (ci2.mirror.x != 0) {
- Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci.mirror.x, 0));
- _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
+ Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0));
+ _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
}
- if (ci.mirror.y != 0) {
+ if (ci2.mirror.y != 0) {
- Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci.mirror.y));
- _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
+ Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y));
+ _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
}
- if (ci.mirror.y != 0 && ci.mirror.x != 0) {
+ if (ci2.mirror.y != 0 && ci2.mirror.x != 0) {
- Transform2D xform2 = p_transform * Transform2D(0, ci.mirror);
- _render_canvas_item_tree(ci.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
+ Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror);
+ _render_canvas_item_tree(ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
}
}
}
@@ -319,6 +319,19 @@ void VisualServerCanvas::canvas_set_modulate(RID p_canvas, const Color &p_color)
canvas->modulate = p_color;
}
+void VisualServerCanvas::canvas_set_disable_scale(bool p_disable) {
+ disable_scale = p_disable;
+}
+
+void VisualServerCanvas::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) {
+
+ Canvas *canvas = canvas_owner.get(p_canvas);
+ ERR_FAIL_COND(!canvas);
+
+ canvas->parent = p_parent;
+ canvas->parent_scale = p_scale;
+}
+
RID VisualServerCanvas::canvas_item_create() {
Item *canvas_item = memnew(Item);
@@ -616,7 +629,7 @@ void VisualServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p
if (p_tile) {
rect->flags |= RasterizerCanvas::CANVAS_RECT_TILE;
rect->flags |= RasterizerCanvas::CANVAS_RECT_REGION;
- rect->source = Rect2(0, 0, p_rect.size.width, p_rect.size.height);
+ rect->source = Rect2(0, 0, fabsf(p_rect.size.width), fabsf(p_rect.size.height));
}
if (p_rect.size.x < 0) {
@@ -758,11 +771,12 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
- int ps = p_points.size();
- ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != ps && p_colors.size() != 1);
- ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != ps);
- ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != ps * 4);
- ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != ps * 4);
+ int vertex_count = p_points.size();
+ ERR_FAIL_COND(vertex_count == 0);
+ ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != vertex_count && p_colors.size() != 1);
+ ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != vertex_count);
+ ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != vertex_count * 4);
+ ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != vertex_count * 4);
Vector<int> indices = p_indices;
@@ -770,9 +784,9 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector
if (indices.empty()) {
- ERR_FAIL_COND(ps % 3 != 0);
+ ERR_FAIL_COND(vertex_count % 3 != 0);
if (p_count == -1)
- count = ps;
+ count = vertex_count;
} else {
ERR_FAIL_COND(indices.size() % 3 != 0);
@@ -1433,4 +1447,5 @@ bool VisualServerCanvas::free(RID p_rid) {
}
VisualServerCanvas::VisualServerCanvas() {
+ disable_scale = false;
}
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index 7d788cbe14..8162085ced 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -126,6 +126,8 @@ public:
bool children_order_dirty;
Vector<ChildItem> child_items;
Color modulate;
+ RID parent;
+ float parent_scale;
int find_item(Item *p_item) {
for (int i = 0; i < child_items.size(); i++) {
@@ -143,13 +145,16 @@ public:
Canvas() {
modulate = Color(1, 1, 1, 1);
children_order_dirty = true;
+ parent_scale = 1.0;
}
};
- RID_Owner<Canvas> canvas_owner;
+ mutable RID_Owner<Canvas> canvas_owner;
RID_Owner<Item> canvas_item_owner;
RID_Owner<RasterizerCanvas::Light> canvas_light_owner;
+ bool disable_scale;
+
private:
void _render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights);
void _render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner);
@@ -161,6 +166,8 @@ public:
RID canvas_create();
void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
void canvas_set_modulate(RID p_canvas, const Color &p_color);
+ void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale);
+ void canvas_set_disable_scale(bool p_disable);
RID canvas_item_create();
void canvas_item_set_parent(RID p_item, RID p_parent);
diff --git a/servers/visual/visual_server_global.cpp b/servers/visual/visual_server_globals.cpp
index 2d6d489759..5c247c7f0f 100644
--- a/servers/visual/visual_server_global.cpp
+++ b/servers/visual/visual_server_globals.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* visual_server_global.cpp */
+/* visual_server_globals.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
RasterizerStorage *VisualServerGlobals::storage = NULL;
RasterizerCanvas *VisualServerGlobals::canvas_render = NULL;
diff --git a/servers/visual/visual_server_global.h b/servers/visual/visual_server_globals.h
index b510307e81..04d52aa1eb 100644
--- a/servers/visual/visual_server_global.h
+++ b/servers/visual/visual_server_globals.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* visual_server_global.h */
+/* visual_server_globals.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VISUALSERVERGLOBAL_H
-#define VISUALSERVERGLOBAL_H
+#ifndef VISUAL_SERVER_GLOBALS_H
+#define VISUAL_SERVER_GLOBALS_H
#include "rasterizer.h"
@@ -51,4 +51,4 @@ public:
#define VSG VisualServerGlobals
-#endif // VISUALSERVERGLOBAL_H
+#endif // VISUAL_SERVER_GLOBALS_H
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 7be3bc562d..a9ca920178 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -33,9 +33,9 @@
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/project_settings.h"
-#include "core/sort.h"
+#include "core/sort_array.h"
#include "visual_server_canvas.h"
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
#include "visual_server_scene.h"
// careful, these may run in different threads than the visual server
@@ -123,7 +123,6 @@ void VisualServerRaster::draw(bool p_swap_buffers, double frame_step) {
frame_drawn_callbacks.pop_front();
}
-
VS::get_singleton()->emit_signal("frame_post_draw");
}
void VisualServerRaster::sync() {
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index e6434189f9..8ce25ba906 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -31,12 +31,11 @@
#ifndef VISUAL_SERVER_RASTER_H
#define VISUAL_SERVER_RASTER_H
-#include "core/allocators.h"
#include "core/math/octree.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
#include "visual_server_canvas.h"
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
#include "visual_server_scene.h"
#include "visual_server_viewport.h"
/**
@@ -297,6 +296,7 @@ public:
BIND3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
BIND2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
BIND2(skeleton_set_base_transform_2d, RID, const Transform2D &)
+ BIND3(skeleton_set_world_transform, RID, bool, const Transform &)
/* Light API */
@@ -569,6 +569,8 @@ public:
BIND0R(RID, canvas_create)
BIND3(canvas_set_item_mirroring, RID, RID, const Point2 &)
BIND2(canvas_set_modulate, RID, const Color &)
+ BIND3(canvas_set_parent, RID, RID, float)
+ BIND1(canvas_set_disable_scale, bool)
BIND0R(RID, canvas_item_create)
BIND2(canvas_item_set_parent, RID, RID)
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index 23ad2ec1ec..2590e29aef 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -30,8 +30,9 @@
#include "visual_server_scene.h"
#include "core/os/os.h"
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
#include "visual_server_raster.h"
+#include <new>
/* CAMERA API */
RID VisualServerScene::camera_create() {
@@ -444,6 +445,9 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
InstanceGeometryData *geom = memnew(InstanceGeometryData);
instance->base_data = geom;
+ if (instance->base_type == VS::INSTANCE_MESH) {
+ instance->blend_values.resize(VSG::storage->mesh_get_blend_shape_count(p_base));
+ }
} break;
case VS::INSTANCE_REFLECTION_PROBE: {
@@ -573,6 +577,19 @@ void VisualServerScene::instance_set_transform(RID p_instance, const Transform &
if (instance->transform == p_transform)
return; //must be checked to avoid worst evil
+#ifdef DEBUG_ENABLED
+
+ for (int i = 0; i < 4; i++) {
+ const Vector3 &v = i < 3 ? p_transform.basis.elements[i] : p_transform.origin;
+ ERR_FAIL_COND(Math::is_inf(v.x));
+ ERR_FAIL_COND(Math::is_nan(v.x));
+ ERR_FAIL_COND(Math::is_inf(v.y));
+ ERR_FAIL_COND(Math::is_nan(v.y));
+ ERR_FAIL_COND(Math::is_inf(v.z));
+ ERR_FAIL_COND(Math::is_nan(v.z));
+ }
+
+#endif
instance->transform = p_transform;
_instance_queue_update(instance, true);
}
@@ -1240,7 +1257,9 @@ void VisualServerScene::_update_instance_lightmap_captures(Instance *p_instance)
//print_line("update captures for pos: " + p_instance->transform.origin);
- zeromem(p_instance->lightmap_capture_data.ptrw(), 12 * sizeof(Color));
+ for (int i = 0; i < 12; i++)
+ new (&p_instance->lightmap_capture_data.ptrw()[i]) Color;
+
//this could use some sort of blending..
for (List<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
const PoolVector<RasterizerStorage::LightmapCaptureOctree> *octree = VSG::storage->lightmap_capture_get_octree_ptr(E->get()->base);
@@ -2464,7 +2483,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
uint32_t a = uint32_t(alpha_block[x][y]) - min_alpha;
//convert range to 3 bits
a = int((a * 7.0 / (max_alpha - min_alpha)) + 0.5);
- a = CLAMP(a, 0, 7); //just to be sure
+ a = MIN(a, 7); //just to be sure
a = 7 - a; //because range is inverted in this mode
if (a == 0) {
//do none, remain
@@ -2900,7 +2919,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
uint32_t idx = level_cells[j];
- uint32_t r = (uint32_t(local_data[idx].energy[0]) / probe_data->dynamic.bake_dynamic_range) >> 2;
+ uint32_t r2 = (uint32_t(local_data[idx].energy[0]) / probe_data->dynamic.bake_dynamic_range) >> 2;
uint32_t g = (uint32_t(local_data[idx].energy[1]) / probe_data->dynamic.bake_dynamic_range) >> 2;
uint32_t b = (uint32_t(local_data[idx].energy[2]) / probe_data->dynamic.bake_dynamic_range) >> 2;
uint32_t a = (cells[idx].level_alpha >> 8) & 0xFF;
@@ -2908,10 +2927,10 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
uint32_t mm_ofs = sizes[0] * sizes[1] * (local_data[idx].pos[2]) + sizes[0] * (local_data[idx].pos[1]) + (local_data[idx].pos[0]);
mm_ofs *= 4; //for RGBA (4 bytes)
- mipmapw[mm_ofs + 0] = uint8_t(CLAMP(r, 0, 255));
- mipmapw[mm_ofs + 1] = uint8_t(CLAMP(g, 0, 255));
- mipmapw[mm_ofs + 2] = uint8_t(CLAMP(b, 0, 255));
- mipmapw[mm_ofs + 3] = uint8_t(CLAMP(a, 0, 255));
+ mipmapw[mm_ofs + 0] = uint8_t(MIN(r2, 255));
+ mipmapw[mm_ofs + 1] = uint8_t(MIN(g, 255));
+ mipmapw[mm_ofs + 2] = uint8_t(MIN(b, 255));
+ mipmapw[mm_ofs + 3] = uint8_t(MIN(a, 255));
}
}
} else if (probe_data->dynamic.compression == RasterizerStorage::GI_PROBE_S3TC) {
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
index 539855bdc4..7583acd88f 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -33,7 +33,6 @@
#include "servers/visual/rasterizer.h"
-#include "core/allocators.h"
#include "core/math/geometry.h"
#include "core/math/octree.h"
#include "core/os/semaphore.h"
@@ -120,7 +119,6 @@ public:
VS::ScenarioDebugMode debug;
RID self;
- // well wtf, balloon allocator is slower?
Octree<Instance, true> octree;
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index 92b17eae47..9ad3e4a308 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -32,9 +32,46 @@
#include "core/project_settings.h"
#include "visual_server_canvas.h"
-#include "visual_server_global.h"
+#include "visual_server_globals.h"
#include "visual_server_scene.h"
+static Transform2D _canvas_get_transform(VisualServerViewport::Viewport *p_viewport, VisualServerCanvas::Canvas *p_canvas, VisualServerViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) {
+
+ Transform2D xf = p_viewport->global_transform;
+
+ float scale = 1.0;
+ if (p_viewport->canvas_map.has(p_canvas->parent)) {
+ xf = xf * p_viewport->canvas_map[p_canvas->parent].transform;
+ scale = p_canvas->parent_scale;
+ }
+
+ xf = xf * p_canvas_data->transform;
+
+ if (scale != 1.0 && !VSG::canvas->disable_scale) {
+ Vector2 pivot = p_vp_size * 0.5;
+ Transform2D xfpivot;
+ xfpivot.set_origin(pivot);
+ Transform2D xfscale;
+ xfscale.scale(Vector2(scale, scale));
+
+ xf = xfpivot.affine_inverse() * xf;
+ xf = xfscale * xf;
+ xf = xfpivot * xf;
+ }
+
+ return xf;
+}
+
+void VisualServerViewport::_draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {
+ Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
+
+ if (p_viewport->use_arvr && arvr_interface.is_valid()) {
+ VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ } else {
+ VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ }
+}
+
void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {
/* Camera should always be BEFORE any other 3D */
@@ -62,13 +99,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
}
if (!scenario_draw_canvas_bg && can_draw_3d) {
- Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
-
- if (p_viewport->use_arvr && arvr_interface.is_valid()) {
- VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
- } else {
- VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
- }
+ _draw_3d(p_viewport, p_eye);
}
if (!p_viewport->hide_canvas) {
@@ -86,10 +117,10 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
- Transform2D xf = p_viewport->global_transform * E->get().transform;
-
VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get().canvas);
+ Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
+
//find lights in canvas
for (Set<RasterizerCanvas::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) {
@@ -97,7 +128,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
RasterizerCanvas::Light *cl = F->get();
if (cl->enabled && cl->texture.is_valid()) {
//not super efficient..
- Size2 tsize(VSG::storage->texture_get_width(cl->texture), VSG::storage->texture_get_height(cl->texture));
+ Size2 tsize = VSG::storage->texture_size_with_proxy(cl->texture);
tsize *= cl->scale;
Vector2 offset = tsize / 2.0;
@@ -167,24 +198,20 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
RasterizerCanvas::Light *light = lights_with_shadow;
while (light) {
- VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer, light->xform_cache.affine_inverse(), light->item_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders, &light->shadow_matrix_cache);
+ VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders, &light->shadow_matrix_cache);
light = light->shadows_next_ptr;
}
//VSG::canvas_render->reset_canvas();
}
- VSG::rasterizer->restore_render_target();
+ VSG::rasterizer->restore_render_target(!scenario_draw_canvas_bg && can_draw_3d);
if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
- Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
-
if (!can_draw_3d) {
VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
- } else if (p_viewport->use_arvr && arvr_interface.is_valid()) {
- VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
} else {
- VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ _draw_3d(p_viewport, p_eye);
}
scenario_draw_canvas_bg = false;
}
@@ -193,7 +220,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get()->canvas);
- Transform2D xform = p_viewport->global_transform * E->get()->transform;
+ Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size);
RasterizerCanvas::Light *canvas_lights = NULL;
@@ -210,14 +237,10 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
i++;
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
- Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
-
if (!can_draw_3d) {
VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
- } else if (p_viewport->use_arvr && arvr_interface.is_valid()) {
- VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
} else {
- VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ _draw_3d(p_viewport, p_eye);
}
scenario_draw_canvas_bg = false;
@@ -225,14 +248,10 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
}
if (scenario_draw_canvas_bg) {
- Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
-
if (!can_draw_3d) {
VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
- } else if (p_viewport->use_arvr && arvr_interface.is_valid()) {
- VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
} else {
- VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ _draw_3d(p_viewport, p_eye);
}
scenario_draw_canvas_bg = false;
@@ -281,12 +300,22 @@ void VisualServerViewport::draw_viewports() {
// render mono or left eye first
ARVRInterface::Eyes leftOrMono = arvr_interface->is_stereo() ? ARVRInterface::EYE_LEFT : ARVRInterface::EYE_MONO;
+
+ // check for an external texture destination for our left eye/mono
+ VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(leftOrMono));
+
+ // set our render target as current
VSG::rasterizer->set_current_render_target(vp->render_target);
+
+ // and draw left eye/mono
_draw_viewport(vp, leftOrMono);
arvr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect);
// render right eye
if (leftOrMono == ARVRInterface::EYE_LEFT) {
+ // check for an external texture destination for our right eye
+ VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(ARVRInterface::EYE_RIGHT));
+
// commit for eye may have changed the render target
VSG::rasterizer->set_current_render_target(vp->render_target);
@@ -297,6 +326,7 @@ void VisualServerViewport::draw_viewports() {
// and for our frame timing, mark when we've finished committing our eyes
ARVRServer::get_singleton()->_mark_commit();
} else {
+ VSG::storage->render_target_set_external_texture(vp->render_target, 0);
VSG::rasterizer->set_current_render_target(vp->render_target);
VSG::scene_render->set_debug_draw_mode(vp->debug_draw);
diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h
index 4e3015c020..555b40a103 100644
--- a/servers/visual/visual_server_viewport.h
+++ b/servers/visual/visual_server_viewport.h
@@ -90,7 +90,8 @@ public:
}
CanvasKey(const RID &p_canvas, int p_layer, int p_sublayer) {
canvas = p_canvas;
- stacking = ((int64_t)p_layer << 32) + p_sublayer;
+ int64_t sign = p_layer < 0 ? -1 : 1;
+ stacking = sign * (((int64_t)ABS(p_layer)) << 32) + p_sublayer;
}
int get_layer() const { return stacking >> 32; }
};
@@ -146,6 +147,7 @@ public:
private:
Color clear_color;
+ void _draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye);
void _draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye = ARVRInterface::EYE_MONO);
public:
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index a6f0bd9d16..efe251e9de 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -232,6 +232,7 @@ public:
FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
+ FUNC3(skeleton_set_world_transform, RID, bool, const Transform &)
/* Light API */
@@ -486,6 +487,8 @@ public:
FUNCRID(canvas)
FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
FUNC2(canvas_set_modulate, RID, const Color &)
+ FUNC3(canvas_set_parent, RID, RID, float)
+ FUNC1(canvas_set_disable_scale, bool)
FUNCRID(canvas_item)
FUNC2(canvas_item_set_parent, RID, RID)
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 02acf72951..19c6106502 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -776,7 +776,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_
continue; //break;
ERR_FAIL_INDEX_V(idx, total_bones, ERR_INVALID_DATA);
- if (bptr->size.x < 0) {
+ if (bptr[idx].size.x < 0) {
//first
bptr[idx] = AABB(v, SMALL_VEC3);
any_valid = true;
@@ -1163,11 +1163,11 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_prim
PoolVector<uint8_t> noindex;
AABB laabb;
- Error err = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb);
+ Error err2 = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb);
aabb.merge_with(laabb);
- if (err) {
+ if (err2) {
ERR_EXPLAIN("Invalid blend shape array format for surface");
- ERR_FAIL_COND(err != OK);
+ ERR_FAIL_COND(err2 != OK);
}
blend_shape_data.push_back(vertex_array_shape);
@@ -2368,11 +2368,11 @@ VisualServer::VisualServer() {
//ERR_FAIL_COND(singleton);
singleton = this;
- GLOBAL_DEF("rendering/vram_compression/import_bptc", false);
- GLOBAL_DEF("rendering/vram_compression/import_s3tc", true);
- GLOBAL_DEF("rendering/vram_compression/import_etc", false);
- GLOBAL_DEF("rendering/vram_compression/import_etc2", true);
- GLOBAL_DEF("rendering/vram_compression/import_pvrtc", false);
+ GLOBAL_DEF_RST("rendering/vram_compression/import_bptc", false);
+ GLOBAL_DEF_RST("rendering/vram_compression/import_s3tc", true);
+ GLOBAL_DEF_RST("rendering/vram_compression/import_etc", false);
+ GLOBAL_DEF_RST("rendering/vram_compression/import_etc2", true);
+ GLOBAL_DEF_RST("rendering/vram_compression/import_pvrtc", false);
GLOBAL_DEF("rendering/quality/directional_shadow/size", 4096);
GLOBAL_DEF("rendering/quality/directional_shadow/size.mobile", 2048);
@@ -2406,7 +2406,7 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx.mobile", true);
GLOBAL_DEF("rendering/quality/depth_prepass/enable", true);
- GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno");
+ GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false);
}
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 96a5d19efd..596b893b69 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -393,6 +393,7 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
+ virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_base_transform) = 0;
/* Light API */
@@ -859,6 +860,9 @@ public:
virtual RID canvas_create() = 0;
virtual void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) = 0;
virtual void canvas_set_modulate(RID p_canvas, const Color &p_color) = 0;
+ virtual void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) = 0;
+
+ virtual void canvas_set_disable_scale(bool p_disable) = 0;
virtual RID canvas_item_create() = 0;
virtual void canvas_item_set_parent(RID p_item, RID p_parent) = 0;