diff options
Diffstat (limited to 'servers')
51 files changed, 1056 insertions, 211 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..9ea59a3961 100644 --- a/servers/arvr/arvr_interface.h +++ b/servers/arvr/arvr_interface.h @@ -108,9 +108,11 @@ 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; + virtual void notification(int p_what) = 0; ARVRInterface(); ~ARVRInterface(); 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_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp index 88f3ed8d15..ad5bcde382 100644 --- a/servers/audio/audio_rb_resampler.cpp +++ b/servers/audio/audio_rb_resampler.cpp @@ -201,10 +201,8 @@ void AudioRBResampler::clear() { return; //should be stopped at this point but just in case - if (rb) { - memdelete_arr(rb); - memdelete_arr(read_buf); - } + memdelete_arr(rb); + memdelete_arr(read_buf); rb = NULL; offset = 0; rb_read_pos = 0; diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp index 2dd71f9452..abf9d5593c 100644 --- a/servers/audio/effects/audio_effect_record.cpp +++ b/servers/audio/effects/audio_effect_record.cpp @@ -32,6 +32,9 @@ void AudioEffectRecordInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { if (!is_recording) { + for (int i = 0; i < p_frame_count; i++) { + p_dst_frames[i] = p_src_frames[i]; + } return; } @@ -39,6 +42,7 @@ void AudioEffectRecordInstance::process(const AudioFrame *p_src_frames, AudioFra const AudioFrame *src = p_src_frames; AudioFrame *rb_buf = ring_buffer.ptrw(); for (int i = 0; i < p_frame_count; i++) { + p_dst_frames[i] = p_src_frames[i]; rb_buf[ring_buffer_pos & ring_buffer_mask] = src[i]; ring_buffer_pos++; } @@ -66,7 +70,7 @@ void AudioEffectRecordInstance::_io_thread_process() { while (is_recording) { //Check: The current recording has been requested to stop - if (is_recording && !base->recording_active) { + if (!base->recording_active) { is_recording = false; } diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp new file mode 100644 index 0000000000..8e15e9288f --- /dev/null +++ b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp @@ -0,0 +1,256 @@ +#include "audio_effect_spectrum_analyzer.h" +#include "servers/audio_server.h" + +static void smbFft(float *fftBuffer, long fftFrameSize, long sign) +/* + FFT routine, (C)1996 S.M.Bernsee. Sign = -1 is FFT, 1 is iFFT (inverse) + Fills fftBuffer[0...2*fftFrameSize-1] with the Fourier transform of the + time domain data in fftBuffer[0...2*fftFrameSize-1]. The FFT array takes + and returns the cosine and sine parts in an interleaved manner, ie. + fftBuffer[0] = cosPart[0], fftBuffer[1] = sinPart[0], asf. fftFrameSize + must be a power of 2. It expects a complex input signal (see footnote 2), + ie. when working with 'common' audio signals our input signal has to be + passed as {in[0],0.,in[1],0.,in[2],0.,...} asf. In that case, the transform + of the frequencies of interest is in fftBuffer[0...fftFrameSize]. +*/ +{ + float wr, wi, arg, *p1, *p2, temp; + float tr, ti, ur, ui, *p1r, *p1i, *p2r, *p2i; + long i, bitm, j, le, le2, k; + + for (i = 2; i < 2 * fftFrameSize - 2; i += 2) { + for (bitm = 2, j = 0; bitm < 2 * fftFrameSize; bitm <<= 1) { + if (i & bitm) j++; + j <<= 1; + } + if (i < j) { + p1 = fftBuffer + i; + p2 = fftBuffer + j; + temp = *p1; + *(p1++) = *p2; + *(p2++) = temp; + temp = *p1; + *p1 = *p2; + *p2 = temp; + } + } + for (k = 0, le = 2; k < (long)(log((double)fftFrameSize) / log(2.) + .5); k++) { + le <<= 1; + le2 = le >> 1; + ur = 1.0; + ui = 0.0; + arg = Math_PI / (le2 >> 1); + wr = cos(arg); + wi = sign * sin(arg); + for (j = 0; j < le2; j += 2) { + p1r = fftBuffer + j; + p1i = p1r + 1; + p2r = p1r + le2; + p2i = p2r + 1; + for (i = j; i < 2 * fftFrameSize; i += le) { + tr = *p2r * ur - *p2i * ui; + ti = *p2r * ui + *p2i * ur; + *p2r = *p1r - tr; + *p2i = *p1i - ti; + *p1r += tr; + *p1i += ti; + p1r += le; + p1i += le; + p2r += le; + p2i += le; + } + tr = ur * wr - ui * wi; + ui = ur * wi + ui * wr; + ur = tr; + } + } +} +void AudioEffectSpectrumAnalyzerInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { + + uint64_t time = OS::get_singleton()->get_ticks_usec(); + + //copy everything over first, since this only really does capture + for (int i = 0; i < p_frame_count; i++) { + p_dst_frames[i] = p_src_frames[i]; + } + + //capture spectrum + while (p_frame_count) { + int to_fill = fft_size * 2 - temporal_fft_pos; + to_fill = MIN(to_fill, p_frame_count); + + float *fftw = temporal_fft.ptrw(); + for (int i = 0; i < to_fill; i++) { //left and right buffers + fftw[(i + temporal_fft_pos) * 2] = p_src_frames[i].l; + fftw[(i + temporal_fft_pos) * 2 + 1] = 0; + fftw[(i + temporal_fft_pos + fft_size * 2) * 2] = p_src_frames[i].r; + fftw[(i + temporal_fft_pos + fft_size * 2) * 2 + 1] = 0; + } + + p_src_frames += to_fill; + temporal_fft_pos += to_fill; + p_frame_count -= to_fill; + + if (temporal_fft_pos == fft_size * 2) { + //time to do a FFT + smbFft(fftw, fft_size * 2, -1); + smbFft(fftw + fft_size * 4, fft_size * 2, -1); + int next = (fft_pos + 1) % fft_count; + + AudioFrame *hw = (AudioFrame *)fft_history[next].ptr(); //do not use write, avoid cow + + for (int i = 0; i < fft_size; i++) { + //abs(vec)/fft_size normalizes each frequency + float window = 1.0; //-.5 * Math::cos(2. * Math_PI * (double)i / (double)fft_size) + .5; + hw[i].l = window * Vector2(fftw[i * 2], fftw[i * 2 + 1]).length() / float(fft_size); + hw[i].r = window * Vector2(fftw[fft_size * 4 + i * 2], fftw[fft_size * 4 + i * 2 + 1]).length() / float(fft_size); + } + + fft_pos = next; //swap + temporal_fft_pos = 0; + } + } + + //determine time of capture + double remainer_sec = (temporal_fft_pos / mix_rate); //subtract remainder from mix time + last_fft_time = time - uint64_t(remainer_sec * 1000000.0); +} + +void AudioEffectSpectrumAnalyzerInstance::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_magnitude_for_frequency_range", "from_hz", "to_hz", "mode"), &AudioEffectSpectrumAnalyzerInstance::get_magnitude_for_frequency_range, DEFVAL(MAGNITUDE_MAX)); + BIND_ENUM_CONSTANT(MAGNITUDE_AVERAGE); + BIND_ENUM_CONSTANT(MAGNITUDE_MAX); +} + +Vector2 AudioEffectSpectrumAnalyzerInstance::get_magnitude_for_frequency_range(float p_begin, float p_end, MagnitudeMode p_mode) const { + + if (last_fft_time == 0) { + return Vector2(); + } + uint64_t time = OS::get_singleton()->get_ticks_usec(); + float diff = double(time - last_fft_time) / 1000000.0 + base->get_tap_back_pos(); + diff -= AudioServer::get_singleton()->get_output_latency(); + float fft_time_size = float(fft_size) / mix_rate; + + int fft_index = fft_pos; + + while (diff > fft_time_size) { + diff -= fft_time_size; + fft_index -= 1; + if (fft_index < 0) { + fft_index = fft_count - 1; + } + } + + int begin_pos = p_begin * fft_size / (mix_rate * 0.5); + int end_pos = p_end * fft_size / (mix_rate * 0.5); + + begin_pos = CLAMP(begin_pos, 0, fft_size - 1); + end_pos = CLAMP(end_pos, 0, fft_size - 1); + + if (begin_pos > end_pos) { + SWAP(begin_pos, end_pos); + } + const AudioFrame *r = fft_history[fft_index].ptr(); + + if (p_mode == MAGNITUDE_AVERAGE) { + Vector2 avg; + + for (int i = begin_pos; i <= end_pos; i++) { + avg += Vector2(r[i]); + } + + avg /= float(end_pos - begin_pos + 1); + + return avg; + } else { + + Vector2 max; + + for (int i = begin_pos; i <= end_pos; i++) { + max.x = MAX(max.x, r[i].l); + max.y = MAX(max.y, r[i].r); + } + + return max; + } +} + +Ref<AudioEffectInstance> AudioEffectSpectrumAnalyzer::instance() { + + Ref<AudioEffectSpectrumAnalyzerInstance> ins; + ins.instance(); + ins->base = Ref<AudioEffectSpectrumAnalyzer>(this); + static const int fft_sizes[FFT_SIZE_MAX] = { 256, 512, 1024, 2048, 4096 }; + ins->fft_size = fft_sizes[fft_size]; + ins->mix_rate = AudioServer::get_singleton()->get_mix_rate(); + ins->fft_count = (buffer_length / (float(ins->fft_size) / ins->mix_rate)) + 1; + ins->fft_pos = 0; + ins->last_fft_time = 0; + ins->fft_history.resize(ins->fft_count); + ins->temporal_fft.resize(ins->fft_size * 8); //x2 stereo, x2 amount of samples for freqs, x2 for input + ins->temporal_fft_pos = 0; + for (int i = 0; i < ins->fft_count; i++) { + ins->fft_history.write[i].resize(ins->fft_size); //only magnitude matters + for (int j = 0; j < ins->fft_size; j++) { + ins->fft_history.write[i].write[j] = AudioFrame(0, 0); + } + } + return ins; +} + +void AudioEffectSpectrumAnalyzer::set_buffer_length(float p_volume) { + buffer_length = p_volume; +} + +float AudioEffectSpectrumAnalyzer::get_buffer_length() const { + + return buffer_length; +} + +void AudioEffectSpectrumAnalyzer::set_tap_back_pos(float p_seconds) { + tapback_pos = p_seconds; +} + +float AudioEffectSpectrumAnalyzer::get_tap_back_pos() const { + return tapback_pos; +} + +void AudioEffectSpectrumAnalyzer::set_fft_size(FFT_Size p_fft_size) { + ERR_FAIL_INDEX(p_fft_size, FFT_SIZE_MAX); + fft_size = p_fft_size; +} + +AudioEffectSpectrumAnalyzer::FFT_Size AudioEffectSpectrumAnalyzer::get_fft_size() const { + return fft_size; +} + +void AudioEffectSpectrumAnalyzer::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_buffer_length", "seconds"), &AudioEffectSpectrumAnalyzer::set_buffer_length); + ClassDB::bind_method(D_METHOD("get_buffer_length"), &AudioEffectSpectrumAnalyzer::get_buffer_length); + + ClassDB::bind_method(D_METHOD("set_tap_back_pos", "seconds"), &AudioEffectSpectrumAnalyzer::set_tap_back_pos); + ClassDB::bind_method(D_METHOD("get_tap_back_pos"), &AudioEffectSpectrumAnalyzer::get_tap_back_pos); + + ClassDB::bind_method(D_METHOD("set_fft_size", "size"), &AudioEffectSpectrumAnalyzer::set_fft_size); + ClassDB::bind_method(D_METHOD("get_fft_size"), &AudioEffectSpectrumAnalyzer::get_fft_size); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "buffer_length", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_buffer_length", "get_buffer_length"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "tap_back_pos", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_tap_back_pos", "get_tap_back_pos"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fft_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_fft_size", "get_fft_size"); + + BIND_ENUM_CONSTANT(FFT_SIZE_256); + BIND_ENUM_CONSTANT(FFT_SIZE_512); + BIND_ENUM_CONSTANT(FFT_SIZE_1024); + BIND_ENUM_CONSTANT(FFT_SIZE_2048); + BIND_ENUM_CONSTANT(FFT_SIZE_4096); + BIND_ENUM_CONSTANT(FFT_SIZE_MAX); +} + +AudioEffectSpectrumAnalyzer::AudioEffectSpectrumAnalyzer() { + buffer_length = 2; + tapback_pos = 0.01; + fft_size = FFT_SIZE_1024; +} diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.h b/servers/audio/effects/audio_effect_spectrum_analyzer.h new file mode 100644 index 0000000000..0534426da3 --- /dev/null +++ b/servers/audio/effects/audio_effect_spectrum_analyzer.h @@ -0,0 +1,76 @@ +#ifndef AUDIO_EFFECT_SPECTRUM_ANALYZER_H +#define AUDIO_EFFECT_SPECTRUM_ANALYZER_H + +#include "servers/audio/audio_effect.h" + +class AudioEffectSpectrumAnalyzer; + +class AudioEffectSpectrumAnalyzerInstance : public AudioEffectInstance { + GDCLASS(AudioEffectSpectrumAnalyzerInstance, AudioEffectInstance) + +public: + enum MagnitudeMode { + MAGNITUDE_AVERAGE, + MAGNITUDE_MAX, + }; + +private: + friend class AudioEffectSpectrumAnalyzer; + Ref<AudioEffectSpectrumAnalyzer> base; + + Vector<Vector<AudioFrame> > fft_history; + Vector<float> temporal_fft; + int temporal_fft_pos; + int fft_size; + int fft_count; + int fft_pos; + float mix_rate; + uint64_t last_fft_time; + +protected: + static void _bind_methods(); + +public: + virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count); + Vector2 get_magnitude_for_frequency_range(float p_begin, float p_end, MagnitudeMode p_mode = MAGNITUDE_MAX) const; +}; + +VARIANT_ENUM_CAST(AudioEffectSpectrumAnalyzerInstance::MagnitudeMode) + +class AudioEffectSpectrumAnalyzer : public AudioEffect { + GDCLASS(AudioEffectSpectrumAnalyzer, AudioEffect) +public: + enum FFT_Size { + FFT_SIZE_256, + FFT_SIZE_512, + FFT_SIZE_1024, + FFT_SIZE_2048, + FFT_SIZE_4096, + FFT_SIZE_MAX + }; + +public: + friend class AudioEffectSpectrumAnalyzerInstance; + float buffer_length; + float tapback_pos; + FFT_Size fft_size; + +protected: + static void _bind_methods(); + +public: + Ref<AudioEffectInstance> instance(); + void set_buffer_length(float p_seconds); + float get_buffer_length() const; + void set_tap_back_pos(float p_seconds); + float get_tap_back_pos() const; + + void set_fft_size(FFT_Size); + FFT_Size get_fft_size() const; + + AudioEffectSpectrumAnalyzer(); +}; + +VARIANT_ENUM_CAST(AudioEffectSpectrumAnalyzer::FFT_Size); + +#endif // AUDIO_EFFECT_SPECTRUM_ANALYZER_H diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp new file mode 100644 index 0000000000..f4a66b5643 --- /dev/null +++ b/servers/audio/effects/audio_stream_generator.cpp @@ -0,0 +1,182 @@ +#include "audio_stream_generator.h" + +void AudioStreamGenerator::set_mix_rate(float p_mix_rate) { + mix_rate = p_mix_rate; +} + +float AudioStreamGenerator::get_mix_rate() const { + + return mix_rate; +} + +void AudioStreamGenerator::set_buffer_length(float p_seconds) { + + buffer_len = p_seconds; +} +float AudioStreamGenerator::get_buffer_length() const { + + return buffer_len; +} + +Ref<AudioStreamPlayback> AudioStreamGenerator::instance_playback() { + + Ref<AudioStreamGeneratorPlayback> playback; + playback.instance(); + playback->generator = this; + int target_buffer_size = mix_rate * buffer_len; + playback->buffer.resize(nearest_shift(target_buffer_size)); + playback->buffer.clear(); + return playback; +} +String AudioStreamGenerator::get_stream_name() const { + + return "UserFeed"; +} + +float AudioStreamGenerator::get_length() const { + return 0; +} + +void AudioStreamGenerator::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mix_rate", "hz"), &AudioStreamGenerator::set_mix_rate); + ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamGenerator::get_mix_rate); + + ClassDB::bind_method(D_METHOD("set_buffer_length", "seconds"), &AudioStreamGenerator::set_buffer_length); + ClassDB::bind_method(D_METHOD("get_buffer_length"), &AudioStreamGenerator::get_buffer_length); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "mix_rate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_mix_rate", "get_mix_rate"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_buffer_length", "get_buffer_length"); +} + +AudioStreamGenerator::AudioStreamGenerator() { + mix_rate = 44100; + buffer_len = 0.5; +} + +//////////////// + +bool AudioStreamGeneratorPlayback::push_frame(const Vector2 &p_frame) { + if (buffer.space_left() < 1) { + return false; + } + + AudioFrame f = p_frame; + + buffer.write(&f, 1); + return true; +} + +bool AudioStreamGeneratorPlayback::can_push_buffer(int p_frames) const { + return buffer.space_left() >= p_frames; +} +bool AudioStreamGeneratorPlayback::push_buffer(const PoolVector2Array &p_frames) { + + int to_write = p_frames.size(); + if (buffer.space_left() < to_write) { + return false; + } + + PoolVector2Array::Read r = p_frames.read(); + if (sizeof(real_t) == 4) { + //write directly + buffer.write((const AudioFrame *)r.ptr(), to_write); + } else { + //convert from double + AudioFrame buf[2048]; + int ofs = 0; + while (to_write) { + + int w = MIN(to_write, 2048); + for (int i = 0; i < w; i++) { + buf[i] = r[i + ofs]; + } + buffer.write(buf, w); + ofs += w; + to_write -= w; + } + } + return true; +} + +int AudioStreamGeneratorPlayback::get_frames_available() const { + return buffer.space_left(); +} + +int AudioStreamGeneratorPlayback::get_skips() const { + return skips; +} + +void AudioStreamGeneratorPlayback::clear_buffer() { + ERR_FAIL_COND(active); + buffer.clear(); + mixed = 0; +} + +void AudioStreamGeneratorPlayback::_mix_internal(AudioFrame *p_buffer, int p_frames) { + + int read_amount = buffer.data_left(); + if (p_frames < read_amount) { + read_amount = p_frames; + } + + buffer.read(p_buffer, read_amount); + + if (read_amount < p_frames) { + //skipped, not ideal + for (int i = read_amount; i < p_frames; i++) { + p_buffer[i] = AudioFrame(0, 0); + } + + skips++; + } + + mixed += p_frames / generator->get_mix_rate(); +} +float AudioStreamGeneratorPlayback::get_stream_sampling_rate() { + return generator->get_mix_rate(); +} + +void AudioStreamGeneratorPlayback::start(float p_from_pos) { + + if (mixed == 0.0) { + _begin_resample(); + } + skips = 0; + active = true; + mixed = 0.0; +} + +void AudioStreamGeneratorPlayback::stop() { + active = false; +} +bool AudioStreamGeneratorPlayback::is_playing() const { + + return active; //always playing, can't be stopped +} + +int AudioStreamGeneratorPlayback::get_loop_count() const { + return 0; +} + +float AudioStreamGeneratorPlayback::get_playback_position() const { + return mixed; +} +void AudioStreamGeneratorPlayback::seek(float p_time) { + //no seek possible +} + +void AudioStreamGeneratorPlayback::_bind_methods() { + ClassDB::bind_method(D_METHOD("push_frame", "frame"), &AudioStreamGeneratorPlayback::push_frame); + ClassDB::bind_method(D_METHOD("can_push_buffer", "amount"), &AudioStreamGeneratorPlayback::can_push_buffer); + ClassDB::bind_method(D_METHOD("push_buffer", "frames"), &AudioStreamGeneratorPlayback::push_buffer); + ClassDB::bind_method(D_METHOD("get_frames_available"), &AudioStreamGeneratorPlayback::get_frames_available); + ClassDB::bind_method(D_METHOD("get_skips"), &AudioStreamGeneratorPlayback::get_skips); + ClassDB::bind_method(D_METHOD("clear_buffer"), &AudioStreamGeneratorPlayback::clear_buffer); +} + +AudioStreamGeneratorPlayback::AudioStreamGeneratorPlayback() { + generator = NULL; + skips = 0; + active = false; + mixed = 0; +} diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h new file mode 100644 index 0000000000..2082682907 --- /dev/null +++ b/servers/audio/effects/audio_stream_generator.h @@ -0,0 +1,66 @@ +#ifndef AUDIO_STREAM_USER_FED_H +#define AUDIO_STREAM_USER_FED_H + +#include "core/ring_buffer.h" +#include "servers/audio/audio_stream.h" + +class AudioStreamGenerator : public AudioStream { + GDCLASS(AudioStreamGenerator, AudioStream) + + float mix_rate; + float buffer_len; + +protected: + static void _bind_methods(); + +public: + void set_mix_rate(float p_mix_rate); + float get_mix_rate() const; + + void set_buffer_length(float p_seconds); + float get_buffer_length() const; + + virtual Ref<AudioStreamPlayback> instance_playback(); + virtual String get_stream_name() const; + + virtual float get_length() const; + AudioStreamGenerator(); +}; + +class AudioStreamGeneratorPlayback : public AudioStreamPlaybackResampled { + + GDCLASS(AudioStreamGeneratorPlayback, AudioStreamPlaybackResampled) + friend class AudioStreamGenerator; + RingBuffer<AudioFrame> buffer; + int skips; + bool active; + float mixed; + AudioStreamGenerator *generator; + +protected: + virtual void _mix_internal(AudioFrame *p_buffer, int p_frames); + virtual float get_stream_sampling_rate(); + + static void _bind_methods(); + +public: + virtual void start(float p_from_pos = 0.0); + virtual void stop(); + virtual bool is_playing() const; + + virtual int get_loop_count() const; //times it looped + + virtual float get_playback_position() const; + virtual void seek(float p_time); + + bool push_frame(const Vector2 &p_frame); + bool can_push_buffer(int p_frames) const; + bool push_buffer(const PoolVector2Array &p_frames); + int get_frames_available() const; + int get_skips() const; + + void clear_buffer(); + + AudioStreamGeneratorPlayback(); +}; +#endif // AUDIO_STREAM_USER_FED_H diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 8c092a02a2..fc3ecedd03 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -68,16 +68,21 @@ void AudioDriver::audio_server_process(int p_frames, int32_t *p_buffer, bool p_u void AudioDriver::update_mix_time(int p_frames) { - _mix_amount += p_frames; + _last_mix_frames = p_frames; if (OS::get_singleton()) _last_mix_time = OS::get_singleton()->get_ticks_usec(); } -double AudioDriver::get_mix_time() const { +double AudioDriver::get_time_since_last_mix() const { + + return (OS::get_singleton()->get_ticks_usec() - _last_mix_time) / 1000000.0; +} + +double AudioDriver::get_time_to_next_mix() const { double total = (OS::get_singleton()->get_ticks_usec() - _last_mix_time) / 1000000.0; - total += _mix_amount / (double)get_mix_rate(); - return total; + double mix_buffer = _last_mix_frames / (double)get_mix_rate(); + return mix_buffer - total; } void AudioDriver::input_buffer_init(int driver_buffer_frames) { @@ -148,7 +153,7 @@ Array AudioDriver::capture_get_device_list() { AudioDriver::AudioDriver() { _last_mix_time = 0; - _mix_amount = 0; + _last_mix_frames = 0; input_position = 0; input_size = 0; @@ -281,13 +286,6 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) { to_mix -= to_copy; } - // Calculate latency for Performance.AUDIO_OUTPUT_LATENCY - if (OS::get_singleton()) { - uint64_t ticks = OS::get_singleton()->get_ticks_usec(); - output_latency = (ticks - output_latency_ticks) / 1000000.f; - output_latency_ticks = ticks; - } - #ifdef DEBUG_ENABLED prof_time += OS::get_singleton()->get_ticks_usec() - prof_ticks; #endif @@ -876,6 +874,15 @@ int AudioServer::get_bus_effect_count(int p_bus) { return buses[p_bus]->effects.size(); } +Ref<AudioEffectInstance> AudioServer::get_bus_effect_instance(int p_bus, int p_effect, int p_channel) { + + ERR_FAIL_INDEX_V(p_bus, buses.size(), Ref<AudioEffectInstance>()); + ERR_FAIL_INDEX_V(p_effect, buses[p_bus]->effects.size(), Ref<AudioEffectInstance>()); + ERR_FAIL_INDEX_V(p_channel, buses[p_bus]->channels.size(), Ref<AudioEffectInstance>()); + + return buses[p_bus]->channels[p_channel].effect_instances[p_effect]; +} + Ref<AudioEffect> AudioServer::get_bus_effect(int p_bus, int p_effect) { ERR_FAIL_INDEX_V(p_bus, buses.size(), Ref<AudioEffect>()); @@ -1045,8 +1052,10 @@ void AudioServer::update() { void AudioServer::load_default_bus_layout() { - if (ResourceLoader::exists("res://default_bus_layout.tres")) { - Ref<AudioBusLayout> default_layout = ResourceLoader::load("res://default_bus_layout.tres"); + String layout_path = ProjectSettings::get_singleton()->get("audio/default_bus_layout"); + + if (ResourceLoader::exists(layout_path)) { + Ref<AudioBusLayout> default_layout = ResourceLoader::load(layout_path); if (default_layout.is_valid()) { set_bus_layout(default_layout); } @@ -1096,13 +1105,19 @@ AudioServer *AudioServer::get_singleton() { return singleton; } -double AudioServer::get_mix_time() const { +double AudioServer::get_output_latency() const { - return 0; + return AudioDriver::get_singleton()->get_latency(); } -double AudioServer::get_output_delay() const { - return 0; +double AudioServer::get_time_to_next_mix() const { + + return AudioDriver::get_singleton()->get_time_to_next_mix(); +} + +double AudioServer::get_time_since_last_mix() const { + + return AudioDriver::get_singleton()->get_time_since_last_mix(); } AudioServer *AudioServer::singleton = NULL; @@ -1328,6 +1343,7 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bus_effect_count", "bus_idx"), &AudioServer::get_bus_effect_count); ClassDB::bind_method(D_METHOD("get_bus_effect", "bus_idx", "effect_idx"), &AudioServer::get_bus_effect); + ClassDB::bind_method(D_METHOD("get_bus_effect_instance", "bus_idx", "effect_idx", "channel"), &AudioServer::get_bus_effect_instance, DEFVAL(0)); ClassDB::bind_method(D_METHOD("swap_bus_effects", "bus_idx", "effect_idx", "by_effect_idx"), &AudioServer::swap_bus_effects); ClassDB::bind_method(D_METHOD("set_bus_effect_enabled", "bus_idx", "effect_idx", "enabled"), &AudioServer::set_bus_effect_enabled); @@ -1345,6 +1361,10 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_device"), &AudioServer::get_device); ClassDB::bind_method(D_METHOD("set_device", "device"), &AudioServer::set_device); + ClassDB::bind_method(D_METHOD("get_time_to_next_mix"), &AudioServer::get_time_to_next_mix); + ClassDB::bind_method(D_METHOD("get_time_since_last_mix"), &AudioServer::get_time_since_last_mix); + ClassDB::bind_method(D_METHOD("get_output_latency"), &AudioServer::get_output_latency); + ClassDB::bind_method(D_METHOD("capture_get_device_list"), &AudioServer::capture_get_device_list); ClassDB::bind_method(D_METHOD("capture_get_device"), &AudioServer::capture_get_device); ClassDB::bind_method(D_METHOD("capture_set_device", "name"), &AudioServer::capture_set_device); @@ -1374,6 +1394,8 @@ AudioServer::AudioServer() { #ifdef DEBUG_ENABLED prof_time = 0; #endif + mix_time = 0; + mix_size = 0; } AudioServer::~AudioServer() { diff --git a/servers/audio_server.h b/servers/audio_server.h index 6bd8093c76..8c0ffd5a6b 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -45,7 +45,7 @@ class AudioDriver { static AudioDriver *singleton; uint64_t _last_mix_time; - uint64_t _mix_amount; + uint64_t _last_mix_frames; #ifdef DEBUG_ENABLED uint64_t prof_ticks; @@ -71,7 +71,8 @@ protected: #endif public: - double get_mix_time() const; //useful for video -> audio sync + double get_time_since_last_mix() const; //useful for video -> audio sync + double get_time_to_next_mix() const; enum SpeakerMode { SPEAKER_MODE_STEREO, @@ -148,7 +149,7 @@ class AudioServer : public Object { GDCLASS(AudioServer, Object) public: - //re-expose this her, as AudioDriver is not exposed to script + //re-expose this here, as AudioDriver is not exposed to script enum SpeakerMode { SPEAKER_MODE_STEREO, SPEAKER_SURROUND_31, @@ -163,6 +164,9 @@ public: typedef void (*AudioCallback)(void *p_userdata); private: + uint64_t mix_time; + int mix_size; + uint32_t buffer_size; uint64_t mix_count; uint64_t mix_frames; @@ -322,6 +326,7 @@ public: int get_bus_effect_count(int p_bus); Ref<AudioEffect> get_bus_effect(int p_bus, int p_effect); + Ref<AudioEffectInstance> get_bus_effect_instance(int p_bus, int p_effect, int p_channel = 0); void swap_bus_effects(int p_bus, int p_effect, int p_by_effect); @@ -350,8 +355,9 @@ public: static AudioServer *get_singleton(); - virtual double get_mix_time() const; //useful for video -> audio sync - virtual double get_output_delay() const; + virtual double get_output_latency() const; + virtual double get_time_to_next_mix() const; + virtual double get_time_since_last_mix() const; void *audio_data_alloc(uint32_t p_data_len, const uint8_t *p_from_data = NULL); void audio_data_free(void *p_data); @@ -376,7 +382,6 @@ public: String capture_get_device(); void capture_set_device(const String &p_name); - float get_output_latency() { return output_latency; } AudioServer(); virtual ~AudioServer(); }; diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index f0fbbafe1c..b4c3670a7b 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -196,7 +196,8 @@ void BodySW::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) { angular_damp = p_value; } break; - default: {} + default: { + } } } @@ -226,7 +227,8 @@ real_t BodySW::get_param(PhysicsServer::BodyParameter p_param) const { return angular_damp; } break; - default: {} + default: { + } } return 0; @@ -474,7 +476,8 @@ void BodySW::integrate_forces(real_t p_step) { _compute_area_gravity_and_dampenings(aa[i].area); stopped = mode == PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE; } break; - default: {} + default: { + } } } } diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp index 085ad4f9ea..b1c21290ab 100644 --- a/servers/physics/collision_object_sw.cpp +++ b/servers/physics/collision_object_sw.cpp @@ -32,13 +32,14 @@ #include "servers/physics/physics_server_sw.h" #include "space_sw.h" -void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform) { +void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform, bool p_disabled) { Shape s; s.shape = p_shape; s.xform = p_transform; s.xform_inv = s.xform.affine_inverse(); s.bpid = 0; //needs update + s.disabled = p_disabled; shapes.push_back(s); p_shape->add_owner(this); diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h index 5c14d5aaf9..c2c3fe0e5a 100644 --- a/servers/physics/collision_object_sw.h +++ b/servers/physics/collision_object_sw.h @@ -118,7 +118,7 @@ public: void _shape_changed(); _FORCE_INLINE_ Type get_type() const { return type; } - void add_shape(ShapeSW *p_shape, const Transform &p_transform = Transform()); + void add_shape(ShapeSW *p_shape, const Transform &p_transform = Transform(), bool p_disabled = false); void set_shape(int p_index, ShapeSW *p_shape); void set_shape_transform(int p_index, const Transform &p_transform); _FORCE_INLINE_ int get_shape_count() const { return shapes.size(); } diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp index baf7431e28..3073cc8b11 100644 --- a/servers/physics/collision_solver_sat.cpp +++ b/servers/physics/collision_solver_sat.cpp @@ -98,7 +98,7 @@ static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_ Vector3 c = rel_A.cross(rel_B).cross(rel_B); - if (Math::abs(rel_A.dot(c)) < CMP_EPSILON) { + if (Math::is_zero_approx(rel_A.dot(c))) { // should handle somehow.. //ERR_PRINT("TODO FIX"); @@ -678,7 +678,7 @@ static void _collision_box_box(const ShapeSW *p_a, const Transform &p_transform_ Vector3 axis = p_transform_a.basis.get_axis(i).cross(p_transform_b.basis.get_axis(j)); - if (axis.length_squared() < CMP_EPSILON) + if (Math::is_zero_approx(axis.length_squared())) continue; axis.normalize(); @@ -767,7 +767,7 @@ static void _collision_box_capsule(const ShapeSW *p_a, const Transform &p_transf // cylinder Vector3 box_axis = p_transform_a.basis.get_axis(i); Vector3 axis = box_axis.cross(cyl_axis); - if (axis.length_squared() < CMP_EPSILON) + if (Math::is_zero_approx(axis.length_squared())) continue; if (!separator.test_axis(axis.normalized())) diff --git a/servers/physics/joints/cone_twist_joint_sw.cpp b/servers/physics/joints/cone_twist_joint_sw.cpp index 268b9eefeb..1b3de3e913 100644 --- a/servers/physics/joints/cone_twist_joint_sw.cpp +++ b/servers/physics/joints/cone_twist_joint_sw.cpp @@ -127,10 +127,10 @@ bool ConeTwistJointSW::setup(real_t p_timestep) { Vector3 relPos = pivotBInW - pivotAInW; Vector3 normal[3]; - if (relPos.length_squared() > CMP_EPSILON) { - normal[0] = relPos.normalized(); - } else { + if (Math::is_zero_approx(relPos.length_squared())) { normal[0] = Vector3(real_t(1.0), 0, 0); + } else { + normal[0] = relPos.normalized(); } plane_space(normal[0], normal[1], normal[2]); diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp index 756348f448..813d9b7704 100644 --- a/servers/physics/joints/generic_6dof_joint_sw.cpp +++ b/servers/physics/joints/generic_6dof_joint_sw.cpp @@ -107,7 +107,7 @@ real_t G6DOFRotationalLimitMotorSW::solveAngularLimits( // correction velocity real_t motor_relvel = m_limitSoftness * (target_velocity - m_damping * rel_vel); - if (motor_relvel < CMP_EPSILON && motor_relvel > -CMP_EPSILON) { + if (Math::is_zero_approx(motor_relvel)) { return 0.0f; //no need for applying force } diff --git a/servers/physics/joints/hinge_joint_sw.cpp b/servers/physics/joints/hinge_joint_sw.cpp index e972496b2b..1d1b30286e 100644 --- a/servers/physics/joints/hinge_joint_sw.cpp +++ b/servers/physics/joints/hinge_joint_sw.cpp @@ -167,10 +167,10 @@ bool HingeJointSW::setup(real_t p_step) { Vector3 relPos = pivotBInW - pivotAInW; Vector3 normal[3]; - if (relPos.length_squared() > CMP_EPSILON) { - normal[0] = relPos.normalized(); - } else { + if (Math::is_zero_approx(relPos.length_squared())) { normal[0] = Vector3(real_t(1.0), 0, 0); + } else { + normal[0] = relPos.normalized(); } plane_space(normal[0], normal[1], normal[2]); diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 36d18e8901..7b982e7015 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -283,7 +283,7 @@ PhysicsServer::AreaSpaceOverrideMode PhysicsServerSW::area_get_space_override_mo return area->get_space_override_mode(); } -void PhysicsServerSW::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform) { +void PhysicsServerSW::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform, bool p_disabled) { AreaSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); @@ -291,7 +291,7 @@ void PhysicsServerSW::area_add_shape(RID p_area, RID p_shape, const Transform &p ShapeSW *shape = shape_owner.get(p_shape); ERR_FAIL_COND(!shape); - area->add_shape(shape, p_transform); + area->add_shape(shape, p_transform, p_disabled); } void PhysicsServerSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { @@ -365,7 +365,7 @@ void PhysicsServerSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool area->set_shape_as_disabled(p_shape_idx, p_disabled); } -void PhysicsServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_ID) { +void PhysicsServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) { if (space_owner.owns(p_area)) { SpaceSW *space = space_owner.get(p_area); @@ -373,7 +373,7 @@ void PhysicsServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_ID) } AreaSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); - area->set_instance_id(p_ID); + area->set_instance_id(p_id); } ObjectID PhysicsServerSW::area_get_object_instance_id(RID p_area) const { @@ -540,7 +540,7 @@ PhysicsServer::BodyMode PhysicsServerSW::body_get_mode(RID p_body) const { return body->get_mode(); }; -void PhysicsServerSW::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform) { +void PhysicsServerSW::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -548,7 +548,7 @@ void PhysicsServerSW::body_add_shape(RID p_body, RID p_shape, const Transform &p ShapeSW *shape = shape_owner.get(p_shape); ERR_FAIL_COND(!shape); - body->add_shape(shape, p_transform); + body->add_shape(shape, p_transform, p_disabled); } void PhysicsServerSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { @@ -673,12 +673,12 @@ uint32_t PhysicsServerSW::body_get_collision_mask(RID p_body) const { return body->get_collision_mask(); } -void PhysicsServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_ID) { +void PhysicsServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_id) { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); - body->set_instance_id(p_ID); + body->set_instance_id(p_id); }; uint32_t PhysicsServerSW::body_get_object_instance_id(RID p_body) const { diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 5d0ba3628e..b593e9b5f1 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -119,7 +119,7 @@ public: virtual void area_set_space(RID p_area, RID p_space); virtual RID area_get_space(RID p_area) const; - virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform()); + virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false); virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape); virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform); @@ -132,7 +132,7 @@ public: virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled); - virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID); + virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id); virtual ObjectID area_get_object_instance_id(RID p_area) const; virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value); @@ -163,7 +163,7 @@ public: virtual void body_set_mode(RID p_body, BodyMode p_mode); virtual BodyMode body_get_mode(RID p_body) const; - virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform()); + virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false); virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape); virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform); @@ -176,7 +176,7 @@ public: virtual void body_remove_shape(RID p_body, int p_shape_idx); virtual void body_clear_shapes(RID p_body); - virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID); + virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id); virtual uint32_t body_get_object_instance_id(RID p_body) const; virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable); diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index 4ab92715f4..8b9f210850 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -351,10 +351,8 @@ bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_sh CollisionSolverSW::CallbackResult cbkres = NULL; PhysicsServerSW::CollCbkData *cbkptr = NULL; - if (p_result_max > 0) { - cbkptr = &cbk; - cbkres = PhysicsServerSW::_shape_col_cbk; - } + cbkptr = &cbk; + cbkres = PhysicsServerSW::_shape_col_cbk; for (int i = 0; i < amount; i++) { @@ -632,7 +630,7 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo int ray_index = -1; //reuse shape for (int k = 0; k < rays_found; k++) { - if (r_results[ray_index].collision_local_shape == j) { + if (r_results[k].collision_local_shape == j) { ray_index = k; } } diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index 60bcb2e28e..60bbcef4b6 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -174,7 +174,8 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value) angular_damp = p_value; } break; - default: {} + default: { + } } } @@ -206,7 +207,8 @@ real_t Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { return angular_damp; } break; - default: {} + default: { + } } return 0; @@ -443,7 +445,8 @@ void Body2DSW::integrate_forces(real_t p_step) { _compute_area_gravity_and_dampenings(aa[i].area); stopped = mode == Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE; } break; - default: {} + default: { + } } } } diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp index 4ec92497e7..445a2e0613 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/collision_object_2d_sw.cpp @@ -31,14 +31,14 @@ #include "collision_object_2d_sw.h" #include "space_2d_sw.h" -void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_transform) { +void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_transform, bool p_disabled) { Shape s; s.shape = p_shape; s.xform = p_transform; s.xform_inv = s.xform.affine_inverse(); s.bpid = 0; //needs update - s.disabled = false; + s.disabled = p_disabled; s.one_way_collision = false; s.one_way_collision_margin = 0; shapes.push_back(s); diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index d5e815ff45..fa18e61262 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -111,7 +111,7 @@ public: void _shape_changed(); _FORCE_INLINE_ Type get_type() const { return type; } - void add_shape(Shape2DSW *p_shape, const Transform2D &p_transform = Transform2D()); + void add_shape(Shape2DSW *p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); void set_shape(int p_index, Shape2DSW *p_shape); void set_shape_transform(int p_index, const Transform2D &p_transform); void set_shape_metadata(int p_index, const Variant &p_metadata); diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp index d6c3fff421..f4bff66389 100644 --- a/servers/physics_2d/collision_solver_2d_sat.cpp +++ b/servers/physics_2d/collision_solver_2d_sat.cpp @@ -237,8 +237,8 @@ public: Vector2 axis = p_axis; - if (Math::abs(axis.x) < CMP_EPSILON && - Math::abs(axis.y) < CMP_EPSILON) { + if (Math::is_zero_approx(axis.x) && + Math::is_zero_approx(axis.y)) { // strange case, try an upwards separator axis = Vector2(0.0, 1.0); } 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 283d20876d..0efa15d43e 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -378,7 +378,7 @@ Physics2DServer::AreaSpaceOverrideMode Physics2DServerSW::area_get_space_overrid return area->get_space_override_mode(); } -void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform) { +void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) { Area2DSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); @@ -386,7 +386,7 @@ void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Transform2 Shape2DSW *shape = shape_owner.get(p_shape); ERR_FAIL_COND(!shape); - area->add_shape(shape, p_transform); + area->add_shape(shape, p_transform, p_disabled); } void Physics2DServerSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { @@ -460,7 +460,7 @@ void Physics2DServerSW::area_clear_shapes(RID p_area) { area->remove_shape(0); } -void Physics2DServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_ID) { +void Physics2DServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) { if (space_owner.owns(p_area)) { Space2DSW *space = space_owner.get(p_area); @@ -468,7 +468,7 @@ void Physics2DServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_ID } Area2DSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); - area->set_instance_id(p_ID); + area->set_instance_id(p_id); } ObjectID Physics2DServerSW::area_get_object_instance_id(RID p_area) const { @@ -481,7 +481,7 @@ ObjectID Physics2DServerSW::area_get_object_instance_id(RID p_area) const { return area->get_instance_id(); } -void Physics2DServerSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_ID) { +void Physics2DServerSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_id) { if (space_owner.owns(p_area)) { Space2DSW *space = space_owner.get(p_area); @@ -489,7 +489,7 @@ void Physics2DServerSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_ID } Area2DSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); - area->set_canvas_instance_id(p_ID); + area->set_canvas_instance_id(p_id); } ObjectID Physics2DServerSW::area_get_canvas_instance_id(RID p_area) const { @@ -643,7 +643,7 @@ Physics2DServer::BodyMode Physics2DServerSW::body_get_mode(RID p_body) const { return body->get_mode(); }; -void Physics2DServerSW::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform) { +void Physics2DServerSW::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -651,7 +651,7 @@ void Physics2DServerSW::body_add_shape(RID p_body, RID p_shape, const Transform2 Shape2DSW *shape = shape_owner.get(p_shape); ERR_FAIL_COND(!shape); - body->add_shape(shape, p_transform); + body->add_shape(shape, p_transform, p_disabled); } void Physics2DServerSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { @@ -763,12 +763,12 @@ Physics2DServerSW::CCDMode Physics2DServerSW::body_get_continuous_collision_dete return body->get_continuous_collision_detection_mode(); } -void Physics2DServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_ID) { +void Physics2DServerSW::body_attach_object_instance_id(RID p_body, uint32_t p_id) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); - body->set_instance_id(p_ID); + body->set_instance_id(p_id); }; uint32_t Physics2DServerSW::body_get_object_instance_id(RID p_body) const { @@ -779,12 +779,12 @@ uint32_t Physics2DServerSW::body_get_object_instance_id(RID p_body) const { return body->get_instance_id(); }; -void Physics2DServerSW::body_attach_canvas_instance_id(RID p_body, uint32_t p_ID) { +void Physics2DServerSW::body_attach_canvas_instance_id(RID p_body, uint32_t p_id) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); - body->set_canvas_instance_id(p_ID); + body->set_canvas_instance_id(p_id); }; uint32_t Physics2DServerSW::body_get_canvas_instance_id(RID p_body) const { diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 4beec41442..adc011af40 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -131,7 +131,7 @@ public: virtual void area_set_space(RID p_area, RID p_space); virtual RID area_get_space(RID p_area) const; - virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D()); + virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape); virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform); @@ -144,10 +144,10 @@ public: virtual void area_remove_shape(RID p_area, int p_shape_idx); virtual void area_clear_shapes(RID p_area); - virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID); + virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id); virtual ObjectID area_get_object_instance_id(RID p_area) const; - virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_ID); + virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_id); virtual ObjectID area_get_canvas_instance_id(RID p_area) const; virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value); @@ -175,7 +175,7 @@ public: virtual void body_set_mode(RID p_body, BodyMode p_mode); virtual BodyMode body_get_mode(RID p_body) const; - virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D()); + virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape); virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform); virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata); @@ -191,10 +191,10 @@ public: virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled); virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, float p_margin); - virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID); + virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id); virtual uint32_t body_get_object_instance_id(RID p_body) const; - virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_ID); + virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_id); virtual uint32_t body_get_canvas_instance_id(RID p_body) const; virtual void body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 5b9a102a1b..b61e1faad2 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -140,7 +140,7 @@ public: FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode); FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID); - FUNC3(area_add_shape, RID, RID, const Transform2D &); + FUNC4(area_add_shape, RID, RID, const Transform2D &, bool); FUNC3(area_set_shape, RID, int, RID); FUNC3(area_set_shape_transform, RID, int, const Transform2D &); FUNC3(area_set_shape_disabled, RID, int, bool); @@ -183,7 +183,7 @@ public: FUNC2(body_set_mode, RID, BodyMode); FUNC1RC(BodyMode, body_get_mode, RID); - FUNC3(body_add_shape, RID, RID, const Transform2D &); + FUNC4(body_add_shape, RID, RID, const Transform2D &, bool); FUNC3(body_set_shape, RID, int, RID); FUNC3(body_set_shape_transform, RID, int, const Transform2D &); FUNC3(body_set_shape_metadata, RID, int, const Variant &); diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index 56b87f620c..0043b948b0 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -240,12 +240,7 @@ bool SegmentShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 & real_t SegmentShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { - Vector2 s[2] = { a * p_scale, b * p_scale }; - - real_t l = s[1].distance_to(s[0]); - Vector2 ofs = (s[0] + s[1]) * 0.5; - - return p_mass * (l * l / 12.0 + ofs.length_squared()); + return p_mass * ((a * p_scale).distance_squared_to(b * p_scale)) / 12; } void SegmentShape2DSW::set_data(const Variant &p_data) { @@ -318,7 +313,9 @@ bool CircleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p real_t CircleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { - return (radius * radius) * (p_scale.x * 0.5 + p_scale.y * 0.5); + real_t a = radius * p_scale.x; + real_t b = radius * p_scale.y; + return p_mass * (a * a + b * b) / 4; } void CircleShape2DSW::set_data(const Variant &p_data) { @@ -586,7 +583,7 @@ bool ConvexPolygonShape2DSW::contains_point(const Vector2 &p_point) const { in = true; } - return (in && !out) || (!in && out); + return in != out; } bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { @@ -637,7 +634,7 @@ real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 aabb.expand_to(points[i].pos * p_scale); } - return p_mass * aabb.size.dot(aabb.size) / 12.0 + p_mass * (aabb.position + aabb.size * 0.5).length_squared(); + return p_mass * aabb.size.dot(aabb.size) / 12.0; } void ConvexPolygonShape2DSW::set_data(const Variant &p_data) { diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 831764b40c..e2b1bb9da4 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -333,10 +333,8 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D & CollisionSolver2DSW::CallbackResult cbkres = NULL; Physics2DServerSW::CollCbkData *cbkptr = NULL; - if (p_result_max > 0) { - cbkptr = &cbk; - cbkres = Physics2DServerSW::_shape_col_cbk; - } + cbkptr = &cbk; + cbkres = Physics2DServerSW::_shape_col_cbk; for (int i = 0; i < amount; i++) { @@ -353,7 +351,7 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D & cbk.valid_depth = 0; if (CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) { - collided = p_result_max == 0 || cbk.amount > 0; + collided = cbk.amount > 0; } } @@ -797,7 +795,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized(); float owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx); - cbk.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it wont work + cbk.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work cbk.invalid_by_dir = 0; if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) { diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 3a05791f17..dadadf68fd 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -567,10 +567,10 @@ void Physics2DServer::_bind_methods() { ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &Physics2DServer::area_set_space_override_mode); ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &Physics2DServer::area_get_space_override_mode); - ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform"), &Physics2DServer::area_add_shape, DEFVAL(Transform2D())); + ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &Physics2DServer::area_add_shape, DEFVAL(Transform2D()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &Physics2DServer::area_set_shape); ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &Physics2DServer::area_set_shape_transform); - ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disable"), &Physics2DServer::area_set_shape_disabled); + ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disabled"), &Physics2DServer::area_set_shape_disabled); ClassDB::bind_method(D_METHOD("area_get_shape_count", "area"), &Physics2DServer::area_get_shape_count); ClassDB::bind_method(D_METHOD("area_get_shape", "area", "shape_idx"), &Physics2DServer::area_get_shape); @@ -606,7 +606,7 @@ void Physics2DServer::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_mode", "body", "mode"), &Physics2DServer::body_set_mode); ClassDB::bind_method(D_METHOD("body_get_mode", "body"), &Physics2DServer::body_get_mode); - ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform"), &Physics2DServer::body_add_shape, DEFVAL(Transform2D())); + ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &Physics2DServer::body_add_shape, DEFVAL(Transform2D()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &Physics2DServer::body_set_shape); ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &Physics2DServer::body_set_shape_transform); ClassDB::bind_method(D_METHOD("body_set_shape_metadata", "body", "shape_idx", "metadata"), &Physics2DServer::body_set_shape_metadata); @@ -619,7 +619,7 @@ void Physics2DServer::_bind_methods() { ClassDB::bind_method(D_METHOD("body_remove_shape", "body", "shape_idx"), &Physics2DServer::body_remove_shape); 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_disabled", "body", "shape_idx", "disabled"), &Physics2DServer::body_set_shape_disabled); 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); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 1de9c7df93..46b22d6777 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -335,7 +335,7 @@ public: virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0; virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0; - virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D()) = 0; + virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0; virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) = 0; @@ -348,10 +348,10 @@ public: virtual void area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) = 0; - virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID) = 0; + virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id) = 0; virtual ObjectID area_get_object_instance_id(RID p_area) const = 0; - virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_ID) = 0; + virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_id) = 0; virtual ObjectID area_get_canvas_instance_id(RID p_area) const = 0; virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0; @@ -388,7 +388,7 @@ public: virtual void body_set_mode(RID p_body, BodyMode p_mode) = 0; virtual BodyMode body_get_mode(RID p_body) const = 0; - virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D()) = 0; + virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0; virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0; virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) = 0; virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata) = 0; @@ -404,10 +404,10 @@ public: virtual void body_remove_shape(RID p_body, int p_shape_idx) = 0; virtual void body_clear_shapes(RID p_body) = 0; - virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID) = 0; + virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id) = 0; virtual uint32_t body_get_object_instance_id(RID p_body) const = 0; - virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_ID) = 0; + virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_id) = 0; virtual uint32_t body_get_canvas_instance_id(RID p_body) const = 0; enum CCDMode { @@ -653,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 0629af663e..fe8c644f0b 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -427,9 +427,10 @@ void PhysicsServer::_bind_methods() { ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer::area_set_space_override_mode); ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer::area_get_space_override_mode); - ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform"), &PhysicsServer::area_add_shape, DEFVAL(Transform())); + ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer::area_add_shape, DEFVAL(Transform()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer::area_set_shape); ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer::area_set_shape_transform); + ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disabled"), &PhysicsServer::area_set_shape_disabled); ClassDB::bind_method(D_METHOD("area_get_shape_count", "area"), &PhysicsServer::area_get_shape_count); ClassDB::bind_method(D_METHOD("area_get_shape", "area", "shape_idx"), &PhysicsServer::area_get_shape); @@ -471,9 +472,10 @@ void PhysicsServer::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer::body_set_collision_mask); ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer::body_get_collision_mask); - ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform"), &PhysicsServer::body_add_shape, DEFVAL(Transform())); + ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer::body_add_shape, DEFVAL(Transform()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &PhysicsServer::body_set_shape); ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer::body_set_shape_transform); + ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disabled"), &PhysicsServer::body_set_shape_disabled); ClassDB::bind_method(D_METHOD("body_get_shape_count", "body"), &PhysicsServer::body_get_shape_count); ClassDB::bind_method(D_METHOD("body_get_shape", "body", "shape_idx"), &PhysicsServer::body_get_shape); diff --git a/servers/physics_server.h b/servers/physics_server.h index c71bb01943..5e5964ca8d 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -320,7 +320,7 @@ public: virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0; virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0; - virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform()) = 0; + virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0; virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) = 0; @@ -333,7 +333,7 @@ public: virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) = 0; - virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID) = 0; + virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id) = 0; virtual ObjectID area_get_object_instance_id(RID p_area) const = 0; virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0; @@ -372,7 +372,7 @@ public: virtual void body_set_mode(RID p_body, BodyMode p_mode) = 0; virtual BodyMode body_get_mode(RID p_body) const = 0; - virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform()) = 0; + virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0; virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0; virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) = 0; @@ -385,7 +385,7 @@ public: virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) = 0; - virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID) = 0; + virtual void body_attach_object_instance_id(RID p_body, uint32_t p_id) = 0; virtual uint32_t body_get_object_instance_id(RID p_body) const = 0; virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) = 0; @@ -794,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 0cc1cc119c..f3394019f5 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -50,7 +50,9 @@ #include "audio/effects/audio_effect_pitch_shift.h" #include "audio/effects/audio_effect_record.h" #include "audio/effects/audio_effect_reverb.h" +#include "audio/effects/audio_effect_spectrum_analyzer.h" #include "audio/effects/audio_effect_stereo_enhance.h" +#include "audio/effects/audio_stream_generator.h" #include "audio_server.h" #include "core/script_debugger_remote.h" #include "physics/physics_server_sw.h" @@ -120,13 +122,18 @@ void register_server_types() { ClassDB::register_virtual_class<AudioStream>(); ClassDB::register_virtual_class<AudioStreamPlayback>(); + ClassDB::register_virtual_class<AudioStreamPlaybackResampled>(); ClassDB::register_class<AudioStreamMicrophone>(); ClassDB::register_class<AudioStreamRandomPitch>(); ClassDB::register_virtual_class<AudioEffect>(); + ClassDB::register_virtual_class<AudioEffectInstance>(); ClassDB::register_class<AudioEffectEQ>(); ClassDB::register_class<AudioEffectFilter>(); ClassDB::register_class<AudioBusLayout>(); + ClassDB::register_class<AudioStreamGenerator>(); + ClassDB::register_virtual_class<AudioStreamGeneratorPlayback>(); + { //audio effects ClassDB::register_class<AudioEffectAmplify>(); @@ -156,7 +163,10 @@ void register_server_types() { ClassDB::register_class<AudioEffectLimiter>(); ClassDB::register_class<AudioEffectPitchShift>(); ClassDB::register_class<AudioEffectPhaser>(); + ClassDB::register_class<AudioEffectRecord>(); + ClassDB::register_class<AudioEffectSpectrumAnalyzer>(); + ClassDB::register_virtual_class<AudioEffectSpectrumAnalyzerInstance>(); } ClassDB::register_virtual_class<Physics2DDirectBodyState>(); diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index dd54698471..31888261ec 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -373,6 +373,7 @@ public: virtual void light_set_negative(RID p_light, bool p_enable) = 0; virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; + virtual void light_set_use_gi(RID p_light, bool p_enable) = 0; virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) = 0; virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) = 0; @@ -392,6 +393,7 @@ public: virtual AABB light_get_aabb(RID p_light) const = 0; virtual float light_get_param(RID p_light, VS::LightParam p_param) = 0; virtual Color light_get_color(RID p_light) = 0; + virtual bool light_get_use_gi(RID p_light) = 0; virtual uint64_t light_get_version(RID p_light) const = 0; /* PROBE API */ @@ -548,12 +550,15 @@ public: RENDER_TARGET_NO_SAMPLING, RENDER_TARGET_HDR, RENDER_TARGET_KEEP_3D_LINEAR, + RENDER_TARGET_DIRECT_TO_SCREEN, RENDER_TARGET_FLAG_MAX }; virtual RID render_target_create() = 0; + virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 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; @@ -788,6 +793,8 @@ public: RID mesh; RID texture; RID normal_map; + Transform2D transform; + Color modulate; CommandMesh() { type = TYPE_MESH; } }; @@ -1101,7 +1108,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 1f9d263354..6efd05593e 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -616,7 +616,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { else tk.type = TK_INT_CONSTANT; - tk.constant = str.to_double(); //wont work with hex + tk.constant = str.to_double(); //won't work with hex tk.line = tk_line; return tk; @@ -2968,6 +2968,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons member_type = DataType(dt - 1); } else if (l == 2) { member_type = dt; + } else if (l == 3) { + member_type = DataType(dt + 1); + } else if (l == 4) { + member_type = DataType(dt + 2); } else { ok = false; break; @@ -3001,6 +3005,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons member_type = DataType(dt - 1); } else if (l == 3) { member_type = dt; + } else if (l == 4) { + member_type = DataType(dt + 1); } else { ok = false; break; @@ -3620,7 +3626,8 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha case TYPE_FLOAT: { nv.real = -cn->values[i].real; } break; - default: {} + default: { + } } values.push_back(nv); @@ -4822,7 +4829,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct case TYPE_MAT2: limit = 2; break; case TYPE_MAT3: limit = 3; break; case TYPE_MAT4: limit = 4; break; - default: {} + default: { + } } for (int i = 0; i < limit; i++) { diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 7a42bc475e..bc6010117c 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -76,7 +76,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); @@ -147,6 +147,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["light"].can_discard = true; @@ -187,6 +188,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].modes.push_back("shadows_disabled"); shader_modes[VS::SHADER_SPATIAL].modes.push_back("ambient_light_disabled"); + shader_modes[VS::SHADER_SPATIAL].modes.push_back("shadow_to_opacity"); shader_modes[VS::SHADER_SPATIAL].modes.push_back("vertex_lighting"); diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 85dcaa6b03..d5e154a7fc 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -33,11 +33,9 @@ #include "visual_server_raster.h" #include "visual_server_viewport.h" -void VisualServerCanvas::_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) { +static const int z_range = VS::CANVAS_ITEM_Z_MAX - VS::CANVAS_ITEM_Z_MIN + 1; - static const int z_range = VS::CANVAS_ITEM_Z_MAX - VS::CANVAS_ITEM_Z_MIN + 1; - RasterizerCanvas::Item *z_list[z_range]; - RasterizerCanvas::Item *z_last_list[z_range]; +void VisualServerCanvas::_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) { memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); @@ -51,20 +49,23 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra } } -void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item **r_items, int &r_index) { +void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item *p_material_owner, VisualServerCanvas::Item **r_items, int &r_index) { int child_item_count = p_canvas_item->child_items.size(); VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw(); for (int i = 0; i < child_item_count; i++) { - if (r_items) { - r_items[r_index] = child_items[i]; - child_items[i]->ysort_xform = p_transform; - child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]); - } + if (child_items[i]->visible) { + if (r_items) { + r_items[r_index] = child_items[i]; + child_items[i]->ysort_xform = p_transform; + child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]); + child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : NULL; + } - r_index++; + r_index++; - if (child_items[i]->sort_y) - _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_index); + if (child_items[i]->sort_y) + _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index); + } } } @@ -124,14 +125,14 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor if (ci->ysort_children_count == -1) { ci->ysort_children_count = 0; - _collect_ysort_children(ci, Transform2D(), NULL, ci->ysort_children_count); + _collect_ysort_children(ci, Transform2D(), p_material_owner, NULL, ci->ysort_children_count); } child_item_count = ci->ysort_children_count; child_items = (Item **)alloca(child_item_count * sizeof(Item *)); int i = 0; - _collect_ysort_children(ci, Transform2D(), child_items, i); + _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i); SortArray<Item *, ItemPtrSort> sorter; sorter.sort(child_items, child_item_count); @@ -147,7 +148,7 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) continue; if (ci->sort_y) { - _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); } else { _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); } @@ -189,7 +190,7 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) continue; if (ci->sort_y) { - _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); } else { _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); } @@ -319,6 +320,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); @@ -380,6 +394,10 @@ void VisualServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible) { ERR_FAIL_COND(!canvas_item); canvas_item->visible = p_visible; + + if (canvas_item->parent.is_valid() && canvas_item_owner.owns(canvas_item->parent)) { + _mark_ysort_dirty(canvas_item_owner.get(canvas_item->parent), canvas_item_owner); + } } void VisualServerCanvas::canvas_item_set_light_mask(RID p_item, int p_mask) { @@ -616,7 +634,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) { @@ -810,7 +828,7 @@ void VisualServerCanvas::canvas_item_add_set_transform(RID p_item, const Transfo canvas_item->commands.push_back(tr); } -void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture, RID p_normal_map) { +void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture, RID p_normal_map) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -820,6 +838,8 @@ void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID m->mesh = p_mesh; m->texture = p_texture; m->normal_map = p_normal_map; + m->transform = p_transform; + m->modulate = p_modulate; canvas_item->commands.push_back(m); } @@ -1434,4 +1454,15 @@ bool VisualServerCanvas::free(RID p_rid) { } VisualServerCanvas::VisualServerCanvas() { + + z_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *)); + z_last_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *)); + + disable_scale = false; +} + +VisualServerCanvas::~VisualServerCanvas() { + + memfree(z_list); + memfree(z_last_list); } diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index 7d788cbe14..26424f927e 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -82,7 +82,7 @@ public: _FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const { - if (Math::abs(p_left->ysort_pos.y - p_right->ysort_pos.y) < CMP_EPSILON) + if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y)) return p_left->ysort_pos.x < p_right->ysort_pos.x; else return p_left->ysort_pos.y < p_right->ysort_pos.y; @@ -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,24 +145,32 @@ 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); void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights); + RasterizerCanvas::Item **z_list; + RasterizerCanvas::Item **z_last_list; + public: void render_canvas(Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect); 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); @@ -190,7 +200,7 @@ public: void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()); void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false); void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()); - void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID()); + void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID()); void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()); void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal); void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform); @@ -247,6 +257,7 @@ public: bool free(RID p_rid); VisualServerCanvas(); + ~VisualServerCanvas(); }; #endif // VISUALSERVERCANVAS_H diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index a9ca920178..310aa16130 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -201,8 +201,10 @@ VisualServerRaster::VisualServerRaster() { VSG::canvas_render = VSG::rasterizer->get_canvas(); VSG::scene_render = VSG::rasterizer->get_scene(); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { black_margin[i] = 0; + black_image[i] = RID(); + } } VisualServerRaster::~VisualServerRaster() { diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index a1204c7573..921d55556d 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -312,6 +312,7 @@ public: BIND2(light_set_negative, RID, bool) BIND2(light_set_cull_mask, RID, uint32_t) BIND2(light_set_reverse_cull_face_mode, RID, bool) + BIND2(light_set_use_gi, RID, bool) BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode) BIND2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail) @@ -430,6 +431,7 @@ public: BIND0R(RID, camera_create) BIND4(camera_set_perspective, RID, float, float, float) BIND4(camera_set_orthogonal, RID, float, float, float) + BIND5(camera_set_frustum, RID, float, Vector2, float, float) BIND2(camera_set_transform, RID, const Transform &) BIND2(camera_set_cull_mask, RID, uint32_t) BIND2(camera_set_environment, RID, RID) @@ -452,6 +454,7 @@ public: BIND2(viewport_set_clear_mode, RID, ViewportClearMode) BIND3(viewport_attach_to_screen, RID, const Rect2 &, int) + BIND2(viewport_set_render_direct_to_screen, RID, bool) BIND1(viewport_detach, RID) BIND2(viewport_set_update_mode, RID, ViewportUpdateMode) @@ -569,6 +572,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) @@ -598,7 +603,7 @@ public: BIND7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID) BIND7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool) BIND10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID) - BIND4(canvas_item_add_mesh, RID, const RID &, RID, RID) + BIND6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID) BIND4(canvas_item_add_multimesh, RID, RID, RID, RID) BIND4(canvas_item_add_particles, RID, RID, RID, RID) BIND2(canvas_item_add_set_transform, RID, const Transform2D &) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 2590e29aef..3ee23e9290 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -61,6 +61,16 @@ void VisualServerScene::camera_set_orthogonal(RID p_camera, float p_size, float camera->zfar = p_z_far; } +void VisualServerScene::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) { + Camera *camera = camera_owner.get(p_camera); + ERR_FAIL_COND(!camera); + camera->type = Camera::FRUSTUM; + camera->size = p_size; + camera->offset = p_offset; + camera->znear = p_z_near; + camera->zfar = p_z_far; +} + void VisualServerScene::camera_set_transform(RID p_camera, const Transform &p_transform) { Camera *camera = camera_owner.get(p_camera); @@ -399,7 +409,8 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { VSG::scene_render->free(gi_probe->probe_instance); } break; - default: {} + default: { + } } if (instance->base_data) { @@ -476,7 +487,8 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { gi_probe->probe_instance = VSG::scene_render->gi_probe_instance_create(); } break; - default: {} + default: { + } } VSG::storage->instance_add_dependency(p_base, instance); @@ -524,7 +536,8 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) { gi_probe_update_list.remove(&gi_probe->update_element); } } break; - default: {} + default: { + } } instance->scenario = NULL; @@ -556,7 +569,8 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) { gi_probe_update_list.add(&gi_probe->update_element); } } break; - default: {} + default: { + } } _instance_queue_update(instance, true, true); @@ -593,12 +607,12 @@ void VisualServerScene::instance_set_transform(RID p_instance, const Transform & instance->transform = p_transform; _instance_queue_update(instance, true); } -void VisualServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_ID) { +void VisualServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) { Instance *instance = instance_owner.get(p_instance); ERR_FAIL_COND(!instance); - instance->object_ID = p_ID; + instance->object_id = p_id; } void VisualServerScene::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) { @@ -671,7 +685,8 @@ void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) { } } break; - default: {} + default: { + } } } inline bool is_geometry_instance(VisualServer::InstanceType p_type) { @@ -776,10 +791,10 @@ Vector<ObjectID> VisualServerScene::instances_cull_aabb(const AABB &p_aabb, RID Instance *instance = cull[i]; ERR_CONTINUE(!instance); - if (instance->object_ID == 0) + if (instance->object_id == 0) continue; - instances.push_back(instance->object_ID); + instances.push_back(instance->object_id); } return instances; @@ -798,10 +813,10 @@ Vector<ObjectID> VisualServerScene::instances_cull_ray(const Vector3 &p_from, co for (int i = 0; i < culled; i++) { Instance *instance = cull[i]; ERR_CONTINUE(!instance); - if (instance->object_ID == 0) + if (instance->object_id == 0) continue; - instances.push_back(instance->object_ID); + instances.push_back(instance->object_id); } return instances; @@ -822,10 +837,10 @@ Vector<ObjectID> VisualServerScene::instances_cull_convex(const Vector<Plane> &p Instance *instance = cull[i]; ERR_CONTINUE(!instance); - if (instance->object_ID == 0) + if (instance->object_id == 0) continue; - instances.push_back(instance->object_ID); + instances.push_back(instance->object_id); } return instances; @@ -848,7 +863,8 @@ void VisualServerScene::instance_geometry_set_flag(RID p_instance, VS::InstanceF instance->redraw_if_visible = p_enabled; } break; - default: {} + default: { + } } } void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting) { @@ -1040,7 +1056,8 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) { new_aabb = VSG::storage->lightmap_capture_get_bounds(p_instance->base); } break; - default: {} + default: { + } } // <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs @@ -1723,6 +1740,17 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_view ortho = false; } break; + case Camera::FRUSTUM: { + + camera_matrix.set_frustum( + camera->size, + p_viewport_size.width / (float)p_viewport_size.height, + camera->offset, + camera->znear, + camera->zfar, + camera->vaspect); + ortho = false; + } break; } _prepare_scene(camera->transform, camera_matrix, ortho, camera->env, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); @@ -1864,7 +1892,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca //failure } else if (ins->base_type == VS::INSTANCE_LIGHT && ins->visible) { - if (ins->visible && light_cull_count < MAX_LIGHTS_CULLED) { + if (light_cull_count < MAX_LIGHTS_CULLED) { InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data); @@ -1881,7 +1909,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca } } else if (ins->base_type == VS::INSTANCE_REFLECTION_PROBE && ins->visible) { - if (ins->visible && reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) { + if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(ins->base_data); @@ -2626,7 +2654,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co for (int i = 0; i < 3; i++) { - if (ABS(light_axis[i]) < CMP_EPSILON) + if (Math::is_zero_approx(light_axis[i])) continue; clip[clip_planes].normal[i] = 1.0; @@ -2761,7 +2789,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co for (int c = 0; c < 3; c++) { - if (ABS(light_axis[c]) < CMP_EPSILON) + if (Math::is_zero_approx(light_axis[c])) continue; clip[clip_planes].normal[c] = 1.0; @@ -3089,6 +3117,9 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { for (List<Instance *>::Element *E = p_gi_probe->scenario->directional_lights.front(); E; E = E->next()) { + if (!VSG::storage->light_get_use_gi(E->get()->base)) + continue; + InstanceGIProbeData::LightCache lc; lc.type = VSG::storage->light_get_type(E->get()->base); lc.color = VSG::storage->light_get_color(E->get()->base); @@ -3109,6 +3140,9 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { for (Set<Instance *>::Element *E = probe_data->lights.front(); E; E = E->next()) { + if (!VSG::storage->light_get_use_gi(E->get()->base)) + continue; + InstanceGIProbeData::LightCache lc; lc.type = VSG::storage->light_get_type(E->get()->base); lc.color = VSG::storage->light_get_color(E->get()->base); diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index 7583acd88f..629d66c6cb 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -77,12 +77,14 @@ public: enum Type { PERSPECTIVE, - ORTHOGONAL + ORTHOGONAL, + FRUSTUM }; Type type; float fov; float znear, zfar; float size; + Vector2 offset; uint32_t visible_layers; bool vaspect; RID env; @@ -97,6 +99,7 @@ public: znear = 0.05; zfar = 100; size = 1.0; + offset = Vector2(); vaspect = false; } }; @@ -106,6 +109,7 @@ public: virtual RID camera_create(); virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far); virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); + virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far); virtual void camera_set_transform(RID p_camera, const Transform &p_transform); virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers); virtual void camera_set_environment(RID p_camera, RID p_env); @@ -170,7 +174,7 @@ public: AABB transformed_aabb; AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better? float extra_margin; - uint32_t object_ID; + uint32_t object_id; float lod_begin; float lod_end; @@ -207,7 +211,7 @@ public: extra_margin = 0; - object_ID = 0; + object_id = 0; visible = true; lod_begin = 0; @@ -453,7 +457,7 @@ public: virtual void instance_set_scenario(RID p_instance, RID p_scenario); // from can be mesh, light, poly, area and portal so far. virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); virtual void instance_set_transform(RID p_instance, const Transform &p_transform); - virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_ID); + virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id); virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight); virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material); virtual void instance_set_visible(RID p_instance, bool p_visible); diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 2c6709662f..b7c54caffd 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -35,6 +35,43 @@ #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()) { @@ -174,17 +205,13 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E //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; @@ -276,17 +295,27 @@ void VisualServerViewport::draw_viewports() { if (vp->use_arvr && arvr_interface.is_valid()) { // override our size, make sure it matches our required size - Size2 size = arvr_interface->get_render_targetsize(); - VSG::storage->render_target_set_size(vp->render_target, size.x, size.y); + vp->size = arvr_interface->get_render_targetsize(); + VSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y); // 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); @@ -313,7 +343,7 @@ void VisualServerViewport::draw_viewports() { vp->render_info[VS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME); vp->render_info[VS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_DRAW_CALLS_IN_FRAME); - if (vp->viewport_to_screen_rect != Rect2()) { + if (vp->viewport_to_screen_rect != Rect2() && (!vp->viewport_render_direct_to_screen || !VSG::rasterizer->is_low_end())) { //copy to screen if set as such VSG::rasterizer->set_current_render_target(RID()); VSG::rasterizer->blit_render_target_to_screen(vp->render_target, vp->viewport_to_screen_rect, vp->viewport_to_screen); @@ -338,6 +368,7 @@ RID VisualServerViewport::viewport_create() { viewport->hide_canvas = false; viewport->render_target = VSG::storage->render_target_create(); viewport->shadow_atlas = VSG::scene_render->shadow_atlas_create(); + viewport->viewport_render_direct_to_screen = false; return rid; } @@ -394,14 +425,55 @@ void VisualServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); + // If using GLES2 we can optimize this operation by rendering directly to system_fbo + // instead of rendering to fbo and copying to system_fbo after + if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { + + VSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y); + VSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y); + } + viewport->viewport_to_screen_rect = p_rect; viewport->viewport_to_screen = p_screen; } + +void VisualServerViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) { + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + if (p_enable == viewport->viewport_render_direct_to_screen) + return; + + // if disabled, reset render_target size and position + if (!p_enable) { + + VSG::storage->render_target_set_position(viewport->render_target, 0, 0); + VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); + } + + VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable); + viewport->viewport_render_direct_to_screen = p_enable; + + // if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unneccesary buffer allocation + if (VSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) { + + VSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y); + VSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y); + } +} + void VisualServerViewport::viewport_detach(RID p_viewport) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); + // if render_direct_to_screen was used, reset size and position + if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { + + VSG::storage->render_target_set_position(viewport->render_target, 0, 0); + VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); + } + viewport->viewport_to_screen_rect = Rect2(); viewport->viewport_to_screen = 0; } diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h index 5176551540..43bbcb66c3 100644 --- a/servers/visual/visual_server_viewport.h +++ b/servers/visual/visual_server_viewport.h @@ -58,6 +58,7 @@ public: int viewport_to_screen; Rect2 viewport_to_screen_rect; + bool viewport_render_direct_to_screen; bool hide_scenario; bool hide_canvas; @@ -147,6 +148,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: @@ -157,6 +159,7 @@ public: void viewport_set_size(RID p_viewport, int p_width, int p_height); void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), int p_screen = 0); + void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable); void viewport_detach(RID p_viewport); void viewport_set_active(RID p_viewport, bool p_active); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index c6da6799a5..cd24deb60c 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -248,6 +248,7 @@ public: FUNC2(light_set_negative, RID, bool) FUNC2(light_set_cull_mask, RID, uint32_t) FUNC2(light_set_reverse_cull_face_mode, RID, bool) + FUNC2(light_set_use_gi, RID, bool) FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode) FUNC2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail) @@ -360,6 +361,7 @@ public: FUNCRID(camera) FUNC4(camera_set_perspective, RID, float, float, float) FUNC4(camera_set_orthogonal, RID, float, float, float) + FUNC5(camera_set_frustum, RID, float, Vector2, float, float) FUNC2(camera_set_transform, RID, const Transform &) FUNC2(camera_set_cull_mask, RID, uint32_t) FUNC2(camera_set_environment, RID, RID) @@ -379,6 +381,7 @@ public: FUNC2(viewport_set_clear_mode, RID, ViewportClearMode) FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int) + FUNC2(viewport_set_render_direct_to_screen, RID, bool) FUNC1(viewport_detach, RID) FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode) @@ -487,6 +490,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) @@ -516,7 +521,7 @@ public: FUNC7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID) FUNC7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool) FUNC10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID) - FUNC4(canvas_item_add_mesh, RID, const RID &, RID, RID) + FUNC6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID) FUNC4(canvas_item_add_multimesh, RID, RID, RID, RID) FUNC4(canvas_item_add_particles, RID, RID, RID, RID) FUNC2(canvas_item_add_set_transform, RID, const Transform2D &) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 19c6106502..0fe00ad61a 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1780,6 +1780,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("light_set_negative", "light", "enable"), &VisualServer::light_set_negative); ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &VisualServer::light_set_cull_mask); ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &VisualServer::light_set_reverse_cull_face_mode); + ClassDB::bind_method(D_METHOD("light_set_use_gi", "light", "enabled"), &VisualServer::light_set_use_gi); ClassDB::bind_method(D_METHOD("light_omni_set_shadow_mode", "light", "mode"), &VisualServer::light_omni_set_shadow_mode); ClassDB::bind_method(D_METHOD("light_omni_set_shadow_detail", "light", "detail"), &VisualServer::light_omni_set_shadow_detail); @@ -1863,6 +1864,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("camera_create"), &VisualServer::camera_create); ClassDB::bind_method(D_METHOD("camera_set_perspective", "camera", "fovy_degrees", "z_near", "z_far"), &VisualServer::camera_set_perspective); ClassDB::bind_method(D_METHOD("camera_set_orthogonal", "camera", "size", "z_near", "z_far"), &VisualServer::camera_set_orthogonal); + ClassDB::bind_method(D_METHOD("camera_set_frustum", "camera", "size", "offset", "z_near", "z_far"), &VisualServer::camera_set_frustum); ClassDB::bind_method(D_METHOD("camera_set_transform", "camera", "transform"), &VisualServer::camera_set_transform); ClassDB::bind_method(D_METHOD("camera_set_cull_mask", "camera", "layers"), &VisualServer::camera_set_cull_mask); ClassDB::bind_method(D_METHOD("camera_set_environment", "camera", "env"), &VisualServer::camera_set_environment); @@ -1874,6 +1876,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &VisualServer::viewport_set_active); ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &VisualServer::viewport_set_parent_viewport); ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &VisualServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &VisualServer::viewport_set_render_direct_to_screen); ClassDB::bind_method(D_METHOD("viewport_detach", "viewport"), &VisualServer::viewport_detach); ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &VisualServer::viewport_set_update_mode); ClassDB::bind_method(D_METHOD("viewport_set_vflip", "viewport", "enabled"), &VisualServer::viewport_set_vflip); diff --git a/servers/visual_server.h b/servers/visual_server.h index 63ddc3328a..01be996bfc 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -435,6 +435,7 @@ public: virtual void light_set_negative(RID p_light, bool p_enable) = 0; virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; + virtual void light_set_use_gi(RID p_light, bool p_enable) = 0; // omni light enum LightOmniShadowMode { @@ -584,6 +585,7 @@ public: virtual RID camera_create() = 0; virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0; virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0; + virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0; virtual void camera_set_transform(RID p_camera, const Transform &p_transform) = 0; virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0; virtual void camera_set_environment(RID p_camera, RID p_env) = 0; @@ -608,6 +610,7 @@ public: virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0; virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), int p_screen = 0) = 0; + virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0; virtual void viewport_detach(RID p_viewport) = 0; enum ViewportUpdateMode { @@ -812,7 +815,7 @@ public: virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0; // from can be mesh, light, poly, area and portal so far. virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0; virtual void instance_set_transform(RID p_instance, const Transform &p_transform) = 0; - virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_ID) = 0; + virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0; virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0; virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0; virtual void instance_set_visible(RID p_instance, bool p_visible) = 0; @@ -860,6 +863,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; @@ -895,7 +901,7 @@ public: virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()) = 0; virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false) = 0; virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()) = 0; - virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0; + virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID()) = 0; virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0; virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map) = 0; virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0; |